diff --git a/bbootimg/src/main/java/cfig/io/Struct.java b/bbootimg/src/main/java/cfig/io/Struct.java index b6efbdb..4a1510f 100644 --- a/bbootimg/src/main/java/cfig/io/Struct.java +++ b/bbootimg/src/main/java/cfig/io/Struct.java @@ -151,7 +151,7 @@ public class Struct { continue; } - if (format[0] == Byte.class || format[0] == Character.class || format[0] == PadByte.class) { + if (format[0] == Byte.class || format[0] == Character.class) { byte[] data = new byte[(Integer) format[1]]; assertEquals((int) format[1], iS.read(data)); ret.add(data); diff --git a/bbootimg/src/main/kotlin/Avb.kt b/bbootimg/src/main/kotlin/Avb.kt index 8bfad8f..dca9013 100755 --- a/bbootimg/src/main/kotlin/Avb.kt +++ b/bbootimg/src/main/kotlin/Avb.kt @@ -297,6 +297,9 @@ class Avb { is HashTreeDescriptor -> { ai.auxBlob!!.hashTreeDescriptor.add(it) } + is ChainPartitionDescriptor -> { + ai.auxBlob!!.chainPartitionDescriptor.add(it) + } is UnknownDescriptor -> { ai.auxBlob!!.unknownDescriptors.add(it) } diff --git a/bbootimg/src/main/kotlin/avb/AVBInfo.kt b/bbootimg/src/main/kotlin/avb/AVBInfo.kt index b3696e6..2364955 100755 --- a/bbootimg/src/main/kotlin/avb/AVBInfo.kt +++ b/bbootimg/src/main/kotlin/avb/AVBInfo.kt @@ -23,6 +23,7 @@ class AVBInfo(var header: Header? = null, var hashTreeDescriptor: MutableList = mutableListOf(), var hashDescriptors: MutableList = mutableListOf(), var kernelCmdlineDescriptor: MutableList = mutableListOf(), + var chainPartitionDescriptor: MutableList = mutableListOf(), var unknownDescriptors: MutableList = mutableListOf() ) { data class PubKeyInfo( diff --git a/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt index 1aa0284..6b5243b 100644 --- a/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/ChainPartitionDescriptor.kt @@ -1,10 +1,68 @@ package avb.desc -class ChainPartitionDescriptor { +import cfig.Helper +import cfig.io.Struct +import java.io.InputStream +import java.security.MessageDigest +import java.util.* + +class ChainPartitionDescriptor( + var rollback_index_location: Long = 0, + var partition_name_len: Long = 0, + var public_key_len: Long = 0, + var partition_name: String = "", + var pubkey: ByteArray = byteArrayOf(), + var pubkey_sha1: String = "" +) : Descriptor(TAG, 0, 0) { + override fun encode(): ByteArray { + this.partition_name_len = this.partition_name.length.toLong() + this.public_key_len = this.pubkey.size.toLong() + this.num_bytes_following = SIZE + this.partition_name_len + this.public_key_len - 16 + val nbf_with_padding = Helper.round_to_multiple(this.num_bytes_following, 8) + val padding_size = nbf_with_padding - this.num_bytes_following + val desc = Struct(FORMAT_STRING + "${RESERVED}s").pack( + TAG, + nbf_with_padding, + this.rollback_index_location, + this.partition_name.length, + this.public_key_len, + null) + val padding = Struct("${padding_size}s").pack(null) + return Helper.join(desc, this.partition_name.toByteArray(), this.pubkey, padding) + } + companion object { const val TAG = 4L const val RESERVED = 64 - const val SIZE = 28 + RESERVED + const val SIZE = 28L + RESERVED const val FORMAT_STRING = "!2Q3L" } + + constructor(data: InputStream, seq: Int = 0) : this() { + if (SIZE - RESERVED != Struct(FORMAT_STRING).calcSize().toLong()) { + throw RuntimeException() + } + this.sequence = seq + val info = Struct(FORMAT_STRING + "${RESERVED}s").unpack(data) + this.tag = info[0] as Long + this.num_bytes_following = info[1] as Long + this.rollback_index_location = info[2] as Long + this.partition_name_len = info[3] as Long + this.public_key_len = info[4] as Long + val expectedSize = Helper.round_to_multiple( + SIZE - 16 + this.partition_name_len + this.public_key_len, 8) + if (this.tag != TAG || this.num_bytes_following != expectedSize) { + throw IllegalArgumentException("Given data does not look like a chain/delegation descriptor") + } + val info2 = Struct("${this.partition_name_len}s${this.public_key_len}s").unpack(data) + this.partition_name = Helper.toCString(info2[0] as ByteArray) + this.pubkey = info2[1] as ByteArray + val md = MessageDigest.getInstance("SHA1") + md.update(this.pubkey) + this.pubkey_sha1 = Helper.toHexString(md.digest()) + } + + override fun toString(): String { + return "ChainPartitionDescriptor(partition=${this.partition_name}, pubkey=${Arrays.toString(this.pubkey)}" + } } \ No newline at end of file diff --git a/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt index 3999074..8efec44 100755 --- a/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/HashDescriptor.kt @@ -9,6 +9,7 @@ import java.security.MessageDigest class HashDescriptor(var image_size: Long = 0L, var hash_algorithm: ByteArray = byteArrayOf(), + var hash_algorithm_str: String = "", var partition_name_len: Long = 0L, var salt_len: Long = 0L, var digest_len: Long = 0L, @@ -36,6 +37,7 @@ class HashDescriptor(var image_size: Long = 0L, this.partition_name = Helper.toCString(payload[0] as ByteArray) this.salt = payload[1] as ByteArray this.digest = payload[2] as ByteArray + this.hash_algorithm_str = Helper.toCString(this.hash_algorithm) } override fun encode(): ByteArray { diff --git a/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt index 8062e49..041daa4 100755 --- a/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt @@ -44,6 +44,9 @@ class UnknownDescriptor(var data: ByteArray = byteArrayOf()) : Descriptor(0, 0, 3L -> { KernelCmdlineDescriptor(ByteArrayInputStream(this.encode()), this.sequence) } + 4L -> { + ChainPartitionDescriptor(ByteArrayInputStream(this.encode()), this.sequence) + } else -> { this }