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