• 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 // Utility functions for VtsKernelEncryptionTest.
18 
19 #include <algorithm>
20 #include <fstream>
21 
22 #include <LzmaLib.h>
23 #include <android-base/parseint.h>
24 #include <android-base/properties.h>
25 #include <android-base/strings.h>
26 #include <android-base/unique_fd.h>
27 #include <errno.h>
28 #include <ext4_utils/ext4.h>
29 #include <ext4_utils/ext4_sb.h>
30 #include <ext4_utils/ext4_utils.h>
31 #include <gtest/gtest.h>
32 #include <libdm/dm.h>
33 #include <linux/magic.h>
34 #include <mntent.h>
35 #include <openssl/cmac.h>
36 #include <sys/statvfs.h>
37 #include <unistd.h>
38 
39 #include "Keymaster.h"
40 #include "vts_kernel_encryption.h"
41 
42 using android::base::ParseInt;
43 using android::base::Split;
44 using android::base::StartsWith;
45 using namespace android::dm;
46 
47 namespace android {
48 namespace kernel {
49 
50 enum KdfVariant {
51   KDF_VARIANT_V1 = 0,
52   KDF_VARIANT_LEGACY = 1,
53   KDF_VARIANT_REARRANGED = 2,
54   KDF_VARIANT_COUNT,
55 };
56 
57 // Context in fixed input string comprises of software provided context,
58 // padding to eight bytes (if required) and the key policy.
59 static const std::vector<std::vector<uint8_t>> HwWrappedEncryptionKeyContexts =
60     {
61         // "v1"
62         {'i',  'n',  'l',  'i',  'n',  'e',  ' ',  'e',  'n', 'c', 'r', 'y',
63          'p',  't',  'i',  'o',  'n',  ' ',  'k',  'e',  'y', 0x0, 0x0, 0x0,
64          0x00, 0x00, 0x00, 0x02, 0x43, 0x00, 0x82, 0x50, 0x0, 0x0, 0x0, 0x0},
65         // Below for "legacy && kdf tied to Trusted Execution
66         // Environment(TEE)".
67         // Where as above caters ( "all latest targets" || ("legacy && kdf
68         // not tied to TEE)).
69         // "legacykdf"
70         {'i',  'n',  'l',  'i',  'n',  'e',  ' ',  'e',  'n', 'c', 'r', 'y',
71          'p',  't',  'i',  'o',  'n',  ' ',  'k',  'e',  'y', 0x0, 0x0, 0x0,
72          0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x82, 0x18, 0x0, 0x0, 0x0, 0x0},
73         // "rearranged"
74         {
75             'i',  'n',  'l',  'i',  'n',  'e',  ' ',  'e',  'n',
76             'c',  'r',  'y',  'p',  't',  'i',  'o',  'n',  ' ',
77             's',  't',  'o',  'r',  'a',  'g',  'e',  'k',  'e',
78             'y',  ' ',  'c',  't',  'x',  0x00, 0x00, 0x00, 0x00,
79             0x00, 0x10, 0x70, 0x18, 0x72, 0x00, 0x00, 0x00, 0x00,
80         }};
81 
82 static const std::vector<std::vector<uint8_t>> HwWrappedEncryptionKeyLabels = {
83     // "v1"
84     {0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
85     // "legacykdf"
86     {0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
87     // "rearranged"
88     {
89         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91     },
92 };
93 
94 static const std::vector<std::vector<uint8_t>> SwSecretContexts = {
95     // "v1"
96     {
97         'r',  'a',  'w',  ' ',  's', 'e', 'c',  'r',  'e',  't',
98         0x0,  0x0,  0x0,  0x0,  0x0, 0x0, 0x00, 0x00, 0x00, 0x02,
99         0x17, 0x00, 0x80, 0x50, 0x0, 0x0, 0x0,  0x0,
100     },
101     // "legacykdf"
102     {
103         'r',  'a',  'w',  ' ',  's', 'e', 'c',  'r',  'e',  't',
104         0x0,  0x0,  0x0,  0x0,  0x0, 0x0, 0x00, 0x00, 0x00, 0x02,
105         0x17, 0x00, 0x80, 0x50, 0x0, 0x0, 0x0,  0x0,
106     },
107     // "rearranged"
108     {
109         'd', 'e', 'r', 'i', 'v', 'e', ' ', 'r', 'a', 'w', ' ',
110         's', 'e', 'c', 'r', 'e', 't', ' ', 'c', 'o', 'n', 't',
111         'e', 'x', 't', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
112     }};
113 
114 static const std::vector<std::vector<uint8_t>> SwSecretLabels = {
115     // "v1"
116     {0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
117     // "legacykdf"
118     {0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
119     // "rearranged"
120     {
121         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123     },
124 };
125 
GetKdfVariantId(KdfVariant * kdf_id)126 static bool GetKdfVariantId(KdfVariant *kdf_id) {
127   std::string kdf =
128       android::base::GetProperty("ro.crypto.hw_wrapped_keys.kdf", "v1");
129 
130   if (kdf == "v1") {
131     *kdf_id = KDF_VARIANT_V1;
132   } else if (kdf == "legacykdf") {
133     *kdf_id = KDF_VARIANT_LEGACY;
134   } else if (kdf == "rearranged") {
135     *kdf_id = KDF_VARIANT_REARRANGED;
136   } else {
137     ADD_FAILURE() << "Unknown KDF: " << kdf;
138     return false;
139   }
140   return true;
141 }
142 
GetKdfContextLabelByKdfId(KdfVariant kdf_id,std::vector<uint8_t> * ctx,std::vector<uint8_t> * lbl)143 static void GetKdfContextLabelByKdfId(KdfVariant kdf_id,
144                                       std::vector<uint8_t> *ctx,
145                                       std::vector<uint8_t> *lbl) {
146   *ctx = HwWrappedEncryptionKeyContexts[kdf_id];
147   *lbl = HwWrappedEncryptionKeyLabels[kdf_id];
148 }
149 
GetSwSecretContextLabelByKdfId(KdfVariant kdf_id,std::vector<uint8_t> * ctx,std::vector<uint8_t> * lbl)150 static void GetSwSecretContextLabelByKdfId(KdfVariant kdf_id,
151                                            std::vector<uint8_t> *ctx,
152                                            std::vector<uint8_t> *lbl) {
153   *ctx = SwSecretContexts[kdf_id];
154   *lbl = SwSecretLabels[kdf_id];
155 }
156 
157 // Offset in bytes to the filesystem superblock, relative to the beginning of
158 // the block device
159 constexpr int kExt4SuperBlockOffset = 1024;
160 constexpr int kF2fsSuperBlockOffset = 1024;
161 
162 // For F2FS: the offsets in bytes to the filesystem magic number and filesystem
163 // UUID, relative to the beginning of the block device
164 constexpr int kF2fsMagicOffset = kF2fsSuperBlockOffset;
165 constexpr int kF2fsUuidOffset = kF2fsSuperBlockOffset + 108;
166 
167 // hw-wrapped key size in bytes
168 constexpr int kHwWrappedKeySize = 32;
169 
Errno()170 std::string Errno() { return std::string(": ") + strerror(errno); }
171 
172 // Recursively deletes the file or directory at |path|, if it exists.
DeleteRecursively(const std::string & path)173 void DeleteRecursively(const std::string &path) {
174   if (unlink(path.c_str()) == 0 || errno == ENOENT) return;
175   ASSERT_EQ(EISDIR, errno) << "Failed to unlink " << path << Errno();
176 
177   std::unique_ptr<DIR, int (*)(DIR *)> dirp(opendir(path.c_str()), closedir);
178   // If the directory was assigned an encryption policy that the kernel lacks
179   // crypto API support for, then opening it will fail, and it will be empty.
180   // So, we have to allow opening the directory to fail.
181   if (dirp != nullptr) {
182     struct dirent *entry;
183     while ((entry = readdir(dirp.get())) != nullptr) {
184       std::string filename(entry->d_name);
185       if (filename != "." && filename != "..")
186         DeleteRecursively(path + "/" + filename);
187     }
188   }
189   ASSERT_EQ(0, rmdir(path.c_str()))
190       << "Failed to remove directory " << path << Errno();
191 }
192 
193 // Generates some "random" bytes.  Not secure; this is for testing only.
RandomBytesForTesting(std::vector<uint8_t> & bytes)194 void RandomBytesForTesting(std::vector<uint8_t> &bytes) {
195   for (size_t i = 0; i < bytes.size(); i++) {
196     bytes[i] = rand();
197   }
198 }
199 
200 // Generates a "random" key.  Not secure; this is for testing only.
GenerateTestKey(size_t size)201 std::vector<uint8_t> GenerateTestKey(size_t size) {
202   std::vector<uint8_t> key(size);
203   RandomBytesForTesting(key);
204   return key;
205 }
206 
BytesToHex(const std::vector<uint8_t> & bytes)207 std::string BytesToHex(const std::vector<uint8_t> &bytes) {
208   std::ostringstream o;
209   for (uint8_t b : bytes) {
210     o << std::hex << std::setw(2) << std::setfill('0') << (int)b;
211   }
212   return o.str();
213 }
214 
GetFirstApiLevel(int * first_api_level)215 bool GetFirstApiLevel(int *first_api_level) {
216   *first_api_level =
217       android::base::GetIntProperty("ro.product.first_api_level", 0);
218   if (*first_api_level == 0) {
219     ADD_FAILURE() << "ro.product.first_api_level is unset";
220     return false;
221   }
222   GTEST_LOG_(INFO) << "ro.product.first_api_level = " << *first_api_level;
223   return true;
224 }
225 
226 // Gets the UUID of the filesystem that uses |fs_blk_device| as its main block
227 // device. |fs_type| gives the filesystem type.
228 //
229 // Unfortunately there's no kernel API to get the UUID; instead we have to read
230 // it from the filesystem superblock.
GetFilesystemUuid(const std::string & fs_blk_device,const std::string & fs_type,FilesystemUuid * fs_uuid)231 static bool GetFilesystemUuid(const std::string &fs_blk_device,
232                               const std::string &fs_type,
233                               FilesystemUuid *fs_uuid) {
234   android::base::unique_fd fd(
235       open(fs_blk_device.c_str(), O_RDONLY | O_CLOEXEC));
236   if (fd < 0) {
237     ADD_FAILURE() << "Failed to open fs block device " << fs_blk_device
238                   << Errno();
239     return false;
240   }
241 
242   if (fs_type == "ext4") {
243     struct ext4_super_block sb;
244 
245     if (pread(fd, &sb, sizeof(sb), kExt4SuperBlockOffset) != sizeof(sb)) {
246       ADD_FAILURE() << "Error reading ext4 superblock from " << fs_blk_device
247                     << Errno();
248       return false;
249     }
250     if (sb.s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {
251       ADD_FAILURE() << "Failed to find ext4 superblock on " << fs_blk_device;
252       return false;
253     }
254     static_assert(sizeof(sb.s_uuid) == kFilesystemUuidSize);
255     memcpy(fs_uuid->bytes, sb.s_uuid, kFilesystemUuidSize);
256   } else if (fs_type == "f2fs") {
257     // Android doesn't have an f2fs equivalent of libext4_utils, so we have to
258     // hard-code the offset to the magic number and UUID.
259 
260     __le32 magic;
261     if (pread(fd, &magic, sizeof(magic), kF2fsMagicOffset) != sizeof(magic)) {
262       ADD_FAILURE() << "Error reading f2fs superblock from " << fs_blk_device
263                     << Errno();
264       return false;
265     }
266     if (magic != cpu_to_le32(F2FS_SUPER_MAGIC)) {
267       ADD_FAILURE() << "Failed to find f2fs superblock on " << fs_blk_device;
268       return false;
269     }
270     if (pread(fd, fs_uuid->bytes, kFilesystemUuidSize, kF2fsUuidOffset) !=
271         kFilesystemUuidSize) {
272       ADD_FAILURE() << "Failed to read f2fs filesystem UUID from "
273                     << fs_blk_device << Errno();
274       return false;
275     }
276   } else {
277     ADD_FAILURE() << "Unknown filesystem type " << fs_type;
278     return false;
279   }
280   return true;
281 }
282 
283 // Gets the raw block device corresponding to |fs_blk_device| that is one of a
284 // filesystem's mounted block devices. By "raw block device" we mean a block
285 // device from which we can read the encrypted file contents and filesystem
286 // metadata.  When metadata encryption is disabled, this is simply
287 // |fs_blk_device|.  When metadata encryption is enabled, then |fs_blk_device|
288 // is a dm-default-key device and the "raw block device" is the parent of this
289 // dm-default-key device.
290 //
291 // We don't just use the block device listed in the fstab, because (a) it can be
292 // a logical partition name which needs extra code to map to a block device, and
293 // (b) due to block-level checkpointing, there can be a dm-bow device between
294 // the fstab partition and dm-default-key.  dm-bow can remap sectors, but for
295 // encryption testing we don't want any sector remapping.  So the correct block
296 // device to read ciphertext from is the one directly underneath dm-default-key.
GetRawBlockDevice(const std::string & fs_blk_device,std::string * raw_blk_device)297 static bool GetRawBlockDevice(const std::string &fs_blk_device,
298                               std::string *raw_blk_device) {
299   DeviceMapper &dm = DeviceMapper::Instance();
300 
301   if (!dm.IsDmBlockDevice(fs_blk_device)) {
302     GTEST_LOG_(INFO)
303         << fs_blk_device
304         << " is not a device-mapper device; metadata encryption is disabled";
305     *raw_blk_device = fs_blk_device;
306     return true;
307   }
308   const std::optional<std::string> name =
309       dm.GetDmDeviceNameByPath(fs_blk_device);
310   if (!name) {
311     ADD_FAILURE() << "Failed to get name of device-mapper device "
312                   << fs_blk_device;
313     return false;
314   }
315 
316   std::vector<DeviceMapper::TargetInfo> table;
317   if (!dm.GetTableInfo(*name, &table)) {
318     ADD_FAILURE() << "Failed to get table of device-mapper device " << *name;
319     return false;
320   }
321   if (table.size() != 1) {
322     GTEST_LOG_(INFO) << fs_blk_device
323                      << " has multiple device-mapper targets; assuming "
324                         "metadata encryption is disabled";
325     *raw_blk_device = fs_blk_device;
326     return true;
327   }
328   const std::string target_type = dm.GetTargetType(table[0].spec);
329   if (target_type != "default-key") {
330     GTEST_LOG_(INFO) << fs_blk_device << " is a dm-" << target_type
331                      << " device, not dm-default-key; assuming metadata "
332                         "encryption is disabled";
333     *raw_blk_device = fs_blk_device;
334     return true;
335   }
336   std::optional<std::string> parent =
337       dm.GetParentBlockDeviceByPath(fs_blk_device);
338   if (!parent) {
339     ADD_FAILURE() << "Failed to get parent of dm-default-key device " << *name;
340     return false;
341   }
342   *raw_blk_device = *parent;
343   return true;
344 }
345 
346 // Gets information about a filesystem's block devices
GetFsBlockDeviceList(FilesystemInfo * fs_info,const std::string & mnt_fsname)347 static bool GetFsBlockDeviceList(FilesystemInfo *fs_info,
348                                  const std::string &mnt_fsname) {
349   // Add a default block device
350   DiskMapEntry map_entry;
351   map_entry.start_blkaddr = 0;
352   map_entry.end_blkaddr = INT64_MAX - 1;
353   map_entry.fs_blk_device = mnt_fsname;
354 
355   if (!GetRawBlockDevice(map_entry.fs_blk_device, &map_entry.raw_blk_device)) {
356     ADD_FAILURE() << "Broken block device path of the default disk";
357     return false;
358   }
359   fs_info->disk_map.push_back(map_entry);
360 
361   if (fs_info->type != "f2fs") return true;
362 
363   // This requires a kernel patch, f238eff95f48 ("f2fs: add a proc entry show
364   // disk layout"), merged in v6.9
365   static constexpr std::string_view kDevBlockPrefix("/dev/block/");
366   const std::string proc_path = "/proc/fs/f2fs/" +
367                                 mnt_fsname.substr(kDevBlockPrefix.length()) +
368                                 "/disk_map";
369   std::ifstream proc_fs(proc_path.c_str());
370   if (!proc_fs.is_open()) {
371     GTEST_LOG_(INFO) << proc_path
372                      << " does not exist (expected on pre-6.9 kernels)";
373     return true;
374   }
375 
376   std::string line;
377   bool first_device = true;
378   while (std::getline(proc_fs, line)) {
379     if (!android::base::StartsWith(line, "Disk: ")) {
380       continue;
381     }
382     if (first_device) {
383       fs_info->disk_map.erase(fs_info->disk_map.begin());
384       first_device = false;
385     }
386     DiskMapEntry map_entry;
387     std::vector<std::string> data = Split(line, "\t ");
388     if (!ParseInt(data[3], &map_entry.start_blkaddr)) {
389       ADD_FAILURE() << "Broken first block address in the address range";
390       return false;
391     }
392     if (!ParseInt(data[5], &map_entry.end_blkaddr)) {
393       ADD_FAILURE() << "Broken last block address in the address range";
394       return false;
395     }
396     map_entry.fs_blk_device = data[7];
397     if (!GetRawBlockDevice(map_entry.fs_blk_device,
398                            &map_entry.raw_blk_device)) {
399       ADD_FAILURE() << "Broken block device path in the disk map entry";
400       return false;
401     }
402     fs_info->disk_map.push_back(map_entry);
403   }
404   return true;
405 }
406 
407 // Gets the block device list and type of the filesystem mounted on
408 // |mountpoint|. The block device list has all the block device information
409 // along with the address space ranges configured by the mounted filesystem.
GetFsBlockDeviceListAndType(const std::string & mountpoint,FilesystemInfo * fs_info)410 static bool GetFsBlockDeviceListAndType(const std::string &mountpoint,
411                                         FilesystemInfo *fs_info) {
412   std::unique_ptr<FILE, int (*)(FILE *)> mnts(setmntent("/proc/mounts", "re"),
413                                               endmntent);
414   if (!mnts) {
415     ADD_FAILURE() << "Failed to open /proc/mounts" << Errno();
416     return false;
417   }
418   struct mntent *mnt;
419   while ((mnt = getmntent(mnts.get())) != nullptr) {
420     if (mnt->mnt_dir == mountpoint) {
421       fs_info->type = mnt->mnt_type;
422       return GetFsBlockDeviceList(fs_info, mnt->mnt_fsname);
423     }
424   }
425   ADD_FAILURE() << "No /proc/mounts entry found for " << mountpoint;
426   return false;
427 }
428 
429 // Gets information about the filesystem mounted on |mountpoint|.
GetFilesystemInfo(const std::string & mountpoint,FilesystemInfo * fs_info)430 bool GetFilesystemInfo(const std::string &mountpoint, FilesystemInfo *fs_info) {
431   if (!GetFsBlockDeviceListAndType(mountpoint, fs_info)) return false;
432 
433   // This disk_map[0] always indicates the main block device which the
434   // filesystem contains its superblock.
435   if (!GetFilesystemUuid(fs_info->disk_map[0].fs_blk_device, fs_info->type,
436                          &fs_info->uuid))
437     return false;
438 
439   struct statvfs stbuf;
440   if (statvfs(mountpoint.c_str(), &stbuf) != 0) {
441     ADD_FAILURE() << "Failed to statvfs " << mountpoint << Errno();
442     return false;
443   }
444   fs_info->block_size = stbuf.f_bsize;
445 
446   GTEST_LOG_(INFO) << "Filesystem mounted on " << mountpoint
447                    << " has type: " << fs_info->type
448                    << ", block_size: " << fs_info->block_size
449                    << ", uuid: " << BytesToHex(fs_info->uuid.bytes);
450   for (const DiskMapEntry &map_entry : fs_info->disk_map) {
451     GTEST_LOG_(INFO) << "Block device: " << map_entry.fs_blk_device << " ("
452                      << map_entry.raw_blk_device << ") ranging from "
453                      << map_entry.start_blkaddr << " to "
454                      << map_entry.end_blkaddr;
455   }
456   return true;
457 }
458 
459 // Returns true if the given data seems to be random.
460 //
461 // Check compressibility rather than byte frequencies.  Compressibility is a
462 // stronger test since it also detects repetitions.
463 //
464 // To check compressibility, use LZMA rather than DEFLATE/zlib/gzip because LZMA
465 // compression is stronger and supports a much larger dictionary.  DEFLATE is
466 // limited to a 32 KiB dictionary.  So, data repeating after 32 KiB (or more)
467 // would not be detected with DEFLATE.  But LZMA can detect it.
VerifyDataRandomness(const std::vector<uint8_t> & bytes)468 bool VerifyDataRandomness(const std::vector<uint8_t> &bytes) {
469   // To avoid flakiness, allow the data to be compressed a tiny bit by chance.
470   // There is at most a 2^-32 chance that random data can be compressed to be 4
471   // bytes shorter.  In practice it's even lower due to compression overhead.
472   size_t destLen = bytes.size() - std::min<size_t>(4, bytes.size());
473   std::vector<uint8_t> dest(destLen);
474   uint8_t outProps[LZMA_PROPS_SIZE];
475   size_t outPropsSize = LZMA_PROPS_SIZE;
476   int ret;
477 
478   ret = LzmaCompress(dest.data(), &destLen, bytes.data(), bytes.size(),
479                      outProps, &outPropsSize,
480                      6,               // compression level (0 <= level <= 9)
481                      bytes.size(),    // dictionary size
482                      -1, -1, -1, -1,  // lc, lp, bp, fb (-1 selects the default)
483                      1);              // number of threads
484 
485   if (ret == SZ_ERROR_OUTPUT_EOF) return true;  // incompressible
486 
487   if (ret == SZ_OK) {
488     ADD_FAILURE() << "Data is not random!  Compressed " << bytes.size()
489                   << " to " << destLen << " bytes";
490   } else {
491     ADD_FAILURE() << "LZMA compression error: ret=" << ret;
492   }
493   return false;
494 }
495 
TryPrepareHwWrappedKey(Keymaster & keymaster,const std::string & master_key_string,std::string * exported_key_string,bool rollback_resistance)496 static bool TryPrepareHwWrappedKey(Keymaster &keymaster,
497                                    const std::string &master_key_string,
498                                    std::string *exported_key_string,
499                                    bool rollback_resistance) {
500   // This key is used to drive a CMAC-based KDF
501   auto paramBuilder =
502       km::AuthorizationSetBuilder().AesEncryptionKey(kHwWrappedKeySize * 8);
503   if (rollback_resistance) {
504     paramBuilder.Authorization(km::TAG_ROLLBACK_RESISTANCE);
505   }
506   paramBuilder.Authorization(km::TAG_STORAGE_KEY);
507 
508   std::string wrapped_key_blob;
509   if (keymaster.importKey(paramBuilder, master_key_string, &wrapped_key_blob) &&
510       keymaster.exportKey(wrapped_key_blob, exported_key_string)) {
511     return true;
512   }
513   // It's fine for Keymaster not to support hardware-wrapped keys, but
514   // if generateKey works, importKey must too.
515   if (keymaster.generateKey(paramBuilder, &wrapped_key_blob) &&
516       keymaster.exportKey(wrapped_key_blob, exported_key_string)) {
517     ADD_FAILURE() << "generateKey succeeded but importKey failed";
518   }
519   return false;
520 }
521 
CreateHwWrappedKey(std::vector<uint8_t> * master_key,std::vector<uint8_t> * exported_key)522 bool CreateHwWrappedKey(std::vector<uint8_t> *master_key,
523                         std::vector<uint8_t> *exported_key) {
524   *master_key = GenerateTestKey(kHwWrappedKeySize);
525 
526   Keymaster keymaster;
527   if (!keymaster) {
528     ADD_FAILURE() << "Unable to find keymaster";
529     return false;
530   }
531   std::string master_key_string(master_key->begin(), master_key->end());
532   std::string exported_key_string;
533   // Make two attempts to create a key, first with and then without
534   // rollback resistance.
535   if (TryPrepareHwWrappedKey(keymaster, master_key_string, &exported_key_string,
536                              true) ||
537       TryPrepareHwWrappedKey(keymaster, master_key_string, &exported_key_string,
538                              false)) {
539     exported_key->assign(exported_key_string.begin(),
540                          exported_key_string.end());
541     return true;
542   }
543   GTEST_LOG_(INFO) << "Skipping test because device doesn't support "
544                       "hardware-wrapped keys";
545   return false;
546 }
547 
PushBigEndian32(uint32_t val,std::vector<uint8_t> * vec)548 static void PushBigEndian32(uint32_t val, std::vector<uint8_t> *vec) {
549   for (int i = 24; i >= 0; i -= 8) {
550     vec->push_back((val >> i) & 0xFF);
551   }
552 }
553 
RearrangeFixedInputString(KdfVariant kdf_id,std::vector<uint8_t> * fixed_input_string)554 static void RearrangeFixedInputString(
555     KdfVariant kdf_id, std::vector<uint8_t> *fixed_input_string) {
556   if (kdf_id != KDF_VARIANT_REARRANGED) {
557     return;
558   }
559 
560   // Rearrange the fixed-input string, reversing the order that the blocks are
561   // processed:
562   // ABCD-EFGH-IJKL-MNO
563   // into
564   // LMNO-HIJK-DEFG-ABC
565   size_t len = fixed_input_string->size();
566   std::vector<uint8_t> tmp(len);
567   for (size_t j = 0; j < len; j += kAesBlockSize) {
568     size_t to_copy = std::min((size_t)kAesBlockSize, len - j);
569     std::copy(fixed_input_string->cbegin() + len - j - to_copy,
570               fixed_input_string->cbegin() + len - j, tmp.begin() + j);
571   }
572   std::copy(tmp.cbegin(), tmp.cend(), fixed_input_string->begin());
573 }
574 
GetFixedInputString(KdfVariant kdf_id,uint32_t counter,const std::vector<uint8_t> & label,const std::vector<uint8_t> & context,uint32_t derived_key_len,std::vector<uint8_t> * fixed_input_string)575 static void GetFixedInputString(KdfVariant kdf_id, uint32_t counter,
576                                 const std::vector<uint8_t> &label,
577                                 const std::vector<uint8_t> &context,
578                                 uint32_t derived_key_len,
579                                 std::vector<uint8_t> *fixed_input_string) {
580   PushBigEndian32(counter, fixed_input_string);
581   fixed_input_string->insert(fixed_input_string->end(), label.begin(),
582                              label.end());
583   fixed_input_string->push_back(0);
584   fixed_input_string->insert(fixed_input_string->end(), context.begin(),
585                              context.end());
586   PushBigEndian32(derived_key_len, fixed_input_string);
587 
588   // If applicable, rearrange the fixed-input string
589   RearrangeFixedInputString(kdf_id, fixed_input_string);
590 }
591 
AesCmacKdfHelper(KdfVariant kdf_id,const std::vector<uint8_t> & key,const std::vector<uint8_t> & label,const std::vector<uint8_t> & context,uint32_t output_key_size,std::vector<uint8_t> * output_data)592 static bool AesCmacKdfHelper(KdfVariant kdf_id, const std::vector<uint8_t> &key,
593                              const std::vector<uint8_t> &label,
594                              const std::vector<uint8_t> &context,
595                              uint32_t output_key_size,
596                              std::vector<uint8_t> *output_data) {
597   GTEST_LOG_(INFO) << "KDF ID = " << kdf_id;
598   output_data->resize(output_key_size);
599   for (size_t count = 0; count < (output_key_size / kAesBlockSize); count++) {
600     std::vector<uint8_t> fixed_input_string;
601     GetFixedInputString(kdf_id, count + 1, label, context,
602                         (output_key_size * 8), &fixed_input_string);
603     GTEST_LOG_(INFO) << "Fixed Input (block: " << count
604                      << "): " << BytesToHex(fixed_input_string);
605     if (!AES_CMAC(output_data->data() + (kAesBlockSize * count), key.data(),
606                   key.size(), fixed_input_string.data(),
607                   fixed_input_string.size())) {
608       ADD_FAILURE()
609           << "AES_CMAC failed while deriving subkey from HW wrapped key";
610       return false;
611     }
612   }
613   return true;
614 }
615 
DeriveHwWrappedEncryptionKeyByKdfId(KdfVariant kdf_id,const std::vector<uint8_t> & master_key,std::vector<uint8_t> * enc_key)616 static bool DeriveHwWrappedEncryptionKeyByKdfId(
617     KdfVariant kdf_id, const std::vector<uint8_t> &master_key,
618     std::vector<uint8_t> *enc_key) {
619   std::vector<uint8_t> ctx;
620   std::vector<uint8_t> label;
621   GetKdfContextLabelByKdfId(kdf_id, &ctx, &label);
622   return AesCmacKdfHelper(kdf_id, master_key, label, ctx, kAes256XtsKeySize,
623                           enc_key);
624 }
625 
DeriveHwWrappedEncryptionKey(const std::vector<uint8_t> & master_key,std::vector<uint8_t> * enc_key)626 bool DeriveHwWrappedEncryptionKey(const std::vector<uint8_t> &master_key,
627                                   std::vector<uint8_t> *enc_key) {
628   KdfVariant kdf_id;
629   if (!GetKdfVariantId(&kdf_id)) {
630     return false;
631   }
632   return DeriveHwWrappedEncryptionKeyByKdfId(kdf_id, master_key, enc_key);
633 }
634 
DeriveHwWrappedRawSecretByKdfId(KdfVariant kdf_id,const std::vector<uint8_t> & master_key,std::vector<uint8_t> * secret)635 static bool DeriveHwWrappedRawSecretByKdfId(
636     KdfVariant kdf_id, const std::vector<uint8_t> &master_key,
637     std::vector<uint8_t> *secret) {
638   std::vector<uint8_t> ctx;
639   std::vector<uint8_t> label;
640   GetSwSecretContextLabelByKdfId(kdf_id, &ctx, &label);
641   return AesCmacKdfHelper(kdf_id, master_key, label, ctx, kAes256KeySize,
642                           secret);
643 }
644 
DeriveHwWrappedRawSecret(const std::vector<uint8_t> & master_key,std::vector<uint8_t> * secret)645 bool DeriveHwWrappedRawSecret(const std::vector<uint8_t> &master_key,
646                               std::vector<uint8_t> *secret) {
647   KdfVariant kdf_id;
648   if (!GetKdfVariantId(&kdf_id)) {
649     return false;
650   }
651   return DeriveHwWrappedRawSecretByKdfId(kdf_id, master_key, secret);
652 }
653 
TEST(UtilsTest,TestKdfVariants)654 TEST(UtilsTest, TestKdfVariants) {
655   std::vector<KdfVariant> kdf_ids = {
656       KDF_VARIANT_V1,
657       KDF_VARIANT_LEGACY,
658       KDF_VARIANT_REARRANGED,
659   };
660 
661   std::vector<std::vector<uint8_t>> expected_keys = {
662       // "v1"
663       {
664           0xcb, 0xe5, 0xdb, 0x40, 0x21, 0x5a, 0x3d, 0x38, 0x6d, 0x61, 0xe5,
665           0x4e, 0xf2, 0xf8, 0xa7, 0x81, 0x4b, 0x00, 0xba, 0xcf, 0x35, 0xb3,
666           0x16, 0xf8, 0x8e, 0x68, 0xe8, 0x9a, 0x47, 0xab, 0xba, 0xb4, 0x83,
667           0x4c, 0x27, 0xda, 0xc8, 0xa9, 0x1a, 0xe1, 0xc3, 0x30, 0x4f, 0x31,
668           0xb5, 0xf2, 0x20, 0x2c, 0x14, 0x98, 0x96, 0x61, 0xba, 0xfc, 0xcc,
669           0x56, 0xcf, 0x62, 0x12, 0xd8, 0xb1, 0xf7, 0x26, 0x91,
670       },
671       // "legacykdf"
672       {
673           0x63, 0x61, 0xf8, 0x02, 0xb3, 0x7a, 0xa6, 0x4a, 0x07, 0x57, 0x84,
674           0xbe, 0xde, 0x23, 0x41, 0xf1, 0xd9, 0x23, 0x6e, 0x64, 0x6c, 0x70,
675           0x46, 0x0f, 0x15, 0xb3, 0x7c, 0xe5, 0xff, 0x43, 0xa5, 0x4f, 0x15,
676           0xd9, 0x56, 0x93, 0x34, 0x3d, 0x52, 0x8b, 0x67, 0x37, 0x2a, 0x7f,
677           0x38, 0x3e, 0xd8, 0xe7, 0xc4, 0x5e, 0xd0, 0x89, 0x9e, 0x02, 0x82,
678           0x54, 0x53, 0xc9, 0x41, 0x9a, 0xaf, 0xa3, 0x69, 0x5f,
679       },
680       // "rearranged"
681       {
682           0xdb, 0xa0, 0xa6, 0x7e, 0x47, 0x1b, 0xe3, 0x9f, 0xd1, 0xec, 0x28,
683           0x99, 0x45, 0xf5, 0x21, 0x45, 0xdf, 0x12, 0x93, 0x7a, 0x0b, 0x42,
684           0x91, 0x5f, 0x7c, 0x71, 0x1f, 0xeb, 0x47, 0x40, 0x3e, 0x6a, 0xe5,
685           0xb7, 0xb5, 0x29, 0x68, 0xa8, 0xcc, 0x63, 0x5d, 0x10, 0xab, 0x8b,
686           0x87, 0x24, 0xef, 0x5d, 0xec, 0x62, 0x36, 0xd8, 0x1a, 0x1b, 0x38,
687           0x78, 0x08, 0xc4, 0x07, 0xce, 0x01, 0xc5, 0x63, 0x88,
688       },
689   };
690 
691   std::vector<std::vector<uint8_t>> expected_secrets = {
692       // "v1"
693       {
694           0xe2, 0x6f, 0xb1, 0x9b, 0x4f, 0xb6, 0x26, 0x6f, 0xc7, 0xc5, 0xfc,
695           0x96, 0x54, 0xef, 0xad, 0x64, 0x3c, 0xfe, 0xbc, 0x64, 0xc0, 0x97,
696           0x34, 0x11, 0x55, 0x19, 0x55, 0x95, 0xc2, 0x8d, 0x5e, 0xc9,
697       },
698       // "legacykdf"
699       {
700           0xe2, 0x6f, 0xb1, 0x9b, 0x4f, 0xb6, 0x26, 0x6f, 0xc7, 0xc5, 0xfc,
701           0x96, 0x54, 0xef, 0xad, 0x64, 0x3c, 0xfe, 0xbc, 0x64, 0xc0, 0x97,
702           0x34, 0x11, 0x55, 0x19, 0x55, 0x95, 0xc2, 0x8d, 0x5e, 0xc9,
703       },
704       // "rearranged"
705       {
706           0x4e, 0xf0, 0x6e, 0x6a, 0xa9, 0x84, 0x10, 0x46, 0x67, 0x86, 0x3f,
707           0x15, 0x08, 0x7c, 0x12, 0xbb, 0xfb, 0x8e, 0x47, 0x15, 0x14, 0x5b,
708           0xc0, 0x6b, 0x59, 0x82, 0xab, 0xd4, 0x19, 0x83, 0x85, 0xb4,
709       },
710   };
711 
712   ASSERT_EQ(kdf_ids.size(), KDF_VARIANT_COUNT);
713   ASSERT_EQ(expected_keys.size(), KDF_VARIANT_COUNT);
714   ASSERT_EQ(expected_secrets.size(), KDF_VARIANT_COUNT);
715 
716   const std::vector<uint8_t> master_key = {
717       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
718       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
719   };
720 
721   GTEST_LOG_(INFO) << "Master Key: " << BytesToHex(master_key);
722   for (size_t i = 0; i < KDF_VARIANT_COUNT; i++) {
723     std::vector<uint8_t> out_key;
724     EXPECT_TRUE(
725         DeriveHwWrappedEncryptionKeyByKdfId(kdf_ids[i], master_key, &out_key));
726     GTEST_LOG_(INFO) << "Key        (id: " << i << "): " << BytesToHex(out_key);
727     GTEST_LOG_(INFO) << "Exp Key    (id: " << i
728                      << "): " << BytesToHex(expected_keys[i]);
729     EXPECT_EQ(out_key, expected_keys[i]);
730     std::vector<uint8_t> out_sec;
731     EXPECT_TRUE(
732         DeriveHwWrappedRawSecretByKdfId(kdf_ids[i], master_key, &out_sec));
733     GTEST_LOG_(INFO) << "Secret     (id: " << i << "): " << BytesToHex(out_sec);
734     GTEST_LOG_(INFO) << "Exp Secret (id: " << i
735                      << "): " << BytesToHex(expected_secrets[i]);
736     EXPECT_EQ(out_sec, expected_secrets[i]);
737   }
738 }
739 
740 }  // namespace kernel
741 }  // namespace android
742