Skip to content

Commit 2c11dd4

Browse files
kousuclaude
andcommitted
Update AVB hash header to match repacked contents.
This follows topjohnwu#9830 by recomputing the AVB hash. Apparently few (no?) devices actually respect this hash in the wild at the moment, but it's good to be prepared. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent fe7c726 commit 2c11dd4

1 file changed

Lines changed: 57 additions & 2 deletions

File tree

native/src/boot/bootimg.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,13 +1026,68 @@ void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp) {
10261026
vbmeta->flags = __builtin_bswap32(3);
10271027
}
10281028

1029-
// Sync hash descriptor image_size with the new AOSP portion size.
1030-
// Without this, some bootloaders (e.g. Motorola) reject images.
1029+
// Patch hash descriptor
10311030
for (auto &desc : vbmeta->descriptors()) {
10321031
if (__builtin_bswap64(desc.tag) != AVB_DESCRIPTOR_TAG_HASH)
10331032
continue;
1033+
1034+
// enforce size limits; protect against adversarial input.
1035+
size_t buf_remaining = out.data() + out.size() - reinterpret_cast<uint8_t *>(&desc);
1036+
if (buf_remaining < __builtin_bswap64(desc.num_bytes) || buf_remaining - __builtin_bswap64(desc.num_bytes) < sizeof(AvbDescriptor)) {
1037+
// beware: both conditions are necessary because underflow in the subtraction could wrap
1038+
fprintf(stderr, "AVB hash descriptor num_bytes overflows buffer\n");
1039+
break;
1040+
}
1041+
1042+
uint8_t *desc_end = reinterpret_cast<uint8_t *>(&desc) + sizeof(AvbDescriptor) + __builtin_bswap64(desc.num_bytes);
1043+
10341044
auto &hd = reinterpret_cast<AvbHashDescriptor &>(desc);
1045+
1046+
// Update image_size
10351047
hd.image_size = __builtin_bswap64(aosp_img_size);
1048+
1049+
// Recompute hash
1050+
auto *algo = reinterpret_cast<char *>(hd.hash_algorithm);
1051+
bool is_sha1 = memcmp(hd.hash_algorithm, "sha1", 5) == 0;
1052+
bool is_sha256 = memcmp(hd.hash_algorithm, "sha256", 7) == 0;
1053+
1054+
uint32_t name_len = __builtin_bswap32(hd.partition_name_len);
1055+
uint32_t salt_len = __builtin_bswap32(hd.salt_len);
1056+
uint32_t digest_len = __builtin_bswap32(hd.digest_len);
1057+
1058+
// Get pointers to the (flexibly sized) payloads, checking each against desc_end
1059+
uint8_t *name = reinterpret_cast<uint8_t *>(&hd + 1);
1060+
if (name > desc_end) {
1061+
fprintf(stderr, "AVB hash descriptor overflows bounds\n");
1062+
break;
1063+
}
1064+
if ((size_t)(desc_end - name) < name_len) {
1065+
fprintf(stderr, "AVB hash descriptor name of %u bytes overflows bounds\n", name_len);
1066+
break;
1067+
}
1068+
uint8_t *salt = name + name_len;
1069+
if ((size_t)(desc_end - salt) < salt_len) {
1070+
fprintf(stderr, "AVB hash descriptor salt of %u bytes overflows bounds\n", salt_len);
1071+
break;
1072+
}
1073+
uint8_t *digest = salt + salt_len;
1074+
if ((size_t)(desc_end - digest) < digest_len) {
1075+
fprintf(stderr, "AVB hash descriptor digest of %u bytes overflows bounds\n", digest_len);
1076+
break;
1077+
}
1078+
1079+
if (is_sha1 || is_sha256) {
1080+
digest_len = is_sha1 ? 20 : 32;
1081+
hd.digest_len = __builtin_bswap32(digest_len);
1082+
1083+
auto ctx = get_sha(is_sha1);
1084+
ctx->update(byte_view(salt, salt_len));
1085+
ctx->update(byte_view(out.data(), aosp_img_size));
1086+
ctx->finalize_into(byte_data(digest, digest_len));
1087+
} else {
1088+
fprintf(stderr, "Unsupported AVB hash algorithm: %.32s — zeroing digest\n", algo);
1089+
memset(digest, 0, desc_end - digest);
1090+
}
10361091
break;
10371092
}
10381093
}

0 commit comments

Comments
 (0)