1 /*
2 * Copyright (C) 2019 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 #define LOG_TAG "VtsSecurityAvbTest"
18
19 #include <sys/utsname.h>
20 #include <unistd.h>
21
22 #include <array>
23 #include <list>
24 #include <map>
25 #include <set>
26 #include <tuple>
27 #include <vector>
28
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/properties.h>
32 #include <android-base/result.h>
33 #include <android-base/stringprintf.h>
34 #include <android-base/unique_fd.h>
35 #include <bootimg.h>
36 #include <fs_avb/fs_avb_util.h>
37 #include <fs_mgr/roots.h>
38 #include <fstab/fstab.h>
39 #include <gtest/gtest.h>
40 #include <libavb/libavb.h>
41 #include <libavb_user/avb_ops_user.h>
42 #include <libdm/dm.h>
43 #include <log/log.h>
44 #include <openssl/sha.h>
45
46 using android::base::Error;
47 using android::base::Result;
48
HexDigitToByte(char c)49 static uint8_t HexDigitToByte(char c) {
50 if (c >= '0' && c <= '9') {
51 return c - '0';
52 }
53 if (c >= 'a' && c <= 'f') {
54 return c - 'a' + 10;
55 }
56 if (c >= 'A' && c <= 'Z') {
57 return c - 'A' + 10;
58 }
59 return 0xff;
60 }
61
HexToBytes(const std::string & hex,std::vector<uint8_t> * bytes)62 static bool HexToBytes(const std::string &hex, std::vector<uint8_t> *bytes) {
63 if (hex.size() % 2 != 0) {
64 return false;
65 }
66 bytes->resize(hex.size() / 2);
67 for (unsigned i = 0; i < bytes->size(); i++) {
68 uint8_t hi = HexDigitToByte(hex[i * 2]);
69 uint8_t lo = HexDigitToByte(hex[i * 2 + 1]);
70 if (lo > 0xf || hi > 0xf) {
71 return false;
72 }
73 bytes->at(i) = (hi << 4) | lo;
74 }
75 return true;
76 }
77
78 // The abstract class of SHA algorithms.
79 class ShaHasher {
80 protected:
81 const uint32_t digest_size_;
82
ShaHasher(uint32_t digest_size)83 ShaHasher(uint32_t digest_size) : digest_size_(digest_size) {}
84
85 public:
~ShaHasher()86 virtual ~ShaHasher() {}
87
GetDigestSize() const88 uint32_t GetDigestSize() const { return digest_size_; }
89
90 virtual bool CalculateDigest(const void *buffer, size_t size,
91 const void *salt, uint32_t block_length,
92 uint8_t *digest) const = 0;
93 };
94
95 template <typename CTX_TYPE>
96 class ShaHasherImpl : public ShaHasher {
97 private:
98 typedef int (*InitFunc)(CTX_TYPE *);
99 typedef int (*UpdateFunc)(CTX_TYPE *sha, const void *data, size_t len);
100 typedef int (*FinalFunc)(uint8_t *md, CTX_TYPE *sha);
101
102 const InitFunc init_func_;
103 const UpdateFunc update_func_;
104 const FinalFunc final_func_;
105
106 public:
ShaHasherImpl(InitFunc init_func,UpdateFunc update_func,FinalFunc final_func,uint32_t digest_size)107 ShaHasherImpl(InitFunc init_func, UpdateFunc update_func,
108 FinalFunc final_func, uint32_t digest_size)
109 : ShaHasher(digest_size),
110 init_func_(init_func),
111 update_func_(update_func),
112 final_func_(final_func) {}
113
~ShaHasherImpl()114 ~ShaHasherImpl() {}
115
CalculateDigest(const void * buffer,size_t size,const void * salt,uint32_t salt_length,uint8_t * digest) const116 bool CalculateDigest(const void *buffer, size_t size, const void *salt,
117 uint32_t salt_length, uint8_t *digest) const {
118 CTX_TYPE ctx;
119 if (init_func_(&ctx) != 1) {
120 return false;
121 }
122 if (update_func_(&ctx, salt, salt_length) != 1) {
123 return false;
124 }
125 if (update_func_(&ctx, buffer, size) != 1) {
126 return false;
127 }
128 if (final_func_(digest, &ctx) != 1) {
129 return false;
130 }
131 return true;
132 }
133 };
134
135 // Creates a hasher with the parameters corresponding to the algorithm name.
CreateShaHasher(const std::string & algorithm)136 static std::unique_ptr<ShaHasher> CreateShaHasher(
137 const std::string &algorithm) {
138 if (algorithm == "sha1") {
139 return std::make_unique<ShaHasherImpl<SHA_CTX>>(
140 SHA1_Init, SHA1_Update, SHA1_Final, SHA_DIGEST_LENGTH);
141 }
142 if (algorithm == "sha256") {
143 return std::make_unique<ShaHasherImpl<SHA256_CTX>>(
144 SHA256_Init, SHA256_Update, SHA256_Final, SHA256_DIGEST_LENGTH);
145 }
146 if (algorithm == "sha512") {
147 return std::make_unique<ShaHasherImpl<SHA512_CTX>>(
148 SHA512_Init, SHA512_Update, SHA512_Final, SHA512_DIGEST_LENGTH);
149 }
150 return nullptr;
151 }
152
153 // Calculates the digest of a block filled with 0.
CalculateZeroDigest(const ShaHasher & hasher,size_t size,const void * salt,int32_t block_length,uint8_t * digest)154 static bool CalculateZeroDigest(const ShaHasher &hasher, size_t size,
155 const void *salt, int32_t block_length,
156 uint8_t *digest) {
157 const std::vector<uint8_t> buffer(size, 0);
158 return hasher.CalculateDigest(buffer.data(), size, salt, block_length,
159 digest);
160 }
161
162 // Logical structure of a hashtree:
163 //
164 // Level 2: [ root ]
165 // / \
166 // Level 1: [entry_0] [entry_1]
167 // / ... \ ... \
168 // Level 0: [entry_0_0] ... [entry_0_127] ... [entry_1_127]
169 // / ... \ / ... \ / ... \
170 // Data: blk_0 ... blk_127 blk_16256 ... blk_16383 blk_32640 ... blk_32767
171 //
172 // The digest of a data block or a hash block in level N is stored in level
173 // N + 1.
174 // The function VerifyHashtree allocates a HashtreeLevel for each level. It
175 // calculates the digests of the blocks in lower level and fills them in
176 // calculating_hash_block. When calculating_hash_block is full, it is compared
177 // with the hash block at comparing_tree_offset in the image. After comparison,
178 // calculating_hash_block is cleared and reused for the next hash block.
179 //
180 // comparing_tree_offset
181 // |
182 // v
183 // [<-------------------- level_size -------------------->]
184 // [entry_0_0] ... [entry_0_127 ] ... [entry_1_127]
185 //
186 // [calculating_hash_block]
187 // ^
188 // |
189 // calculating_offset
190 struct HashtreeLevel {
191 // Offset of an expected hash block to compare, relative to the beginning of
192 // the hashtree in the image file.
193 uint64_t comparing_tree_offset;
194 // Size of this level, in bytes.
195 const uint64_t level_size;
196 // Offset of a digest in calculating_hash_block.
197 size_t calculating_offset;
198 // The hash block containing the digests calculated from the lower level.
199 std::vector<uint8_t> calculating_hash_block;
200
HashtreeLevelHashtreeLevel201 HashtreeLevel(uint64_t lv_offset, uint64_t lv_size, size_t hash_block_size)
202 : comparing_tree_offset(lv_offset),
203 level_size(lv_size),
204 calculating_offset(0),
205 calculating_hash_block(hash_block_size) {}
206 };
207
208 // Calculates and verifies the image's hashtree.
209 //
210 // Arguments:
211 // image_fd: The raw image file.
212 // image_size, data_block_size, hash_block_size, tree_offset, tree_size: The
213 // fields in AvbHashtreeDescriptor.
214 // salt: The binary value of the salt in FsAvbHashtreeDescriptor.
215 // hasher: The ShaHasher object.
216 // root_digest: The binary value of the root_digest in
217 // FsAvbHashtreeDescriptor.
218 //
219 // Returns:
220 // An empty string if the function succeeds.
221 // Otherwise it returns the error message.
VerifyHashtree(int image_fd,uint64_t image_size,const std::vector<uint8_t> & salt,uint32_t data_block_size,uint32_t hash_block_size,uint64_t tree_offset,uint64_t tree_size,const ShaHasher & hasher,const std::vector<uint8_t> & root_digest)222 static std::string VerifyHashtree(int image_fd, uint64_t image_size,
223 const std::vector<uint8_t> &salt,
224 uint32_t data_block_size,
225 uint32_t hash_block_size,
226 uint64_t tree_offset, uint64_t tree_size,
227 const ShaHasher &hasher,
228 const std::vector<uint8_t> &root_digest) {
229 uint32_t digest_size = hasher.GetDigestSize();
230 uint32_t padded_digest_size = 1;
231 while (padded_digest_size < digest_size) {
232 padded_digest_size *= 2;
233 }
234
235 if (image_size % data_block_size != 0) {
236 return "Image size is not a multiple of data block size";
237 }
238
239 uint64_t data_block_count = image_size / data_block_size;
240 uint32_t digests_per_block = hash_block_size / padded_digest_size;
241
242 // Initialize HashtreeLevel in bottom-up order.
243 std::list<HashtreeLevel> levels;
244 {
245 uint64_t hash_block_count = 0;
246 uint32_t level_block_count = data_block_count;
247 // Calculate the hashtree until the root hash is reached.
248 while (level_block_count > 1) {
249 uint32_t next_level_block_count =
250 (level_block_count + digests_per_block - 1) / digests_per_block;
251 hash_block_count += next_level_block_count;
252 // comparing_tree_offset will be initialized later.
253 levels.emplace_back(0 /* comparing_tree_offset */,
254 next_level_block_count * hash_block_size,
255 hash_block_size);
256 level_block_count = next_level_block_count;
257 }
258 if (hash_block_count * hash_block_size != tree_size) {
259 return "Block count and tree size mismatch";
260 }
261 // Append the root digest. Its level_size is unused.
262 levels.emplace_back(0 /* comparing_tree_offset */, 0 /* level_size */,
263 digest_size);
264
265 // Initialize comparing_tree_offset of each level
266 for (auto level = std::prev(levels.end()); level != levels.begin();
267 level--) {
268 std::prev(level)->comparing_tree_offset =
269 level->comparing_tree_offset + level->level_size;
270 }
271 }
272
273 std::vector<uint8_t> padded_zero_digest(padded_digest_size, 0);
274 if (!CalculateZeroDigest(hasher, data_block_size, salt.data(), salt.size(),
275 padded_zero_digest.data())) {
276 return "CalculateZeroDigest fails";
277 }
278
279 std::vector<uint8_t> data_block(data_block_size);
280 std::vector<uint8_t> tree_block(hash_block_size);
281 for (uint64_t image_offset = 0; image_offset < image_size;
282 image_offset += data_block_size) {
283 ssize_t read_size = TEMP_FAILURE_RETRY(
284 pread64(image_fd, data_block.data(), data_block.size(), image_offset));
285 if (read_size != data_block.size()) {
286 return android::base::StringPrintf(
287 "Fail to read data block at offset %llu",
288 (unsigned long long)image_offset);
289 }
290
291 bool is_last_data = (image_offset + data_block.size() == image_size);
292 // The block to be digested
293 std::vector<uint8_t> *current_block = &data_block;
294 for (auto level = levels.begin(); true; level++) {
295 uint8_t *current_digest =
296 level->calculating_hash_block.data() + level->calculating_offset;
297 if (!hasher.CalculateDigest(current_block->data(), current_block->size(),
298 salt.data(), salt.size(), current_digest)) {
299 return "CalculateDigest fails";
300 }
301 // Stop at root digest
302 if (std::next(level) == levels.end()) {
303 break;
304 }
305
306 // Pad the digest
307 memset(current_digest + digest_size, 0, padded_digest_size - digest_size);
308 level->calculating_offset += padded_digest_size;
309 // Pad the last hash block of this level
310 if (is_last_data) {
311 memset(
312 level->calculating_hash_block.data() + level->calculating_offset, 0,
313 level->calculating_hash_block.size() - level->calculating_offset);
314 } else if (level->calculating_offset <
315 level->calculating_hash_block.size()) {
316 // Stop at this level if the hash block is not full, continue to read
317 // more data_blocks from the outside loop for digest calculation
318 break;
319 }
320 // Verify the full hash block
321 // current_block may point to tree_block. Since the following pread64
322 // changes tree_block, do not read current_block in the rest of this
323 // code block.
324 current_block = nullptr;
325 read_size = TEMP_FAILURE_RETRY(
326 pread64(image_fd, tree_block.data(), tree_block.size(),
327 tree_offset + level->comparing_tree_offset));
328 if (read_size != tree_block.size()) {
329 return android::base::StringPrintf(
330 "Fail to read tree block at offset %llu",
331 (unsigned long long)tree_offset + level->comparing_tree_offset);
332 }
333
334 for (uint32_t offset = 0; offset < tree_block.size();
335 offset += padded_digest_size) {
336 // If the digest in the hashtree is equal to the digest of zero block,
337 // it indicates the corresponding data block is in DONT_CARE chunk in
338 // sparse image. The block should not be verified.
339 if (level == levels.begin() &&
340 memcmp(tree_block.data() + offset, padded_zero_digest.data(),
341 padded_digest_size) == 0) {
342 continue;
343 }
344 if (memcmp(tree_block.data() + offset,
345 level->calculating_hash_block.data() + offset,
346 padded_digest_size) != 0) {
347 return android::base::StringPrintf(
348 "Hash blocks mismatch, block offset = %llu, digest offset = %u",
349 (unsigned long long)tree_offset + level->comparing_tree_offset,
350 offset);
351 }
352 }
353
354 level->calculating_offset = 0;
355 level->comparing_tree_offset += hash_block_size;
356 if (level->comparing_tree_offset > tree_size) {
357 return "Tree offset is out of bound";
358 }
359 // Prepare for next/upper level, to calculate the digest of this
360 // hash_block for comparison
361 current_block = &tree_block;
362 }
363 }
364
365 if (levels.back().calculating_hash_block != root_digest) {
366 return "Root digests mismatch";
367 }
368 return "";
369 }
370
371 // Converts descriptor.hash_algorithm to std::string.
GetHashAlgorithm(const AvbHashtreeDescriptor & descriptor)372 static std::string GetHashAlgorithm(const AvbHashtreeDescriptor &descriptor) {
373 return std::string(reinterpret_cast<const char *>(descriptor.hash_algorithm));
374 }
375
376 // Converts descriptor.hash_algorithm to std::string.
GetHashAlgorithm(const AvbHashDescriptor & descriptor)377 static std::string GetHashAlgorithm(const AvbHashDescriptor &descriptor) {
378 return std::string(reinterpret_cast<const char *>(descriptor.hash_algorithm));
379 }
380
381 // Checks whether the public key is an official GSI key or not.
ValidatePublicKeyBlob(const std::string & key_blob_to_validate)382 static bool ValidatePublicKeyBlob(const std::string &key_blob_to_validate) {
383 if (key_blob_to_validate.empty()) {
384 ALOGE("Failed to validate an empty key");
385 return false;
386 }
387
388 std::string allowed_key_blob;
389 std::vector<std::string> allowed_key_paths = {
390 "/data/local/tmp/q-gsi.avbpubkey", "/data/local/tmp/r-gsi.avbpubkey",
391 "/data/local/tmp/s-gsi.avbpubkey", "/data/local/tmp/qcar-gsi.avbpubkey"};
392 for (const auto &path : allowed_key_paths) {
393 if (android::base::ReadFileToString(path, &allowed_key_blob)) {
394 if (key_blob_to_validate == allowed_key_blob) {
395 ALOGE("Found matching GSI key: %s", path.c_str());
396 return true;
397 }
398 }
399 }
400 return false;
401 }
402
403 // Gets the system partition's AvbHashtreeDescriptor and device file path.
404 //
405 // Arguments:
406 // out_verify_result: The result of vbmeta verification.
407 // out_system_path: The system's device file path.
408 //
409 // Returns:
410 // The pointer to the system's AvbHashtreeDescriptor.
411 // nullptr if any operation fails.
412 static std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor>
GetSystemHashtreeDescriptor(android::fs_mgr::VBMetaVerifyResult * out_verify_result,std::string * out_system_path)413 GetSystemHashtreeDescriptor(
414 android::fs_mgr::VBMetaVerifyResult *out_verify_result,
415 std::string *out_system_path) {
416 android::fs_mgr::Fstab default_fstab;
417 bool ok = ReadDefaultFstab(&default_fstab);
418 if (!ok) {
419 ALOGE("ReadDefaultFstab fails");
420 return nullptr;
421 }
422 android::fs_mgr::FstabEntry *system_fstab_entry =
423 GetEntryForPath(&default_fstab, "/system");
424 if (system_fstab_entry == nullptr) {
425 ALOGE("GetEntryForPath fails");
426 return nullptr;
427 }
428
429 ok = fs_mgr_update_logical_partition(system_fstab_entry);
430 if (!ok) {
431 ALOGE("fs_mgr_update_logical_partition fails");
432 return nullptr;
433 }
434
435 CHECK(out_system_path != nullptr);
436 *out_system_path = system_fstab_entry->blk_device;
437
438 std::string out_public_key_data;
439 std::string out_avb_partition_name;
440 std::unique_ptr<android::fs_mgr::VBMetaData> vbmeta =
441 android::fs_mgr::LoadAndVerifyVbmeta(
442 *system_fstab_entry, "" /* expected_key_blob */, &out_public_key_data,
443 &out_avb_partition_name, out_verify_result);
444 if (vbmeta == nullptr) {
445 ALOGE("LoadAndVerifyVbmeta fails");
446 return nullptr;
447 }
448
449 if (out_public_key_data.empty()) {
450 ALOGE("The GSI image is not signed");
451 return nullptr;
452 }
453
454 if (!ValidatePublicKeyBlob(out_public_key_data)) {
455 ALOGE("The GSI image is not signed by an official key");
456 return nullptr;
457 }
458
459 std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor> descriptor =
460 android::fs_mgr::GetHashtreeDescriptor("system", std::move(*vbmeta));
461 if (descriptor == nullptr) {
462 ALOGE("GetHashtreeDescriptor fails");
463 return nullptr;
464 }
465
466 return descriptor;
467 }
468
469 // Returns true iff the device has the specified feature.
DeviceSupportsFeature(const char * feature)470 bool DeviceSupportsFeature(const char *feature) {
471 bool device_supports_feature = false;
472 FILE *p = popen("pm list features", "re");
473 if (p) {
474 char *line = NULL;
475 size_t len = 0;
476 while (getline(&line, &len, p) > 0) {
477 if (strstr(line, feature)) {
478 device_supports_feature = true;
479 break;
480 }
481 }
482 pclose(p);
483 }
484 return device_supports_feature;
485 }
486
GetFirstApiLevel()487 static int GetFirstApiLevel() {
488 int level = android::base::GetIntProperty("ro.product.first_api_level", 0);
489 if (level == 0) {
490 level = android::base::GetIntProperty("ro.build.version.sdk", 0);
491 }
492 if (level == 0) {
493 ADD_FAILURE() << "Failed to determine first API level";
494 }
495 return level;
496 }
497
ShouldSkipGkiTest()498 bool ShouldSkipGkiTest() {
499 /* Skip for devices launched before Android R. */
500 constexpr auto R_API_LEVEL = 30;
501 int first_api_level = GetFirstApiLevel();
502 GTEST_LOG_(INFO) << "First API level is " << first_api_level;
503 if (first_api_level < R_API_LEVEL) {
504 GTEST_LOG_(INFO) << "Exempt from GKI test due to old starting API level";
505 return true;
506 }
507
508 /* Skip for form factors that do not mandate GKI yet */
509 const static bool tv_device =
510 DeviceSupportsFeature("android.software.leanback");
511 const static bool auto_device =
512 DeviceSupportsFeature("android.hardware.type.automotive");
513 if (tv_device || auto_device) {
514 GTEST_LOG_(INFO) << "Exempt from GKI test on TV/Auto devices";
515 return true;
516 }
517
518 return false;
519 }
520
521 // Returns a tuple of (version_major, version_minor and architecture).
GetKernelInfo()522 static Result<std::tuple<int, int, std::string>> GetKernelInfo() {
523 struct utsname buf;
524 int ret, kernel_version_major, kernel_version_minor;
525 ret = uname(&buf);
526 if (ret != 0) {
527 return Error() << "Failed to get kernel version.";
528 }
529
530 char unused;
531 ret = sscanf(buf.release, "%d.%d%c", &kernel_version_major,
532 &kernel_version_minor, &unused);
533 if (ret < 2) {
534 return Error() << "Failed to parse kernel version.";
535 }
536
537 return std::make_tuple(kernel_version_major, kernel_version_minor,
538 buf.machine);
539 }
540
ShouldSkipGkiComplianceV1()541 bool ShouldSkipGkiComplianceV1() {
542 auto kernel_info = GetKernelInfo();
543
544 if (!kernel_info.ok()) {
545 ADD_FAILURE() << "Failed to get kernel info";
546 return true;
547 }
548
549 const auto [kernel_version_major, kernel_version_minor, kernel_arch] =
550 (std::move(kernel_info).value());
551
552 /* Skip for devices if the kernel version is not 5.4. */
553 if (kernel_version_major != 5 || kernel_version_minor != 4) {
554 GTEST_LOG_(INFO)
555 << "Exempt from GKI 1.0 test due to unmatched kernel version: "
556 << kernel_version_major << "." << kernel_version_minor;
557 return true;
558 }
559 /* Skip for non arm64 that do not mandate GKI yet. */
560 if (kernel_arch != "aarch64") {
561 GTEST_LOG_(INFO) << "Exempt from GKI test on non-arm64 devices";
562 return true;
563 }
564
565 return false;
566 }
567
ShouldSkipGkiComplianceV2()568 bool ShouldSkipGkiComplianceV2() {
569 auto kernel_info = GetKernelInfo();
570
571 if (!kernel_info.ok()) {
572 ADD_FAILURE() << "Failed to get kernel info";
573 return true;
574 }
575
576 const auto [kernel_version_major, kernel_version_minor, kernel_arch] =
577 (std::move(kernel_info).value());
578
579 /* Skip for devices if the kernel version is not >= 5.10. */
580 if (kernel_version_major < 5 ||
581 (kernel_version_major == 5 && kernel_version_minor < 10)) {
582 GTEST_LOG_(INFO)
583 << "Exempt from GKI 2.0 test due to unmatched kernel version: "
584 << kernel_version_major << "." << kernel_version_minor;
585 return true;
586 }
587
588 /* Skip for non arm64 that do not mandate GKI yet. */
589 if (kernel_arch != "aarch64") {
590 GTEST_LOG_(INFO) << "Exempt from GKI test on non-arm64 devices";
591 return true;
592 }
593
594 return false;
595 }
596
TEST(AvbTest,GkiComplianceV1)597 TEST(AvbTest, GkiComplianceV1) {
598 if (ShouldSkipGkiTest() || ShouldSkipGkiComplianceV1()) {
599 return;
600 }
601
602 /* load vbmeta struct from boot, verify struct integrity */
603 std::string out_public_key_data;
604 android::fs_mgr::VBMetaVerifyResult out_verify_result;
605 std::string boot_path = "/dev/block/by-name/boot" + fs_mgr_get_slot_suffix();
606 std::unique_ptr<android::fs_mgr::VBMetaData> vbmeta =
607 android::fs_mgr::LoadAndVerifyVbmetaByPath(
608 boot_path, "boot", "" /* expected_key_blob */,
609 true /* allow verification error */, false /* rollback_protection */,
610 false /* is_chained_vbmeta */, &out_public_key_data,
611 nullptr /* out_verification_disabled */, &out_verify_result);
612
613 ASSERT_TRUE(vbmeta) << "Verification of GKI vbmeta fails.";
614 ASSERT_FALSE(out_public_key_data.empty()) << "The GKI image is not signed.";
615 EXPECT_TRUE(ValidatePublicKeyBlob(out_public_key_data))
616 << "The GKI image is not signed by an official key.";
617 EXPECT_EQ(out_verify_result, android::fs_mgr::VBMetaVerifyResult::kSuccess)
618 << "Verification of the GKI vbmeta structure failed.";
619
620 /* verify boot partition according to vbmeta structure */
621 std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor> descriptor =
622 android::fs_mgr::GetHashDescriptor("boot", std::move(*vbmeta));
623 ASSERT_TRUE(descriptor)
624 << "Failed to load hash descriptor from boot.img vbmeta";
625 const std::string &salt_str = descriptor->salt;
626 const std::string &expected_digest_str = descriptor->digest;
627
628 android::base::unique_fd fd(open(boot_path.c_str(), O_RDONLY));
629 ASSERT_GE(fd, 0) << "Fail to open boot partition. Try 'adb root'.";
630
631 const std::string hash_algorithm(GetHashAlgorithm(*descriptor));
632 GTEST_LOG_(INFO) << "hash_algorithm = " << hash_algorithm;
633
634 std::unique_ptr<ShaHasher> hasher = CreateShaHasher(hash_algorithm);
635 ASSERT_TRUE(hasher);
636
637 std::vector<uint8_t> salt, expected_digest, out_digest;
638 bool ok = HexToBytes(salt_str, &salt);
639 ASSERT_TRUE(ok) << "Invalid salt in descriptor: " << salt_str;
640 ok = HexToBytes(expected_digest_str, &expected_digest);
641 ASSERT_TRUE(ok) << "Invalid digest in descriptor: " << expected_digest_str;
642 ASSERT_EQ(expected_digest.size(), hasher->GetDigestSize());
643
644 std::vector<char> boot_partition_vector;
645 boot_partition_vector.resize(descriptor->image_size);
646 ASSERT_TRUE(android::base::ReadFully(fd, boot_partition_vector.data(),
647 descriptor->image_size))
648 << "Could not read boot partition to vector.";
649
650 out_digest.resize(hasher->GetDigestSize());
651 ASSERT_TRUE(hasher->CalculateDigest(
652 boot_partition_vector.data(), descriptor->image_size,
653 salt.data(), descriptor->salt_len, out_digest.data()))
654 << "Unable to calculate boot image digest.";
655
656 ASSERT_TRUE(out_digest.size() == expected_digest.size())
657 << "Calculated GKI boot digest size does not match expected digest size.";
658 ASSERT_TRUE(out_digest == expected_digest)
659 << "Calculated GKI boot digest does not match expected digest.";
660 }
661
662 // Loads GKI compliance V2 images.
663 //
664 // Arguments:
665 // out_boot_partition_vector: the boot.img content without boot_signature.
666 // It consists of a boot header, a kernel and a ramdisk.
667 // out_boot_signature_vector: the boot signature used to verify
668 // out_boot_partition_vector.
669 //
LoadGkiComplianceV2Images(std::vector<uint8_t> * out_boot_partition_vector,std::vector<uint8_t> * out_boot_signature_vector)670 void LoadGkiComplianceV2Images(
671 std::vector<uint8_t> *out_boot_partition_vector,
672 std::vector<uint8_t> *out_boot_signature_vector) {
673 constexpr auto BOOT_HEADER_SIZE = 4096;
674 std::string boot_path = "/dev/block/by-name/boot" + fs_mgr_get_slot_suffix();
675
676 // Read boot header first.
677 android::base::unique_fd fd(open(boot_path.c_str(), O_RDONLY));
678 ASSERT_GE(fd, 0) << "Fail to open boot partition. Try 'adb root'.";
679
680 out_boot_partition_vector->resize(BOOT_HEADER_SIZE);
681 ASSERT_TRUE(android::base::ReadFully(fd, out_boot_partition_vector->data(),
682 BOOT_HEADER_SIZE))
683 << "Could not read boot partition header to vector.";
684
685 boot_img_hdr_v4 *boot_header =
686 reinterpret_cast<boot_img_hdr_v4 *>(out_boot_partition_vector->data());
687 std::string boot_magic(reinterpret_cast<const char *>(boot_header->magic),
688 BOOT_MAGIC_SIZE);
689 ASSERT_EQ(boot_magic, BOOT_MAGIC) << "Incorrect boot magic: " << boot_magic;
690
691 GTEST_LOG_(INFO) << "kernel size: " << boot_header->kernel_size
692 << ", ramdisk size: " << boot_header->ramdisk_size
693 << ", signature size: " << boot_header->signature_size;
694
695 // Now reads kernel and ramdisk.
696 uint32_t kernel_pages = (boot_header->kernel_size + 4096 - 1) / 4096;
697 uint32_t ramdisk_pages = (boot_header->ramdisk_size + 4096 - 1) / 4096;
698 uint32_t kernel_ramdisk_size = (kernel_pages + ramdisk_pages) * 4096;
699
700 out_boot_partition_vector->resize(BOOT_HEADER_SIZE + kernel_ramdisk_size);
701 ASSERT_TRUE(android::base::ReadFully(
702 fd, out_boot_partition_vector->data() + BOOT_HEADER_SIZE,
703 kernel_ramdisk_size))
704 << "Could not read boot partition to vector.";
705
706 // Reads boot_signature.
707 uint32_t signature_pages = (boot_header->signature_size + 4096 - 1) / 4096;
708 uint32_t signature_size_aligned = signature_pages * 4096;
709 out_boot_signature_vector->resize(signature_size_aligned);
710 ASSERT_TRUE(android::base::ReadFully(fd, out_boot_signature_vector->data(),
711 signature_size_aligned))
712 << "Could not read boot signature to vector.";
713 }
714
715 // Verifies the GKI 2.0 boot.img against the boot signature.
716 //
717 // Arguments:
718 // boot_partition_vector: the boot.img content without boot_signature.
719 // It consists of a boot header, a kernel and a ramdisk.
720 // boot_signature_vector: the boot signature used to verify
721 // boot_partition_vector.
722 //
VerifyGkiComplianceV2Signature(const std::vector<uint8_t> & boot_partition_vector,const std::vector<uint8_t> & boot_signature_vector)723 void VerifyGkiComplianceV2Signature(
724 const std::vector<uint8_t> &boot_partition_vector,
725 const std::vector<uint8_t> &boot_signature_vector) {
726 size_t pk_len;
727 const uint8_t *pk_data;
728 ::AvbVBMetaVerifyResult vbmeta_ret;
729
730 vbmeta_ret =
731 avb_vbmeta_image_verify(boot_signature_vector.data(),
732 boot_signature_vector.size(), &pk_data, &pk_len);
733 ASSERT_EQ(vbmeta_ret, AVB_VBMETA_VERIFY_RESULT_OK)
734 << "Failed to verify boot_signature: " << vbmeta_ret;
735
736 std::string out_public_key_data(reinterpret_cast<const char *>(pk_data),
737 pk_len);
738 ASSERT_FALSE(out_public_key_data.empty()) << "The GKI image is not signed.";
739 EXPECT_TRUE(ValidatePublicKeyBlob(out_public_key_data))
740 << "The GKI image is not signed by an official key.";
741
742 android::fs_mgr::VBMetaData boot_signature(boot_signature_vector.data(),
743 boot_signature_vector.size(),
744 "boot_signature");
745
746 std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor> descriptor =
747 android::fs_mgr::GetHashDescriptor("boot", std::move(boot_signature));
748 ASSERT_TRUE(descriptor)
749 << "Failed to load hash descriptor from the boot signature";
750 ASSERT_EQ(boot_partition_vector.size(), descriptor->image_size);
751
752 const std::string &salt_str = descriptor->salt;
753 const std::string &expected_digest_str = descriptor->digest;
754
755 const std::string hash_algorithm(GetHashAlgorithm(*descriptor));
756 GTEST_LOG_(INFO) << "hash_algorithm = " << hash_algorithm;
757
758 std::unique_ptr<ShaHasher> hasher = CreateShaHasher(hash_algorithm);
759 ASSERT_TRUE(hasher);
760
761 std::vector<uint8_t> salt, expected_digest, out_digest;
762
763 bool ok = HexToBytes(salt_str, &salt);
764 ASSERT_TRUE(ok) << "Invalid salt in descriptor: " << salt_str;
765 ok = HexToBytes(expected_digest_str, &expected_digest);
766 ASSERT_TRUE(ok) << "Invalid digest in descriptor: " << expected_digest_str;
767
768 ASSERT_EQ(expected_digest.size(), hasher->GetDigestSize());
769 out_digest.resize(hasher->GetDigestSize());
770
771 ASSERT_TRUE(hasher->CalculateDigest(boot_partition_vector.data(),
772 boot_partition_vector.size(), salt.data(),
773 descriptor->salt_len, out_digest.data()))
774 << "Unable to calculate boot image digest.";
775
776 ASSERT_EQ(out_digest.size(), expected_digest.size())
777 << "Calculated GKI boot digest size does not match expected digest size.";
778
779 ASSERT_EQ(out_digest, expected_digest)
780 << "Calculated GKI boot digest does not match expected digest.";
781 }
782
TEST(AvbTest,GkiComplianceV2)783 TEST(AvbTest, GkiComplianceV2) {
784 if (ShouldSkipGkiTest() || ShouldSkipGkiComplianceV2()) {
785 return;
786 }
787
788 std::vector<uint8_t> boot_partition_vector;
789 std::vector<uint8_t> boot_signature_vector;
790 ASSERT_NO_FATAL_FAILURE(LoadGkiComplianceV2Images(&boot_partition_vector,
791 &boot_signature_vector));
792 VerifyGkiComplianceV2Signature(boot_partition_vector, boot_signature_vector);
793 }
794
795 // Loads contents and metadata of logical system partition, calculates
796 // the hashtree, and compares with the metadata.
TEST(AvbTest,SystemHashtree)797 TEST(AvbTest, SystemHashtree) {
798 android::fs_mgr::VBMetaVerifyResult verify_result;
799 std::string system_path;
800 std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor> descriptor =
801 GetSystemHashtreeDescriptor(&verify_result, &system_path);
802 ASSERT_TRUE(descriptor);
803
804 ALOGI("System partition is %s", system_path.c_str());
805
806 // TODO: Skip assertion when running with non-compliance configuration.
807 EXPECT_EQ(verify_result, android::fs_mgr::VBMetaVerifyResult::kSuccess);
808 EXPECT_NE(verify_result,
809 android::fs_mgr::VBMetaVerifyResult::kErrorVerification)
810 << "The system image is not an officially signed GSI.";
811
812 const std::string &salt_str = descriptor->salt;
813 const std::string &expected_digest_str = descriptor->root_digest;
814
815 android::base::unique_fd fd(open(system_path.c_str(), O_RDONLY));
816 ASSERT_GE(fd, 0) << "Fail to open system partition. Try 'adb root'.";
817
818 const std::string hash_algorithm(GetHashAlgorithm(*descriptor));
819 ALOGI("hash_algorithm = %s", hash_algorithm.c_str());
820
821 std::unique_ptr<ShaHasher> hasher = CreateShaHasher(hash_algorithm);
822 ASSERT_TRUE(hasher);
823
824 std::vector<uint8_t> salt, expected_digest;
825 bool ok = HexToBytes(salt_str, &salt);
826 ASSERT_TRUE(ok) << "Invalid salt in descriptor: " << salt_str;
827 ok = HexToBytes(expected_digest_str, &expected_digest);
828 ASSERT_TRUE(ok) << "Invalid digest in descriptor: " << expected_digest_str;
829 ASSERT_EQ(expected_digest.size(), hasher->GetDigestSize());
830
831 ALOGI("image_size = %llu", (unsigned long long)descriptor->image_size);
832 ALOGI("data_block_size = %u", descriptor->data_block_size);
833 ALOGI("hash_block_size = %u", descriptor->hash_block_size);
834 ALOGI("tree_offset = %llu", (unsigned long long)descriptor->tree_offset);
835 ALOGI("tree_size = %llu", (unsigned long long)descriptor->tree_size);
836
837 std::string error_message = VerifyHashtree(
838 fd, descriptor->image_size, salt, descriptor->data_block_size,
839 descriptor->hash_block_size, descriptor->tree_offset,
840 descriptor->tree_size, *hasher, expected_digest);
841 ASSERT_EQ(error_message, "");
842 }
843
844 // Finds the next word consisting of non-whitespace characters in a string.
845 //
846 // Arguments:
847 // str: The string to be searched for the next word.
848 // pos: The starting position to search for the next word.
849 // This function sets it to the past-the-end position of the word.
850 //
851 // Returns:
852 // The starting position of the word.
853 // If there is no next word, this function does not change pos and returns
854 // std::string::npos.
NextWord(const std::string & str,size_t * pos)855 static size_t NextWord(const std::string &str, size_t *pos) {
856 const char *whitespaces = " \t\r\n";
857 size_t start = str.find_first_not_of(whitespaces, *pos);
858 if (start == std::string::npos) {
859 return start;
860 }
861 *pos = str.find_first_of(whitespaces, start);
862 if (*pos == std::string::npos) {
863 *pos = str.size();
864 }
865 return start;
866 }
867
868 // Compares device mapper table with system hashtree descriptor.
TEST(AvbTest,SystemDescriptor)869 TEST(AvbTest, SystemDescriptor) {
870 // Get system hashtree descriptor.
871
872 android::fs_mgr::VBMetaVerifyResult verify_result;
873 std::string system_path;
874 std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor> descriptor =
875 GetSystemHashtreeDescriptor(&verify_result, &system_path);
876 ASSERT_TRUE(descriptor);
877
878 // TODO: Assert when running with compliance configuration.
879 // The SystemHashtree function asserts verify_result.
880 if (verify_result != android::fs_mgr::VBMetaVerifyResult::kSuccess) {
881 ALOGW("The system image is not an officially signed GSI.");
882 }
883
884 // Get device mapper table.
885 android::dm::DeviceMapper &device_mapper =
886 android::dm::DeviceMapper::Instance();
887 std::vector<android::dm::DeviceMapper::TargetInfo> table;
888 bool ok = device_mapper.GetTableInfo("system-verity", &table);
889 ASSERT_TRUE(ok) << "GetTableInfo fails";
890 ASSERT_EQ(table.size(), 1);
891 const android::dm::DeviceMapper::TargetInfo &target = table[0];
892 // Sample output:
893 // Device mapper table for system-verity:
894 // 0-1783288: verity, 1 253:0 253:0 4096 4096 222911 222911 sha1
895 // 6b2b46715a2d27c53cc7f91fe63ce798ff1f3df7
896 // 65bc99ca8e97379d4f7adc66664941acc0a8e682 10 restart_on_corruption
897 // ignore_zero_blocks use_fec_from_device 253:0 fec_blocks 224668 fec_start
898 // 224668 fec_roots 2
899 ALOGI("Device mapper table for system-verity:\n%llu-%llu: %s, %s",
900 target.spec.sector_start, target.spec.sector_start + target.spec.length,
901 target.spec.target_type, target.data.c_str());
902 EXPECT_EQ(strcmp(target.spec.target_type, "verity"), 0);
903
904 // Compare the target's positional parameters with the descriptor. Reference:
905 // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity#mapping-table-for-verity-target
906 std::array<std::string, 10> descriptor_values = {
907 std::to_string(descriptor->dm_verity_version),
908 "", // skip data_dev
909 "", // skip hash_dev
910 std::to_string(descriptor->data_block_size),
911 std::to_string(descriptor->hash_block_size),
912 std::to_string(descriptor->image_size /
913 descriptor->data_block_size), // #blocks
914 std::to_string(descriptor->image_size /
915 descriptor->data_block_size), // hash_start
916 GetHashAlgorithm(*descriptor),
917 descriptor->root_digest,
918 descriptor->salt,
919 };
920
921 size_t next_pos = 0;
922 for (const std::string &descriptor_value : descriptor_values) {
923 size_t begin_pos = NextWord(target.data, &next_pos);
924 ASSERT_NE(begin_pos, std::string::npos);
925 if (!descriptor_value.empty()) {
926 EXPECT_EQ(target.data.compare(begin_pos, next_pos - begin_pos,
927 descriptor_value),
928 0);
929 }
930 }
931
932 // Compare the target's optional parameters with the descriptor.
933 unsigned long opt_param_count;
934 {
935 size_t begin_pos = NextWord(target.data, &next_pos);
936 ASSERT_NE(begin_pos, std::string::npos);
937 opt_param_count =
938 std::stoul(target.data.substr(begin_pos, next_pos - begin_pos));
939 }
940 // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity#optional-parameters
941 std::set<std::string> opt_params = {
942 "check_at_most_once",
943 "ignore_corruption",
944 "ignore_zero_blocks",
945 "restart_on_corruption",
946 };
947 // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity#optional-fec-forward-error-correction-parameters
948 std::map<std::string, std::string> opt_fec_params = {
949 {"fec_blocks", ""},
950 {"fec_roots", ""},
951 {"fec_start", ""},
952 {"use_fec_from_device", ""},
953 };
954
955 for (unsigned long i = 0; i < opt_param_count; i++) {
956 size_t begin_pos = NextWord(target.data, &next_pos);
957 ASSERT_NE(begin_pos, std::string::npos);
958 const std::string param_name(target.data, begin_pos, next_pos - begin_pos);
959 if (opt_fec_params.count(param_name)) {
960 i++;
961 ASSERT_LT(i, opt_param_count);
962 begin_pos = NextWord(target.data, &next_pos);
963 ASSERT_NE(begin_pos, std::string::npos);
964 opt_fec_params[param_name] =
965 target.data.substr(begin_pos, next_pos - begin_pos);
966 } else {
967 ASSERT_NE(opt_params.count(param_name), 0)
968 << "Unknown dm-verity target parameter: " << param_name;
969 }
970 }
971
972 EXPECT_EQ(opt_fec_params["fec_roots"],
973 std::to_string(descriptor->fec_num_roots));
974 EXPECT_EQ(
975 opt_fec_params["fec_blocks"],
976 std::to_string(descriptor->fec_offset / descriptor->data_block_size));
977 EXPECT_EQ(
978 opt_fec_params["fec_start"],
979 std::to_string(descriptor->fec_offset / descriptor->data_block_size));
980 // skip use_fec_from_device
981
982 ASSERT_EQ(NextWord(target.data, &next_pos), std::string::npos);
983 }
984
VerifyHashAlgorithm(const AvbHashtreeDescriptor * descriptor)985 static void VerifyHashAlgorithm(const AvbHashtreeDescriptor* descriptor) {
986 AvbHashtreeDescriptor hashtree_descriptor;
987 ASSERT_TRUE(avb_hashtree_descriptor_validate_and_byteswap(
988 descriptor, &hashtree_descriptor))
989 << "hash tree descriptor is invalid.";
990
991 auto partition_name_ptr = reinterpret_cast<const uint8_t*>(descriptor) +
992 sizeof(AvbHashtreeDescriptor);
993 std::string partition_name(
994 partition_name_ptr,
995 partition_name_ptr + hashtree_descriptor.partition_name_len);
996
997 if (avb_strcmp(
998 reinterpret_cast<const char*>(hashtree_descriptor.hash_algorithm),
999 "sha1") == 0) {
1000 FAIL() << "The hash tree algorithm cannot be SHA1 for partition "
1001 << partition_name;
1002 }
1003 }
1004
LoadAndVerifyAvbSlotDataForCurrentSlot(AvbSlotVerifyData ** avb_slot_data)1005 static void LoadAndVerifyAvbSlotDataForCurrentSlot(
1006 AvbSlotVerifyData** avb_slot_data) {
1007 // Use an empty suffix string for non-A/B devices.
1008 std::string suffix;
1009 if (android::base::GetBoolProperty("ro.build.ab_update", false)) {
1010 suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
1011 ASSERT_TRUE(!suffix.empty()) << "Failed to get suffix for the current slot";
1012 }
1013
1014 const char* requested_partitions[] = {nullptr};
1015
1016 auto avb_ops = avb_ops_user_new();
1017 auto verify_result = avb_slot_verify(
1018 avb_ops, requested_partitions, suffix.c_str(), AVB_SLOT_VERIFY_FLAGS_NONE,
1019 AVB_HASHTREE_ERROR_MODE_EIO, avb_slot_data);
1020 ASSERT_EQ(AVB_SLOT_VERIFY_RESULT_OK, verify_result)
1021 << "Failed to verify avb slot data " << verify_result;
1022 }
1023
1024 // Check the correct hashtree algorithm is used.
TEST(AvbTest,HashtreeAlgorithm)1025 TEST(AvbTest, HashtreeAlgorithm) {
1026 constexpr auto S_API_LEVEL = 31;
1027
1028 int first_api_level = GetFirstApiLevel();
1029 GTEST_LOG_(INFO) << "First API level is " << first_api_level;
1030 if (first_api_level < S_API_LEVEL) {
1031 GTEST_LOG_(INFO)
1032 << "Exempt from avb hash tree test due to old starting API level";
1033 return;
1034 }
1035
1036 // Note we don't iterate the entries in fstab; because we don't know if a
1037 // partition uses hashtree or not.
1038 AvbSlotVerifyData* avb_slot_data;
1039 LoadAndVerifyAvbSlotDataForCurrentSlot(&avb_slot_data);
1040 ASSERT_NE(nullptr, avb_slot_data) << "Failed to load avb slot verify data";
1041 std::unique_ptr<AvbSlotVerifyData, decltype(&avb_slot_verify_data_free)>
1042 scope_guard(avb_slot_data, avb_slot_verify_data_free);
1043
1044 // Iterate over the loaded vbmeta structs
1045 for (size_t i = 0; i < avb_slot_data->num_vbmeta_images; i++) {
1046 std::string partition_name = avb_slot_data->vbmeta_images[i].partition_name;
1047 const auto& vbmeta_image = avb_slot_data->vbmeta_images[i];
1048
1049 size_t num_descriptors;
1050 auto descriptors = avb_descriptor_get_all(
1051 vbmeta_image.vbmeta_data, vbmeta_image.vbmeta_size, &num_descriptors);
1052 // Iterate over the hashtree descriptors
1053 for (size_t n = 0; n < num_descriptors; n++) {
1054 if (avb_be64toh(descriptors[n]->tag) != AVB_DESCRIPTOR_TAG_HASHTREE) {
1055 continue;
1056 }
1057
1058 VerifyHashAlgorithm(
1059 reinterpret_cast<const AvbHashtreeDescriptor*>(descriptors[n]));
1060 }
1061 }
1062 }
1063