/* * Copyright (C) 2016 The Android Open Source Project * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include <endian.h> #include <string.h> #include <gtest/gtest.h> #include <libavb/avb_sha.h> #include <libavb/libavb.h> #include "avb_unittest_util.h" namespace avb { // Subclass BaseAvbToolTest to check for memory leaks. class UtilTest : public BaseAvbToolTest { public: UtilTest() {} }; TEST_F(UtilTest, RSAPublicKeyHeaderByteswap) { AvbRSAPublicKeyHeader h; AvbRSAPublicKeyHeader s; uint32_t n32; uint64_t n64; n32 = 0x11223344; n64 = 0x1122334455667788; h.key_num_bits = htobe32(n32); n32++; h.n0inv = htobe32(n32); n32++; EXPECT_NE(0, avb_rsa_public_key_header_validate_and_byteswap(&h, &s)); n32 = 0x11223344; n64 = 0x1122334455667788; EXPECT_EQ(n32, s.key_num_bits); n32++; EXPECT_EQ(n32, s.n0inv); n32++; } TEST_F(UtilTest, FooterByteswap) { AvbFooter h; AvbFooter s; AvbFooter other; AvbFooter bad; uint64_t n64; n64 = 0x1122334455667788; memcpy(h.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN); h.version_major = htobe32(AVB_FOOTER_VERSION_MAJOR); h.version_minor = htobe32(AVB_FOOTER_VERSION_MINOR); h.original_image_size = htobe64(n64); n64++; h.vbmeta_offset = htobe64(n64); n64++; h.vbmeta_size = htobe64(n64); n64++; EXPECT_NE(0, avb_footer_validate_and_byteswap(&h, &s)); n64 = 0x1122334455667788; EXPECT_EQ((uint32_t)AVB_FOOTER_VERSION_MAJOR, s.version_major); EXPECT_EQ((uint32_t)AVB_FOOTER_VERSION_MINOR, s.version_minor); EXPECT_EQ(n64, s.original_image_size); n64++; EXPECT_EQ(n64, s.vbmeta_offset); n64++; EXPECT_EQ(n64, s.vbmeta_size); n64++; // Check that the struct still validates if minor is bigger than // what we expect. other = h; h.version_minor = htobe32(AVB_FOOTER_VERSION_MINOR + 1); EXPECT_NE(0, avb_footer_validate_and_byteswap(&other, &s)); // Check for bad magic. bad = h; bad.magic[0] = 'x'; EXPECT_EQ(0, avb_footer_validate_and_byteswap(&bad, &s)); // Check for bad major version. bad = h; bad.version_major = htobe32(AVB_FOOTER_VERSION_MAJOR + 1); EXPECT_EQ(0, avb_footer_validate_and_byteswap(&bad, &s)); } TEST_F(UtilTest, KernelCmdlineDescriptorByteswap) { AvbKernelCmdlineDescriptor h; AvbKernelCmdlineDescriptor s; AvbKernelCmdlineDescriptor bad; uint64_t nbf; uint32_t n32; // Specify 40 bytes of data past the end of the descriptor struct. nbf = 40 + sizeof(AvbKernelCmdlineDescriptor) - sizeof(AvbDescriptor); h.parent_descriptor.num_bytes_following = htobe64(nbf); h.parent_descriptor.tag = htobe64(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE); h.kernel_cmdline_length = htobe32(40); n32 = 0x11223344; h.flags = htobe32(n32); n32++; EXPECT_NE(0, avb_kernel_cmdline_descriptor_validate_and_byteswap(&h, &s)); n32 = 0x11223344; EXPECT_EQ(n32, s.flags); n32++; EXPECT_EQ(AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE, s.parent_descriptor.tag); EXPECT_EQ(nbf, s.parent_descriptor.num_bytes_following); EXPECT_EQ(40UL, s.kernel_cmdline_length); // Check for bad tag. bad = h; bad.parent_descriptor.tag = htobe64(0xf00dd00d); EXPECT_EQ(0, avb_kernel_cmdline_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 41 bytes. bad = h; bad.kernel_cmdline_length = htobe32(41); EXPECT_EQ(0, avb_kernel_cmdline_descriptor_validate_and_byteswap(&bad, &s)); } TEST_F(UtilTest, HashtreeDescriptorByteswap) { AvbHashtreeDescriptor h; AvbHashtreeDescriptor s; AvbHashtreeDescriptor bad; uint64_t nbf; uint32_t n32; uint64_t n64; // Specify 44 bytes of data past the end of the descriptor struct. nbf = 44 + sizeof(AvbHashtreeDescriptor) - sizeof(AvbDescriptor); h.parent_descriptor.num_bytes_following = htobe64(nbf); h.parent_descriptor.tag = htobe64(AVB_DESCRIPTOR_TAG_HASHTREE); h.partition_name_len = htobe32(10); h.salt_len = htobe32(10); h.root_digest_len = htobe32(10); n32 = 0x11223344; n64 = 0x1122334455667788; h.dm_verity_version = htobe32(n32); n32++; h.image_size = htobe64(n64); n64++; h.tree_offset = htobe64(n64); n64++; h.tree_size = htobe64(n64); n64++; h.data_block_size = htobe32(n32); n32++; h.hash_block_size = htobe32(n32); n32++; h.fec_num_roots = htobe32(n32); n32++; h.fec_offset = htobe64(n64); n64++; h.fec_size = htobe64(n64); n64++; EXPECT_TRUE(avb_hashtree_descriptor_validate_and_byteswap(&h, &s)); n32 = 0x11223344; n64 = 0x1122334455667788; EXPECT_EQ(n32, s.dm_verity_version); n32++; EXPECT_EQ(n64, s.image_size); n64++; EXPECT_EQ(n64, s.tree_offset); n64++; EXPECT_EQ(n64, s.tree_size); n64++; EXPECT_EQ(n32, s.data_block_size); n32++; EXPECT_EQ(n32, s.hash_block_size); n32++; EXPECT_EQ(n32, s.fec_num_roots); n32++; EXPECT_EQ(n64, s.fec_offset); n64++; EXPECT_EQ(n64, s.fec_size); n64++; EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASHTREE, s.parent_descriptor.tag); EXPECT_EQ(nbf, s.parent_descriptor.num_bytes_following); EXPECT_EQ(10UL, s.partition_name_len); EXPECT_EQ(10UL, s.salt_len); EXPECT_EQ(10UL, s.root_digest_len); // Check for bad tag. bad = h; bad.parent_descriptor.tag = htobe64(0xf00dd00d); EXPECT_FALSE(avb_hashtree_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 44 bytes (30 + 10 + 10 = 50). bad = h; bad.partition_name_len = htobe32(30); EXPECT_FALSE(avb_hashtree_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 44 bytes (10 + 30 + 10 = 50). bad = h; bad.salt_len = htobe32(30); EXPECT_FALSE(avb_hashtree_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 44 bytes (10 + 10 + 30 = 50). bad = h; bad.root_digest_len = htobe32(30); EXPECT_FALSE(avb_hashtree_descriptor_validate_and_byteswap(&bad, &s)); } TEST_F(UtilTest, HashDescriptorByteswap) { AvbHashDescriptor h; AvbHashDescriptor s; AvbHashDescriptor bad; uint64_t nbf; // Specify 44 bytes of data past the end of the descriptor struct. nbf = 44 + sizeof(AvbHashDescriptor) - sizeof(AvbDescriptor); h.parent_descriptor.num_bytes_following = htobe64(nbf); h.parent_descriptor.tag = htobe64(AVB_DESCRIPTOR_TAG_HASH); h.partition_name_len = htobe32(10); h.salt_len = htobe32(10); h.digest_len = htobe32(10); EXPECT_NE(0, avb_hash_descriptor_validate_and_byteswap(&h, &s)); EXPECT_EQ(AVB_DESCRIPTOR_TAG_HASH, s.parent_descriptor.tag); EXPECT_EQ(nbf, s.parent_descriptor.num_bytes_following); EXPECT_EQ(10UL, s.partition_name_len); EXPECT_EQ(10UL, s.salt_len); EXPECT_EQ(10UL, s.digest_len); // Check for bad tag. bad = h; bad.parent_descriptor.tag = htobe64(0xf00dd00d); EXPECT_EQ(0, avb_hash_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 44 bytes (30 + 10 + 10 = 50). bad = h; bad.partition_name_len = htobe32(30); EXPECT_EQ(0, avb_hash_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 44 bytes (10 + 30 + 10 = 50). bad = h; bad.salt_len = htobe32(30); EXPECT_EQ(0, avb_hash_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 44 bytes (10 + 10 + 30 = 50). bad = h; bad.digest_len = htobe32(30); EXPECT_EQ(0, avb_hash_descriptor_validate_and_byteswap(&bad, &s)); } TEST_F(UtilTest, ChainPartitionDescriptorByteswap) { AvbChainPartitionDescriptor h; AvbChainPartitionDescriptor s; AvbChainPartitionDescriptor bad; uint64_t nbf; // Specify 36 bytes of data past the end of the descriptor struct. nbf = 36 + sizeof(AvbChainPartitionDescriptor) - sizeof(AvbDescriptor); h.parent_descriptor.num_bytes_following = htobe64(nbf); h.parent_descriptor.tag = htobe64(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION); h.rollback_index_location = htobe32(42); h.partition_name_len = htobe32(16); h.public_key_len = htobe32(17); EXPECT_NE(0, avb_chain_partition_descriptor_validate_and_byteswap(&h, &s)); EXPECT_EQ(AVB_DESCRIPTOR_TAG_CHAIN_PARTITION, s.parent_descriptor.tag); EXPECT_EQ(nbf, s.parent_descriptor.num_bytes_following); EXPECT_EQ(42UL, s.rollback_index_location); EXPECT_EQ(16UL, s.partition_name_len); EXPECT_EQ(17UL, s.public_key_len); // Check for bad tag. bad = h; bad.parent_descriptor.tag = htobe64(0xf00dd00d); EXPECT_EQ(0, avb_chain_partition_descriptor_validate_and_byteswap(&bad, &s)); // Check for bad rollback index slot (must be at least 1). bad = h; bad.rollback_index_location = htobe32(0); EXPECT_EQ(0, avb_chain_partition_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 40 bytes (24 + 17 = 41). bad = h; bad.partition_name_len = htobe32(24); EXPECT_EQ(0, avb_chain_partition_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 40 bytes (16 + 25 = 41). bad = h; bad.public_key_len = htobe32(25); EXPECT_EQ(0, avb_chain_partition_descriptor_validate_and_byteswap(&bad, &s)); } TEST_F(UtilTest, PropertyDescriptorByteswap) { AvbPropertyDescriptor h; AvbPropertyDescriptor s; AvbPropertyDescriptor bad; uint64_t nbf; // Specify 40 bytes of data past the end of the descriptor struct. nbf = 40 + sizeof(AvbPropertyDescriptor) - sizeof(AvbDescriptor); h.parent_descriptor.num_bytes_following = htobe64(nbf); h.parent_descriptor.tag = htobe64(AVB_DESCRIPTOR_TAG_PROPERTY); h.key_num_bytes = htobe64(16); h.value_num_bytes = htobe64(17); EXPECT_NE(0, avb_property_descriptor_validate_and_byteswap(&h, &s)); EXPECT_EQ(AVB_DESCRIPTOR_TAG_PROPERTY, s.parent_descriptor.tag); EXPECT_EQ(nbf, s.parent_descriptor.num_bytes_following); EXPECT_EQ(16UL, s.key_num_bytes); EXPECT_EQ(17UL, s.value_num_bytes); // Check for bad tag. bad = h; bad.parent_descriptor.tag = htobe64(0xf00dd00d); EXPECT_EQ(0, avb_property_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 40 bytes (22 + 17 + 2 = 41). bad = h; bad.key_num_bytes = htobe64(22); EXPECT_EQ(0, avb_property_descriptor_validate_and_byteswap(&bad, &s)); // Doesn't fit in 40 bytes (16 + 23 + 2 = 41). bad = h; bad.value_num_bytes = htobe64(23); EXPECT_EQ(0, avb_property_descriptor_validate_and_byteswap(&bad, &s)); } TEST_F(UtilTest, DescriptorByteswap) { AvbDescriptor h; AvbDescriptor s; uint64_t n64; n64 = 0x1122334455667788; h.num_bytes_following = htobe64(n64); n64++; h.tag = htobe64(n64); n64++; EXPECT_NE(0, avb_descriptor_validate_and_byteswap(&h, &s)); n64 = 0x1122334455667788; EXPECT_EQ(n64, s.num_bytes_following); n64++; EXPECT_EQ(n64, s.tag); n64++; // Check that we catch if |num_bytes_following| isn't divisble by 8. h.num_bytes_following = htobe64(7); EXPECT_EQ(0, avb_descriptor_validate_and_byteswap(&h, &s)); } TEST_F(UtilTest, SafeAddition) { uint64_t value; uint64_t pow2_60 = 1ULL << 60; value = 2; EXPECT_NE(0, avb_safe_add_to(&value, 5)); EXPECT_EQ(7UL, value); /* These should not overflow */ value = 1 * pow2_60; EXPECT_NE(0, avb_safe_add_to(&value, 2 * pow2_60)); EXPECT_EQ(3 * pow2_60, value); value = 7 * pow2_60; EXPECT_NE(0, avb_safe_add_to(&value, 8 * pow2_60)); EXPECT_EQ(15 * pow2_60, value); value = 9 * pow2_60; EXPECT_NE(0, avb_safe_add_to(&value, 3 * pow2_60)); EXPECT_EQ(12 * pow2_60, value); value = 0xfffffffffffffffcUL; EXPECT_NE(0, avb_safe_add_to(&value, 2)); EXPECT_EQ(0xfffffffffffffffeUL, value); /* These should overflow. */ value = 8 * pow2_60; EXPECT_EQ(0, avb_safe_add_to(&value, 8 * pow2_60)); value = 0xfffffffffffffffcUL; EXPECT_EQ(0, avb_safe_add_to(&value, 4)); } static int avb_validate_utf8z(const char* data) { return avb_validate_utf8(reinterpret_cast<const uint8_t*>(data), strlen(data)); } TEST_F(UtilTest, UTF8Validation) { // These should succeed. EXPECT_NE(0, avb_validate_utf8z("foo bar")); // Encoding of U+00E6 LATIN SMALL LETTER AE: æ EXPECT_NE(0, avb_validate_utf8z("foo \xC3\xA6 bar")); // Encoding of U+20AC EURO SIGN: € EXPECT_NE(0, avb_validate_utf8z("foo \xE2\x82\xAC bar")); // Encoding of U+1F466 BOY: 👦 EXPECT_NE(0, avb_validate_utf8z("foo \xF0\x9F\x91\xA6 bar")); // All three runes following each other. EXPECT_NE(0, avb_validate_utf8z("\xC3\xA6\xE2\x82\xAC\xF0\x9F\x91\xA6")); // These should fail. EXPECT_EQ(0, avb_validate_utf8z("foo \xF8 bar")); EXPECT_EQ(0, avb_validate_utf8z("\xF8")); // Stops in the middle of Unicode rune. EXPECT_EQ(0, avb_validate_utf8z("foo \xC3")); } TEST_F(UtilTest, StrConcat) { char buf[8]; // These should succeed. EXPECT_NE(0, avb_str_concat(buf, sizeof buf, "foo", 3, "bar1", 4)); // This should fail: Insufficient space. EXPECT_EQ(0, avb_str_concat(buf, sizeof buf, "foo0", 4, "bar1", 4)); } TEST_F(UtilTest, StrStr) { const char* haystack = "abc def abcabc"; EXPECT_EQ(nullptr, avb_strstr(haystack, "needle")); EXPECT_EQ(haystack, avb_strstr(haystack, "abc")); EXPECT_EQ(haystack + 4, avb_strstr(haystack, "def")); EXPECT_EQ(haystack, avb_strstr(haystack, haystack)); } TEST_F(UtilTest, StrvFindStr) { const char* strings[] = {"abcabc", "abc", "def", nullptr}; EXPECT_EQ(nullptr, avb_strv_find_str(strings, "not there", 9)); EXPECT_EQ(strings[1], avb_strv_find_str(strings, "abc", 3)); EXPECT_EQ(strings[2], avb_strv_find_str(strings, "def", 3)); EXPECT_EQ(strings[0], avb_strv_find_str(strings, "abcabc", 6)); } TEST_F(UtilTest, StrReplace) { char* str; str = avb_replace("$(FOO) blah bah $(FOO $(FOO) blah", "$(FOO)", "OK"); EXPECT_EQ("OK blah bah $(FOO OK blah", std::string(str)); avb_free(str); str = avb_replace("$(FOO)", "$(FOO)", "OK"); EXPECT_EQ("OK", std::string(str)); avb_free(str); str = avb_replace(" $(FOO)", "$(FOO)", "OK"); EXPECT_EQ(" OK", std::string(str)); avb_free(str); str = avb_replace("$(FOO) ", "$(FOO)", "OK"); EXPECT_EQ("OK ", std::string(str)); avb_free(str); str = avb_replace("$(FOO)$(FOO)", "$(FOO)", "LONGSTRING"); EXPECT_EQ("LONGSTRINGLONGSTRING", std::string(str)); avb_free(str); } TEST_F(UtilTest, StrDupV) { char* str; str = avb_strdupv("x", "y", "z", NULL); EXPECT_EQ("xyz", std::string(str)); avb_free(str); str = avb_strdupv("Hello", "World", " XYZ", NULL); EXPECT_EQ("HelloWorld XYZ", std::string(str)); avb_free(str); } TEST_F(UtilTest, Crc32) { /* Compare with output of crc32(1): * * $ (echo -n foobar > /tmp/crc32_input); crc32 /tmp/crc32_input * 9ef61f95 */ EXPECT_EQ(uint32_t(0x9ef61f95), avb_crc32((const uint8_t*)"foobar", 6)); } TEST_F(UtilTest, htobe32) { EXPECT_EQ(avb_htobe32(0x12345678), htobe32(0x12345678)); } TEST_F(UtilTest, be32toh) { EXPECT_EQ(avb_be32toh(0x12345678), be32toh(0x12345678)); } TEST_F(UtilTest, htobe64) { EXPECT_EQ(avb_htobe64(0x123456789abcdef0), htobe64(0x123456789abcdef0)); } TEST_F(UtilTest, be64toh) { EXPECT_EQ(avb_be64toh(0x123456789abcdef0), be64toh(0x123456789abcdef0)); } TEST_F(UtilTest, Basename) { EXPECT_EQ("foobar.c", std::string(avb_basename("foobar.c"))); EXPECT_EQ("foobar.c", std::string(avb_basename("/path/to/foobar.c"))); EXPECT_EQ("foobar.c", std::string(avb_basename("a/foobar.c"))); EXPECT_EQ("baz.c", std::string(avb_basename("/baz.c"))); EXPECT_EQ("some_dir/", std::string(avb_basename("some_dir/"))); EXPECT_EQ("some_dir/", std::string(avb_basename("/path/to/some_dir/"))); EXPECT_EQ("some_dir/", std::string(avb_basename("a/some_dir/"))); EXPECT_EQ("some_dir/", std::string(avb_basename("/some_dir/"))); EXPECT_EQ("/", std::string(avb_basename("/"))); } TEST_F(UtilTest, Sha256) { AvbSHA256Ctx ctx; /* Compare with * * $ echo -n foobar |sha256sum * c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2 - */ avb_sha256_init(&ctx); avb_sha256_update(&ctx, (const uint8_t*)"foobar", 6); EXPECT_EQ("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", mem_to_hexstring(avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE)); } // Disabled for now because it takes ~30 seconds to run. TEST_F(UtilTest, DISABLED_Sha256Large) { AvbSHA256Ctx ctx; /* Also check we this works with greater than 4GiB input. Compare with * * $ dd if=/dev/zero bs=1048576 count=4097 |sha256sum * 829816e339ff597ec3ada4c30fc840d3f2298444169d242952a54bcf3fcd7747 - */ const size_t kMebibyte = 1048576; uint8_t* megabuf; megabuf = new uint8_t[kMebibyte]; memset((char*)megabuf, '\0', kMebibyte); avb_sha256_init(&ctx); for (size_t n = 0; n < 4097; n++) { avb_sha256_update(&ctx, megabuf, kMebibyte); } EXPECT_EQ("829816e339ff597ec3ada4c30fc840d3f2298444169d242952a54bcf3fcd7747", mem_to_hexstring(avb_sha256_final(&ctx), AVB_SHA256_DIGEST_SIZE)); delete[] megabuf; } TEST_F(UtilTest, Sha512) { AvbSHA512Ctx ctx; /* Compare with * * $ echo -n foobar |sha512sum * 0a50261ebd1a390fed2bf326f2673c145582a6342d523204973d0219337f81616a8069b012587cf5635f6925f1b56c360230c19b273500ee013e030601bf2425 * - */ avb_sha512_init(&ctx); avb_sha512_update(&ctx, (const uint8_t*)"foobar", 6); EXPECT_EQ( "0a50261ebd1a390fed2bf326f2673c145582a6342d523204973d0219337f81616a8069b0" "12587cf5635f6925f1b56c360230c19b273500ee013e030601bf2425", mem_to_hexstring(avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE)); } // Disabled for now because it takes ~30 seconds to run. TEST_F(UtilTest, DISABLED_Sha512Large) { AvbSHA512Ctx ctx; /* Also check we this works with greater than 4GiB input. Compare with * * $ dd if=/dev/zero bs=1048576 count=4097 |sha512sum * eac1685671cc2060315888746de072398116c0c83b7ee9463f0576e11bfdea9cdd5ddbf291fb3ffc4ee8a1b459c798d9fb9b50b7845e2871c4b1402470aaf4c0 * - */ const size_t kMebibyte = 1048576; uint8_t* megabuf; megabuf = new uint8_t[kMebibyte]; memset((char*)megabuf, '\0', kMebibyte); avb_sha512_init(&ctx); for (size_t n = 0; n < 4097; n++) { avb_sha512_update(&ctx, megabuf, kMebibyte); } EXPECT_EQ( "eac1685671cc2060315888746de072398116c0c83b7ee9463f0576e11bfdea9cdd5ddbf2" "91fb3ffc4ee8a1b459c798d9fb9b50b7845e2871c4b1402470aaf4c0", mem_to_hexstring(avb_sha512_final(&ctx), AVB_SHA512_DIGEST_SIZE)); delete[] megabuf; } } // namespace avb