1*d289c2baSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*d289c2baSAndroid Build Coastguard Worker 3*d289c2baSAndroid Build Coastguard Worker# Copyright 2016, The Android Open Source Project 4*d289c2baSAndroid Build Coastguard Worker# 5*d289c2baSAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person 6*d289c2baSAndroid Build Coastguard Worker# obtaining a copy of this software and associated documentation 7*d289c2baSAndroid Build Coastguard Worker# files (the "Software"), to deal in the Software without 8*d289c2baSAndroid Build Coastguard Worker# restriction, including without limitation the rights to use, copy, 9*d289c2baSAndroid Build Coastguard Worker# modify, merge, publish, distribute, sublicense, and/or sell copies 10*d289c2baSAndroid Build Coastguard Worker# of the Software, and to permit persons to whom the Software is 11*d289c2baSAndroid Build Coastguard Worker# furnished to do so, subject to the following conditions: 12*d289c2baSAndroid Build Coastguard Worker# 13*d289c2baSAndroid Build Coastguard Worker# The above copyright notice and this permission notice shall be 14*d289c2baSAndroid Build Coastguard Worker# included in all copies or substantial portions of the Software. 15*d289c2baSAndroid Build Coastguard Worker# 16*d289c2baSAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17*d289c2baSAndroid Build Coastguard Worker# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18*d289c2baSAndroid Build Coastguard Worker# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19*d289c2baSAndroid Build Coastguard Worker# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20*d289c2baSAndroid Build Coastguard Worker# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21*d289c2baSAndroid Build Coastguard Worker# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22*d289c2baSAndroid Build Coastguard Worker# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23*d289c2baSAndroid Build Coastguard Worker# SOFTWARE. 24*d289c2baSAndroid Build Coastguard Worker# 25*d289c2baSAndroid Build Coastguard Worker"""Command-line tool for working with Android Verified Boot images.""" 26*d289c2baSAndroid Build Coastguard Worker 27*d289c2baSAndroid Build Coastguard Workerimport argparse 28*d289c2baSAndroid Build Coastguard Workerimport binascii 29*d289c2baSAndroid Build Coastguard Workerimport bisect 30*d289c2baSAndroid Build Coastguard Workerimport hashlib 31*d289c2baSAndroid Build Coastguard Workerimport json 32*d289c2baSAndroid Build Coastguard Workerimport math 33*d289c2baSAndroid Build Coastguard Workerimport os 34*d289c2baSAndroid Build Coastguard Workerimport struct 35*d289c2baSAndroid Build Coastguard Workerimport subprocess 36*d289c2baSAndroid Build Coastguard Workerimport sys 37*d289c2baSAndroid Build Coastguard Workerimport tempfile 38*d289c2baSAndroid Build Coastguard Workerimport time 39*d289c2baSAndroid Build Coastguard Worker 40*d289c2baSAndroid Build Coastguard Worker# Keep in sync with libavb/avb_version.h. 41*d289c2baSAndroid Build Coastguard WorkerAVB_VERSION_MAJOR = 1 42*d289c2baSAndroid Build Coastguard WorkerAVB_VERSION_MINOR = 3 43*d289c2baSAndroid Build Coastguard WorkerAVB_VERSION_SUB = 0 44*d289c2baSAndroid Build Coastguard Worker 45*d289c2baSAndroid Build Coastguard Worker# Keep in sync with libavb/avb_footer.h. 46*d289c2baSAndroid Build Coastguard WorkerAVB_FOOTER_VERSION_MAJOR = 1 47*d289c2baSAndroid Build Coastguard WorkerAVB_FOOTER_VERSION_MINOR = 0 48*d289c2baSAndroid Build Coastguard Worker 49*d289c2baSAndroid Build Coastguard WorkerAVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED = 1 50*d289c2baSAndroid Build Coastguard Worker 51*d289c2baSAndroid Build Coastguard Worker# Configuration for enabling logging of calls to avbtool. 52*d289c2baSAndroid Build Coastguard WorkerAVB_INVOCATION_LOGFILE = os.environ.get('AVB_INVOCATION_LOGFILE') 53*d289c2baSAndroid Build Coastguard Worker 54*d289c2baSAndroid Build Coastguard Worker# Known values for certificate "usage" field. These values must match the 55*d289c2baSAndroid Build Coastguard Worker# libavb_cert implementation. 56*d289c2baSAndroid Build Coastguard Worker# 57*d289c2baSAndroid Build Coastguard Worker# The "android.things" substring is only for historical reasons; these strings 58*d289c2baSAndroid Build Coastguard Worker# are used for the general-purpose libavb_cert extension and are not specific 59*d289c2baSAndroid Build Coastguard Worker# to the Android Things project. However, changing them would be a breaking 60*d289c2baSAndroid Build Coastguard Worker# change so it's simpler to leave them as-is. 61*d289c2baSAndroid Build Coastguard WorkerCERT_USAGE_SIGNING = 'com.google.android.things.vboot' 62*d289c2baSAndroid Build Coastguard WorkerCERT_USAGE_INTERMEDIATE_AUTHORITY = 'com.google.android.things.vboot.ca' 63*d289c2baSAndroid Build Coastguard WorkerCERT_USAGE_UNLOCK = 'com.google.android.things.vboot.unlock' 64*d289c2baSAndroid Build Coastguard Worker 65*d289c2baSAndroid Build Coastguard Worker 66*d289c2baSAndroid Build Coastguard Workerclass AvbError(Exception): 67*d289c2baSAndroid Build Coastguard Worker """Application-specific errors. 68*d289c2baSAndroid Build Coastguard Worker 69*d289c2baSAndroid Build Coastguard Worker These errors represent issues for which a stack-trace should not be 70*d289c2baSAndroid Build Coastguard Worker presented. 71*d289c2baSAndroid Build Coastguard Worker 72*d289c2baSAndroid Build Coastguard Worker Attributes: 73*d289c2baSAndroid Build Coastguard Worker message: Error message. 74*d289c2baSAndroid Build Coastguard Worker """ 75*d289c2baSAndroid Build Coastguard Worker 76*d289c2baSAndroid Build Coastguard Worker def __init__(self, message): 77*d289c2baSAndroid Build Coastguard Worker Exception.__init__(self, message) 78*d289c2baSAndroid Build Coastguard Worker 79*d289c2baSAndroid Build Coastguard Worker 80*d289c2baSAndroid Build Coastguard Workerclass Algorithm(object): 81*d289c2baSAndroid Build Coastguard Worker """Contains details about an algorithm. 82*d289c2baSAndroid Build Coastguard Worker 83*d289c2baSAndroid Build Coastguard Worker See the avb_vbmeta_image.h file for more details about algorithms. 84*d289c2baSAndroid Build Coastguard Worker 85*d289c2baSAndroid Build Coastguard Worker The constant |ALGORITHMS| is a dictionary from human-readable 86*d289c2baSAndroid Build Coastguard Worker names (e.g 'SHA256_RSA2048') to instances of this class. 87*d289c2baSAndroid Build Coastguard Worker 88*d289c2baSAndroid Build Coastguard Worker Attributes: 89*d289c2baSAndroid Build Coastguard Worker algorithm_type: Integer code corresponding to |AvbAlgorithmType|. 90*d289c2baSAndroid Build Coastguard Worker hash_name: Empty or a name from |hashlib.algorithms|. 91*d289c2baSAndroid Build Coastguard Worker hash_num_bytes: Number of bytes used to store the hash. 92*d289c2baSAndroid Build Coastguard Worker signature_num_bytes: Number of bytes used to store the signature. 93*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes: Number of bytes used to store the public key. 94*d289c2baSAndroid Build Coastguard Worker padding: Padding used for signature as bytes, if any. 95*d289c2baSAndroid Build Coastguard Worker """ 96*d289c2baSAndroid Build Coastguard Worker 97*d289c2baSAndroid Build Coastguard Worker def __init__(self, algorithm_type, hash_name, hash_num_bytes, 98*d289c2baSAndroid Build Coastguard Worker signature_num_bytes, public_key_num_bytes, padding): 99*d289c2baSAndroid Build Coastguard Worker self.algorithm_type = algorithm_type 100*d289c2baSAndroid Build Coastguard Worker self.hash_name = hash_name 101*d289c2baSAndroid Build Coastguard Worker self.hash_num_bytes = hash_num_bytes 102*d289c2baSAndroid Build Coastguard Worker self.signature_num_bytes = signature_num_bytes 103*d289c2baSAndroid Build Coastguard Worker self.public_key_num_bytes = public_key_num_bytes 104*d289c2baSAndroid Build Coastguard Worker self.padding = padding 105*d289c2baSAndroid Build Coastguard Worker 106*d289c2baSAndroid Build Coastguard Worker 107*d289c2baSAndroid Build Coastguard Worker# This must be kept in sync with the avb_crypto.h file. 108*d289c2baSAndroid Build Coastguard Worker# 109*d289c2baSAndroid Build Coastguard Worker# The PKC1-v1.5 padding is a blob of binary DER of ASN.1 and is 110*d289c2baSAndroid Build Coastguard Worker# obtained from section 5.2.2 of RFC 4880. 111*d289c2baSAndroid Build Coastguard WorkerALGORITHMS = { 112*d289c2baSAndroid Build Coastguard Worker 'NONE': Algorithm( 113*d289c2baSAndroid Build Coastguard Worker algorithm_type=0, # AVB_ALGORITHM_TYPE_NONE 114*d289c2baSAndroid Build Coastguard Worker hash_name='', 115*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=0, 116*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=0, 117*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=0, 118*d289c2baSAndroid Build Coastguard Worker padding=b''), 119*d289c2baSAndroid Build Coastguard Worker 'SHA256_RSA2048': Algorithm( 120*d289c2baSAndroid Build Coastguard Worker algorithm_type=1, # AVB_ALGORITHM_TYPE_SHA256_RSA2048 121*d289c2baSAndroid Build Coastguard Worker hash_name='sha256', 122*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=32, 123*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=256, 124*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=8 + 2*2048//8, 125*d289c2baSAndroid Build Coastguard Worker padding=bytes(bytearray([ 126*d289c2baSAndroid Build Coastguard Worker # PKCS1-v1_5 padding 127*d289c2baSAndroid Build Coastguard Worker 0x00, 0x01] + [0xff]*202 + [0x00] + [ 128*d289c2baSAndroid Build Coastguard Worker # ASN.1 header 129*d289c2baSAndroid Build Coastguard Worker 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 130*d289c2baSAndroid Build Coastguard Worker 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 131*d289c2baSAndroid Build Coastguard Worker 0x00, 0x04, 0x20, 132*d289c2baSAndroid Build Coastguard Worker ]))), 133*d289c2baSAndroid Build Coastguard Worker 'SHA256_RSA4096': Algorithm( 134*d289c2baSAndroid Build Coastguard Worker algorithm_type=2, # AVB_ALGORITHM_TYPE_SHA256_RSA4096 135*d289c2baSAndroid Build Coastguard Worker hash_name='sha256', 136*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=32, 137*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=512, 138*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=8 + 2*4096//8, 139*d289c2baSAndroid Build Coastguard Worker padding=bytes(bytearray([ 140*d289c2baSAndroid Build Coastguard Worker # PKCS1-v1_5 padding 141*d289c2baSAndroid Build Coastguard Worker 0x00, 0x01] + [0xff]*458 + [0x00] + [ 142*d289c2baSAndroid Build Coastguard Worker # ASN.1 header 143*d289c2baSAndroid Build Coastguard Worker 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 144*d289c2baSAndroid Build Coastguard Worker 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 145*d289c2baSAndroid Build Coastguard Worker 0x00, 0x04, 0x20, 146*d289c2baSAndroid Build Coastguard Worker ]))), 147*d289c2baSAndroid Build Coastguard Worker 'SHA256_RSA8192': Algorithm( 148*d289c2baSAndroid Build Coastguard Worker algorithm_type=3, # AVB_ALGORITHM_TYPE_SHA256_RSA8192 149*d289c2baSAndroid Build Coastguard Worker hash_name='sha256', 150*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=32, 151*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=1024, 152*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=8 + 2*8192//8, 153*d289c2baSAndroid Build Coastguard Worker padding=bytes(bytearray([ 154*d289c2baSAndroid Build Coastguard Worker # PKCS1-v1_5 padding 155*d289c2baSAndroid Build Coastguard Worker 0x00, 0x01] + [0xff]*970 + [0x00] + [ 156*d289c2baSAndroid Build Coastguard Worker # ASN.1 header 157*d289c2baSAndroid Build Coastguard Worker 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 158*d289c2baSAndroid Build Coastguard Worker 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 159*d289c2baSAndroid Build Coastguard Worker 0x00, 0x04, 0x20, 160*d289c2baSAndroid Build Coastguard Worker ]))), 161*d289c2baSAndroid Build Coastguard Worker 'SHA512_RSA2048': Algorithm( 162*d289c2baSAndroid Build Coastguard Worker algorithm_type=4, # AVB_ALGORITHM_TYPE_SHA512_RSA2048 163*d289c2baSAndroid Build Coastguard Worker hash_name='sha512', 164*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=64, 165*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=256, 166*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=8 + 2*2048//8, 167*d289c2baSAndroid Build Coastguard Worker padding=bytes(bytearray([ 168*d289c2baSAndroid Build Coastguard Worker # PKCS1-v1_5 padding 169*d289c2baSAndroid Build Coastguard Worker 0x00, 0x01] + [0xff]*170 + [0x00] + [ 170*d289c2baSAndroid Build Coastguard Worker # ASN.1 header 171*d289c2baSAndroid Build Coastguard Worker 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 172*d289c2baSAndroid Build Coastguard Worker 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 173*d289c2baSAndroid Build Coastguard Worker 0x00, 0x04, 0x40 174*d289c2baSAndroid Build Coastguard Worker ]))), 175*d289c2baSAndroid Build Coastguard Worker 'SHA512_RSA4096': Algorithm( 176*d289c2baSAndroid Build Coastguard Worker algorithm_type=5, # AVB_ALGORITHM_TYPE_SHA512_RSA4096 177*d289c2baSAndroid Build Coastguard Worker hash_name='sha512', 178*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=64, 179*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=512, 180*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=8 + 2*4096//8, 181*d289c2baSAndroid Build Coastguard Worker padding=bytes(bytearray([ 182*d289c2baSAndroid Build Coastguard Worker # PKCS1-v1_5 padding 183*d289c2baSAndroid Build Coastguard Worker 0x00, 0x01] + [0xff]*426 + [0x00] + [ 184*d289c2baSAndroid Build Coastguard Worker # ASN.1 header 185*d289c2baSAndroid Build Coastguard Worker 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 186*d289c2baSAndroid Build Coastguard Worker 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 187*d289c2baSAndroid Build Coastguard Worker 0x00, 0x04, 0x40 188*d289c2baSAndroid Build Coastguard Worker ]))), 189*d289c2baSAndroid Build Coastguard Worker 'SHA512_RSA8192': Algorithm( 190*d289c2baSAndroid Build Coastguard Worker algorithm_type=6, # AVB_ALGORITHM_TYPE_SHA512_RSA8192 191*d289c2baSAndroid Build Coastguard Worker hash_name='sha512', 192*d289c2baSAndroid Build Coastguard Worker hash_num_bytes=64, 193*d289c2baSAndroid Build Coastguard Worker signature_num_bytes=1024, 194*d289c2baSAndroid Build Coastguard Worker public_key_num_bytes=8 + 2*8192//8, 195*d289c2baSAndroid Build Coastguard Worker padding=bytes(bytearray([ 196*d289c2baSAndroid Build Coastguard Worker # PKCS1-v1_5 padding 197*d289c2baSAndroid Build Coastguard Worker 0x00, 0x01] + [0xff]*938 + [0x00] + [ 198*d289c2baSAndroid Build Coastguard Worker # ASN.1 header 199*d289c2baSAndroid Build Coastguard Worker 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 200*d289c2baSAndroid Build Coastguard Worker 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 201*d289c2baSAndroid Build Coastguard Worker 0x00, 0x04, 0x40 202*d289c2baSAndroid Build Coastguard Worker ]))), 203*d289c2baSAndroid Build Coastguard Worker} 204*d289c2baSAndroid Build Coastguard Worker 205*d289c2baSAndroid Build Coastguard Worker 206*d289c2baSAndroid Build Coastguard Workerdef get_release_string(): 207*d289c2baSAndroid Build Coastguard Worker """Calculates the release string to use in the VBMeta struct.""" 208*d289c2baSAndroid Build Coastguard Worker # Keep in sync with libavb/avb_version.c:avb_version_string(). 209*d289c2baSAndroid Build Coastguard Worker return 'avbtool {}.{}.{}'.format(AVB_VERSION_MAJOR, 210*d289c2baSAndroid Build Coastguard Worker AVB_VERSION_MINOR, 211*d289c2baSAndroid Build Coastguard Worker AVB_VERSION_SUB) 212*d289c2baSAndroid Build Coastguard Worker 213*d289c2baSAndroid Build Coastguard Worker 214*d289c2baSAndroid Build Coastguard Workerdef round_to_multiple(number, size): 215*d289c2baSAndroid Build Coastguard Worker """Rounds a number up to nearest multiple of another number. 216*d289c2baSAndroid Build Coastguard Worker 217*d289c2baSAndroid Build Coastguard Worker Arguments: 218*d289c2baSAndroid Build Coastguard Worker number: The number to round up. 219*d289c2baSAndroid Build Coastguard Worker size: The multiple to round up to. 220*d289c2baSAndroid Build Coastguard Worker 221*d289c2baSAndroid Build Coastguard Worker Returns: 222*d289c2baSAndroid Build Coastguard Worker If |number| is a multiple of |size|, returns |number|, otherwise 223*d289c2baSAndroid Build Coastguard Worker returns |number| + |size|. 224*d289c2baSAndroid Build Coastguard Worker """ 225*d289c2baSAndroid Build Coastguard Worker remainder = number % size 226*d289c2baSAndroid Build Coastguard Worker if remainder == 0: 227*d289c2baSAndroid Build Coastguard Worker return number 228*d289c2baSAndroid Build Coastguard Worker return number + size - remainder 229*d289c2baSAndroid Build Coastguard Worker 230*d289c2baSAndroid Build Coastguard Worker 231*d289c2baSAndroid Build Coastguard Workerdef round_to_pow2(number): 232*d289c2baSAndroid Build Coastguard Worker """Rounds a number up to the next power of 2. 233*d289c2baSAndroid Build Coastguard Worker 234*d289c2baSAndroid Build Coastguard Worker Arguments: 235*d289c2baSAndroid Build Coastguard Worker number: The number to round up. 236*d289c2baSAndroid Build Coastguard Worker 237*d289c2baSAndroid Build Coastguard Worker Returns: 238*d289c2baSAndroid Build Coastguard Worker If |number| is already a power of 2 then |number| is 239*d289c2baSAndroid Build Coastguard Worker returned. Otherwise the smallest power of 2 greater than |number| 240*d289c2baSAndroid Build Coastguard Worker is returned. 241*d289c2baSAndroid Build Coastguard Worker """ 242*d289c2baSAndroid Build Coastguard Worker return 2**((number - 1).bit_length()) 243*d289c2baSAndroid Build Coastguard Worker 244*d289c2baSAndroid Build Coastguard Worker 245*d289c2baSAndroid Build Coastguard Workerdef encode_long(num_bits, value): 246*d289c2baSAndroid Build Coastguard Worker """Encodes a long to a bytearray() using a given amount of bits. 247*d289c2baSAndroid Build Coastguard Worker 248*d289c2baSAndroid Build Coastguard Worker This number is written big-endian, e.g. with the most significant 249*d289c2baSAndroid Build Coastguard Worker bit first. 250*d289c2baSAndroid Build Coastguard Worker 251*d289c2baSAndroid Build Coastguard Worker This is the reverse of decode_long(). 252*d289c2baSAndroid Build Coastguard Worker 253*d289c2baSAndroid Build Coastguard Worker Arguments: 254*d289c2baSAndroid Build Coastguard Worker num_bits: The number of bits to write, e.g. 2048. 255*d289c2baSAndroid Build Coastguard Worker value: The value to write. 256*d289c2baSAndroid Build Coastguard Worker 257*d289c2baSAndroid Build Coastguard Worker Returns: 258*d289c2baSAndroid Build Coastguard Worker A bytearray() with the encoded long. 259*d289c2baSAndroid Build Coastguard Worker """ 260*d289c2baSAndroid Build Coastguard Worker ret = bytearray() 261*d289c2baSAndroid Build Coastguard Worker for bit_pos in range(num_bits, 0, -8): 262*d289c2baSAndroid Build Coastguard Worker octet = (value >> (bit_pos - 8)) & 0xff 263*d289c2baSAndroid Build Coastguard Worker ret.extend(struct.pack('!B', octet)) 264*d289c2baSAndroid Build Coastguard Worker return ret 265*d289c2baSAndroid Build Coastguard Worker 266*d289c2baSAndroid Build Coastguard Worker 267*d289c2baSAndroid Build Coastguard Workerdef decode_long(blob): 268*d289c2baSAndroid Build Coastguard Worker """Decodes a long from a bytearray() using a given amount of bits. 269*d289c2baSAndroid Build Coastguard Worker 270*d289c2baSAndroid Build Coastguard Worker This number is expected to be in big-endian, e.g. with the most 271*d289c2baSAndroid Build Coastguard Worker significant bit first. 272*d289c2baSAndroid Build Coastguard Worker 273*d289c2baSAndroid Build Coastguard Worker This is the reverse of encode_long(). 274*d289c2baSAndroid Build Coastguard Worker 275*d289c2baSAndroid Build Coastguard Worker Arguments: 276*d289c2baSAndroid Build Coastguard Worker blob: A bytearray() with the encoded long. 277*d289c2baSAndroid Build Coastguard Worker 278*d289c2baSAndroid Build Coastguard Worker Returns: 279*d289c2baSAndroid Build Coastguard Worker The decoded value. 280*d289c2baSAndroid Build Coastguard Worker """ 281*d289c2baSAndroid Build Coastguard Worker ret = 0 282*d289c2baSAndroid Build Coastguard Worker for b in bytearray(blob): 283*d289c2baSAndroid Build Coastguard Worker ret *= 256 284*d289c2baSAndroid Build Coastguard Worker ret += b 285*d289c2baSAndroid Build Coastguard Worker return ret 286*d289c2baSAndroid Build Coastguard Worker 287*d289c2baSAndroid Build Coastguard Worker 288*d289c2baSAndroid Build Coastguard Workerdef egcd(a, b): 289*d289c2baSAndroid Build Coastguard Worker """Calculate greatest common divisor of two numbers. 290*d289c2baSAndroid Build Coastguard Worker 291*d289c2baSAndroid Build Coastguard Worker This implementation uses a recursive version of the extended 292*d289c2baSAndroid Build Coastguard Worker Euclidian algorithm. 293*d289c2baSAndroid Build Coastguard Worker 294*d289c2baSAndroid Build Coastguard Worker Arguments: 295*d289c2baSAndroid Build Coastguard Worker a: First number. 296*d289c2baSAndroid Build Coastguard Worker b: Second number. 297*d289c2baSAndroid Build Coastguard Worker 298*d289c2baSAndroid Build Coastguard Worker Returns: 299*d289c2baSAndroid Build Coastguard Worker A tuple (gcd, x, y) that where |gcd| is the greatest common 300*d289c2baSAndroid Build Coastguard Worker divisor of |a| and |b| and |a|*|x| + |b|*|y| = |gcd|. 301*d289c2baSAndroid Build Coastguard Worker """ 302*d289c2baSAndroid Build Coastguard Worker if a == 0: 303*d289c2baSAndroid Build Coastguard Worker return (b, 0, 1) 304*d289c2baSAndroid Build Coastguard Worker g, y, x = egcd(b % a, a) 305*d289c2baSAndroid Build Coastguard Worker return (g, x - (b // a) * y, y) 306*d289c2baSAndroid Build Coastguard Worker 307*d289c2baSAndroid Build Coastguard Worker 308*d289c2baSAndroid Build Coastguard Workerdef modinv(a, m): 309*d289c2baSAndroid Build Coastguard Worker """Calculate modular multiplicative inverse of |a| modulo |m|. 310*d289c2baSAndroid Build Coastguard Worker 311*d289c2baSAndroid Build Coastguard Worker This calculates the number |x| such that |a| * |x| == 1 (modulo 312*d289c2baSAndroid Build Coastguard Worker |m|). This number only exists if |a| and |m| are co-prime - |None| 313*d289c2baSAndroid Build Coastguard Worker is returned if this isn't true. 314*d289c2baSAndroid Build Coastguard Worker 315*d289c2baSAndroid Build Coastguard Worker Arguments: 316*d289c2baSAndroid Build Coastguard Worker a: The number to calculate a modular inverse of. 317*d289c2baSAndroid Build Coastguard Worker m: The modulo to use. 318*d289c2baSAndroid Build Coastguard Worker 319*d289c2baSAndroid Build Coastguard Worker Returns: 320*d289c2baSAndroid Build Coastguard Worker The modular multiplicative inverse of |a| and |m| or |None| if 321*d289c2baSAndroid Build Coastguard Worker these numbers are not co-prime. 322*d289c2baSAndroid Build Coastguard Worker """ 323*d289c2baSAndroid Build Coastguard Worker gcd, x, _ = egcd(a, m) 324*d289c2baSAndroid Build Coastguard Worker if gcd != 1: 325*d289c2baSAndroid Build Coastguard Worker return None # modular inverse does not exist 326*d289c2baSAndroid Build Coastguard Worker return x % m 327*d289c2baSAndroid Build Coastguard Worker 328*d289c2baSAndroid Build Coastguard Worker 329*d289c2baSAndroid Build Coastguard Workerdef parse_number(string): 330*d289c2baSAndroid Build Coastguard Worker """Parse a string as a number. 331*d289c2baSAndroid Build Coastguard Worker 332*d289c2baSAndroid Build Coastguard Worker This is just a short-hand for int(string, 0) suitable for use in the 333*d289c2baSAndroid Build Coastguard Worker |type| parameter of |ArgumentParser|'s add_argument() function. An 334*d289c2baSAndroid Build Coastguard Worker improvement to just using type=int is that this function supports 335*d289c2baSAndroid Build Coastguard Worker numbers in other bases, e.g. "0x1234". 336*d289c2baSAndroid Build Coastguard Worker 337*d289c2baSAndroid Build Coastguard Worker Arguments: 338*d289c2baSAndroid Build Coastguard Worker string: The string to parse. 339*d289c2baSAndroid Build Coastguard Worker 340*d289c2baSAndroid Build Coastguard Worker Returns: 341*d289c2baSAndroid Build Coastguard Worker The parsed integer. 342*d289c2baSAndroid Build Coastguard Worker 343*d289c2baSAndroid Build Coastguard Worker Raises: 344*d289c2baSAndroid Build Coastguard Worker ValueError: If the number could not be parsed. 345*d289c2baSAndroid Build Coastguard Worker """ 346*d289c2baSAndroid Build Coastguard Worker return int(string, 0) 347*d289c2baSAndroid Build Coastguard Worker 348*d289c2baSAndroid Build Coastguard Worker 349*d289c2baSAndroid Build Coastguard Workerclass RSAPublicKey(object): 350*d289c2baSAndroid Build Coastguard Worker """Data structure used for a RSA public key. 351*d289c2baSAndroid Build Coastguard Worker 352*d289c2baSAndroid Build Coastguard Worker Attributes: 353*d289c2baSAndroid Build Coastguard Worker exponent: The key exponent. 354*d289c2baSAndroid Build Coastguard Worker modulus: The key modulus. 355*d289c2baSAndroid Build Coastguard Worker num_bits: The key size. 356*d289c2baSAndroid Build Coastguard Worker key_path: The path to a key file. 357*d289c2baSAndroid Build Coastguard Worker """ 358*d289c2baSAndroid Build Coastguard Worker 359*d289c2baSAndroid Build Coastguard Worker MODULUS_PREFIX = b'modulus=' 360*d289c2baSAndroid Build Coastguard Worker 361*d289c2baSAndroid Build Coastguard Worker def __init__(self, key_path): 362*d289c2baSAndroid Build Coastguard Worker """Loads and parses an RSA key from either a private or public key file. 363*d289c2baSAndroid Build Coastguard Worker 364*d289c2baSAndroid Build Coastguard Worker Arguments: 365*d289c2baSAndroid Build Coastguard Worker key_path: The path to a key file. 366*d289c2baSAndroid Build Coastguard Worker 367*d289c2baSAndroid Build Coastguard Worker Raises: 368*d289c2baSAndroid Build Coastguard Worker AvbError: If RSA key parameters could not be read from file. 369*d289c2baSAndroid Build Coastguard Worker """ 370*d289c2baSAndroid Build Coastguard Worker # We used to have something as simple as this: 371*d289c2baSAndroid Build Coastguard Worker # 372*d289c2baSAndroid Build Coastguard Worker # key = Crypto.PublicKey.RSA.importKey(open(key_path).read()) 373*d289c2baSAndroid Build Coastguard Worker # self.exponent = key.e 374*d289c2baSAndroid Build Coastguard Worker # self.modulus = key.n 375*d289c2baSAndroid Build Coastguard Worker # self.num_bits = key.size() + 1 376*d289c2baSAndroid Build Coastguard Worker # 377*d289c2baSAndroid Build Coastguard Worker # but unfortunately PyCrypto is not available in the builder. So 378*d289c2baSAndroid Build Coastguard Worker # instead just parse openssl(1) output to get this 379*d289c2baSAndroid Build Coastguard Worker # information. It's ugly but... 380*d289c2baSAndroid Build Coastguard Worker args = ['openssl', 'rsa', '-in', key_path, '-modulus', '-noout'] 381*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen(args, 382*d289c2baSAndroid Build Coastguard Worker stdin=subprocess.PIPE, 383*d289c2baSAndroid Build Coastguard Worker stdout=subprocess.PIPE, 384*d289c2baSAndroid Build Coastguard Worker stderr=subprocess.PIPE) 385*d289c2baSAndroid Build Coastguard Worker (pout, perr) = p.communicate() 386*d289c2baSAndroid Build Coastguard Worker if p.wait() != 0: 387*d289c2baSAndroid Build Coastguard Worker # Could be just a public key is passed, try that. 388*d289c2baSAndroid Build Coastguard Worker args.append('-pubin') 389*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen(args, 390*d289c2baSAndroid Build Coastguard Worker stdin=subprocess.PIPE, 391*d289c2baSAndroid Build Coastguard Worker stdout=subprocess.PIPE, 392*d289c2baSAndroid Build Coastguard Worker stderr=subprocess.PIPE) 393*d289c2baSAndroid Build Coastguard Worker (pout, perr) = p.communicate() 394*d289c2baSAndroid Build Coastguard Worker if p.wait() != 0: 395*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error getting public key: {}'.format(perr)) 396*d289c2baSAndroid Build Coastguard Worker 397*d289c2baSAndroid Build Coastguard Worker if not pout.lower().startswith(self.MODULUS_PREFIX): 398*d289c2baSAndroid Build Coastguard Worker raise AvbError('Unexpected modulus output') 399*d289c2baSAndroid Build Coastguard Worker 400*d289c2baSAndroid Build Coastguard Worker modulus_hexstr = pout[len(self.MODULUS_PREFIX):] 401*d289c2baSAndroid Build Coastguard Worker 402*d289c2baSAndroid Build Coastguard Worker # The exponent is assumed to always be 65537 and the number of 403*d289c2baSAndroid Build Coastguard Worker # bits can be derived from the modulus by rounding up to the 404*d289c2baSAndroid Build Coastguard Worker # nearest power of 2. 405*d289c2baSAndroid Build Coastguard Worker self.key_path = key_path 406*d289c2baSAndroid Build Coastguard Worker self.modulus = int(modulus_hexstr, 16) 407*d289c2baSAndroid Build Coastguard Worker self.num_bits = round_to_pow2(int(math.ceil(math.log(self.modulus, 2)))) 408*d289c2baSAndroid Build Coastguard Worker self.exponent = 65537 409*d289c2baSAndroid Build Coastguard Worker 410*d289c2baSAndroid Build Coastguard Worker def encode(self): 411*d289c2baSAndroid Build Coastguard Worker """Encodes the public RSA key in |AvbRSAPublicKeyHeader| format. 412*d289c2baSAndroid Build Coastguard Worker 413*d289c2baSAndroid Build Coastguard Worker This creates a |AvbRSAPublicKeyHeader| as well as the two large 414*d289c2baSAndroid Build Coastguard Worker numbers (|key_num_bits| bits long) following it. 415*d289c2baSAndroid Build Coastguard Worker 416*d289c2baSAndroid Build Coastguard Worker Returns: 417*d289c2baSAndroid Build Coastguard Worker The |AvbRSAPublicKeyHeader| followed by two large numbers as bytes. 418*d289c2baSAndroid Build Coastguard Worker 419*d289c2baSAndroid Build Coastguard Worker Raises: 420*d289c2baSAndroid Build Coastguard Worker AvbError: If given RSA key exponent is not 65537. 421*d289c2baSAndroid Build Coastguard Worker """ 422*d289c2baSAndroid Build Coastguard Worker if self.exponent != 65537: 423*d289c2baSAndroid Build Coastguard Worker raise AvbError('Only RSA keys with exponent 65537 are supported.') 424*d289c2baSAndroid Build Coastguard Worker ret = bytearray() 425*d289c2baSAndroid Build Coastguard Worker # Calculate n0inv = -1/n[0] (mod 2^32) 426*d289c2baSAndroid Build Coastguard Worker b = 2 ** 32 427*d289c2baSAndroid Build Coastguard Worker n0inv = b - modinv(self.modulus, b) 428*d289c2baSAndroid Build Coastguard Worker # Calculate rr = r^2 (mod N), where r = 2^(# of key bits) 429*d289c2baSAndroid Build Coastguard Worker r = 2 ** self.modulus.bit_length() 430*d289c2baSAndroid Build Coastguard Worker rrmodn = r * r % self.modulus 431*d289c2baSAndroid Build Coastguard Worker ret.extend(struct.pack('!II', self.num_bits, n0inv)) 432*d289c2baSAndroid Build Coastguard Worker ret.extend(encode_long(self.num_bits, self.modulus)) 433*d289c2baSAndroid Build Coastguard Worker ret.extend(encode_long(self.num_bits, rrmodn)) 434*d289c2baSAndroid Build Coastguard Worker return bytes(ret) 435*d289c2baSAndroid Build Coastguard Worker 436*d289c2baSAndroid Build Coastguard Worker def sign(self, algorithm_name, data_to_sign, signing_helper=None, 437*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files=None): 438*d289c2baSAndroid Build Coastguard Worker """Sign given data using |signing_helper| or openssl. 439*d289c2baSAndroid Build Coastguard Worker 440*d289c2baSAndroid Build Coastguard Worker openssl is used if neither the parameters signing_helper nor 441*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files are given. 442*d289c2baSAndroid Build Coastguard Worker 443*d289c2baSAndroid Build Coastguard Worker Arguments: 444*d289c2baSAndroid Build Coastguard Worker algorithm_name: The algorithm name as per the ALGORITHMS dict. 445*d289c2baSAndroid Build Coastguard Worker data_to_sign: Data to sign as bytes or bytearray. 446*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and returns the signature. 447*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 448*d289c2baSAndroid Build Coastguard Worker 449*d289c2baSAndroid Build Coastguard Worker Returns: 450*d289c2baSAndroid Build Coastguard Worker The signature as bytes. 451*d289c2baSAndroid Build Coastguard Worker 452*d289c2baSAndroid Build Coastguard Worker Raises: 453*d289c2baSAndroid Build Coastguard Worker AvbError: If an error occurred during signing. 454*d289c2baSAndroid Build Coastguard Worker """ 455*d289c2baSAndroid Build Coastguard Worker # Checks requested algorithm for validity. 456*d289c2baSAndroid Build Coastguard Worker algorithm = ALGORITHMS.get(algorithm_name) 457*d289c2baSAndroid Build Coastguard Worker if not algorithm: 458*d289c2baSAndroid Build Coastguard Worker raise AvbError('Algorithm with name {} is not supported.' 459*d289c2baSAndroid Build Coastguard Worker .format(algorithm_name)) 460*d289c2baSAndroid Build Coastguard Worker 461*d289c2baSAndroid Build Coastguard Worker if self.num_bits != (algorithm.signature_num_bytes * 8): 462*d289c2baSAndroid Build Coastguard Worker raise AvbError('Key size of key ({} bits) does not match key size ' 463*d289c2baSAndroid Build Coastguard Worker '({} bits) of given algorithm {}.' 464*d289c2baSAndroid Build Coastguard Worker .format(self.num_bits, algorithm.signature_num_bytes * 8, 465*d289c2baSAndroid Build Coastguard Worker algorithm_name)) 466*d289c2baSAndroid Build Coastguard Worker 467*d289c2baSAndroid Build Coastguard Worker # Hashes the data. 468*d289c2baSAndroid Build Coastguard Worker hasher = hashlib.new(algorithm.hash_name) 469*d289c2baSAndroid Build Coastguard Worker hasher.update(data_to_sign) 470*d289c2baSAndroid Build Coastguard Worker digest = hasher.digest() 471*d289c2baSAndroid Build Coastguard Worker 472*d289c2baSAndroid Build Coastguard Worker # Calculates the signature. 473*d289c2baSAndroid Build Coastguard Worker padding_and_hash = algorithm.padding + digest 474*d289c2baSAndroid Build Coastguard Worker p = None 475*d289c2baSAndroid Build Coastguard Worker if signing_helper_with_files is not None: 476*d289c2baSAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as signing_file: 477*d289c2baSAndroid Build Coastguard Worker signing_file.write(padding_and_hash) 478*d289c2baSAndroid Build Coastguard Worker signing_file.flush() 479*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen([signing_helper_with_files, algorithm_name, 480*d289c2baSAndroid Build Coastguard Worker self.key_path, signing_file.name]) 481*d289c2baSAndroid Build Coastguard Worker retcode = p.wait() 482*d289c2baSAndroid Build Coastguard Worker if retcode != 0: 483*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error signing') 484*d289c2baSAndroid Build Coastguard Worker signing_file.seek(0) 485*d289c2baSAndroid Build Coastguard Worker signature = signing_file.read() 486*d289c2baSAndroid Build Coastguard Worker else: 487*d289c2baSAndroid Build Coastguard Worker if signing_helper is not None: 488*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen( 489*d289c2baSAndroid Build Coastguard Worker [signing_helper, algorithm_name, self.key_path], 490*d289c2baSAndroid Build Coastguard Worker stdin=subprocess.PIPE, 491*d289c2baSAndroid Build Coastguard Worker stdout=subprocess.PIPE, 492*d289c2baSAndroid Build Coastguard Worker stderr=subprocess.PIPE) 493*d289c2baSAndroid Build Coastguard Worker else: 494*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen( 495*d289c2baSAndroid Build Coastguard Worker ['openssl', 'rsautl', '-sign', '-inkey', self.key_path, '-raw'], 496*d289c2baSAndroid Build Coastguard Worker stdin=subprocess.PIPE, 497*d289c2baSAndroid Build Coastguard Worker stdout=subprocess.PIPE, 498*d289c2baSAndroid Build Coastguard Worker stderr=subprocess.PIPE) 499*d289c2baSAndroid Build Coastguard Worker (pout, perr) = p.communicate(padding_and_hash) 500*d289c2baSAndroid Build Coastguard Worker retcode = p.wait() 501*d289c2baSAndroid Build Coastguard Worker if retcode != 0: 502*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error signing: {}'.format(perr)) 503*d289c2baSAndroid Build Coastguard Worker signature = pout 504*d289c2baSAndroid Build Coastguard Worker if len(signature) != algorithm.signature_num_bytes: 505*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error signing: Invalid length of signature') 506*d289c2baSAndroid Build Coastguard Worker return signature 507*d289c2baSAndroid Build Coastguard Worker 508*d289c2baSAndroid Build Coastguard Worker 509*d289c2baSAndroid Build Coastguard Workerdef lookup_algorithm_by_type(alg_type): 510*d289c2baSAndroid Build Coastguard Worker """Looks up algorithm by type. 511*d289c2baSAndroid Build Coastguard Worker 512*d289c2baSAndroid Build Coastguard Worker Arguments: 513*d289c2baSAndroid Build Coastguard Worker alg_type: The integer representing the type. 514*d289c2baSAndroid Build Coastguard Worker 515*d289c2baSAndroid Build Coastguard Worker Returns: 516*d289c2baSAndroid Build Coastguard Worker A tuple with the algorithm name and an |Algorithm| instance. 517*d289c2baSAndroid Build Coastguard Worker 518*d289c2baSAndroid Build Coastguard Worker Raises: 519*d289c2baSAndroid Build Coastguard Worker Exception: If the algorithm cannot be found 520*d289c2baSAndroid Build Coastguard Worker """ 521*d289c2baSAndroid Build Coastguard Worker for alg_name in ALGORITHMS: 522*d289c2baSAndroid Build Coastguard Worker alg_data = ALGORITHMS[alg_name] 523*d289c2baSAndroid Build Coastguard Worker if alg_data.algorithm_type == alg_type: 524*d289c2baSAndroid Build Coastguard Worker return (alg_name, alg_data) 525*d289c2baSAndroid Build Coastguard Worker raise AvbError('Unknown algorithm type {}'.format(alg_type)) 526*d289c2baSAndroid Build Coastguard Worker 527*d289c2baSAndroid Build Coastguard Worker 528*d289c2baSAndroid Build Coastguard Workerdef lookup_hash_size_by_type(alg_type): 529*d289c2baSAndroid Build Coastguard Worker """Looks up hash size by type. 530*d289c2baSAndroid Build Coastguard Worker 531*d289c2baSAndroid Build Coastguard Worker Arguments: 532*d289c2baSAndroid Build Coastguard Worker alg_type: The integer representing the type. 533*d289c2baSAndroid Build Coastguard Worker 534*d289c2baSAndroid Build Coastguard Worker Returns: 535*d289c2baSAndroid Build Coastguard Worker The corresponding hash size. 536*d289c2baSAndroid Build Coastguard Worker 537*d289c2baSAndroid Build Coastguard Worker Raises: 538*d289c2baSAndroid Build Coastguard Worker AvbError: If the algorithm cannot be found. 539*d289c2baSAndroid Build Coastguard Worker """ 540*d289c2baSAndroid Build Coastguard Worker for alg_name in ALGORITHMS: 541*d289c2baSAndroid Build Coastguard Worker alg_data = ALGORITHMS[alg_name] 542*d289c2baSAndroid Build Coastguard Worker if alg_data.algorithm_type == alg_type: 543*d289c2baSAndroid Build Coastguard Worker return alg_data.hash_num_bytes 544*d289c2baSAndroid Build Coastguard Worker raise AvbError('Unsupported algorithm type {}'.format(alg_type)) 545*d289c2baSAndroid Build Coastguard Worker 546*d289c2baSAndroid Build Coastguard Worker 547*d289c2baSAndroid Build Coastguard Workerdef verify_vbmeta_signature(vbmeta_header, vbmeta_blob): 548*d289c2baSAndroid Build Coastguard Worker """Checks that signature in a vbmeta blob was made by the embedded public key. 549*d289c2baSAndroid Build Coastguard Worker 550*d289c2baSAndroid Build Coastguard Worker Arguments: 551*d289c2baSAndroid Build Coastguard Worker vbmeta_header: A AvbVBMetaHeader. 552*d289c2baSAndroid Build Coastguard Worker vbmeta_blob: The whole vbmeta blob, including the header as bytes or 553*d289c2baSAndroid Build Coastguard Worker bytearray. 554*d289c2baSAndroid Build Coastguard Worker 555*d289c2baSAndroid Build Coastguard Worker Returns: 556*d289c2baSAndroid Build Coastguard Worker True if the signature is valid and corresponds to the embedded 557*d289c2baSAndroid Build Coastguard Worker public key. Also returns True if the vbmeta blob is not signed. 558*d289c2baSAndroid Build Coastguard Worker 559*d289c2baSAndroid Build Coastguard Worker Raises: 560*d289c2baSAndroid Build Coastguard Worker AvbError: If there errors calling out to openssl command during 561*d289c2baSAndroid Build Coastguard Worker signature verification. 562*d289c2baSAndroid Build Coastguard Worker """ 563*d289c2baSAndroid Build Coastguard Worker (_, alg) = lookup_algorithm_by_type(vbmeta_header.algorithm_type) 564*d289c2baSAndroid Build Coastguard Worker if not alg.hash_name: 565*d289c2baSAndroid Build Coastguard Worker return True 566*d289c2baSAndroid Build Coastguard Worker header_blob = vbmeta_blob[0:256] 567*d289c2baSAndroid Build Coastguard Worker auth_offset = 256 568*d289c2baSAndroid Build Coastguard Worker aux_offset = auth_offset + vbmeta_header.authentication_data_block_size 569*d289c2baSAndroid Build Coastguard Worker aux_size = vbmeta_header.auxiliary_data_block_size 570*d289c2baSAndroid Build Coastguard Worker aux_blob = vbmeta_blob[aux_offset:aux_offset + aux_size] 571*d289c2baSAndroid Build Coastguard Worker pubkey_offset = aux_offset + vbmeta_header.public_key_offset 572*d289c2baSAndroid Build Coastguard Worker pubkey_size = vbmeta_header.public_key_size 573*d289c2baSAndroid Build Coastguard Worker pubkey_blob = vbmeta_blob[pubkey_offset:pubkey_offset + pubkey_size] 574*d289c2baSAndroid Build Coastguard Worker 575*d289c2baSAndroid Build Coastguard Worker digest_offset = auth_offset + vbmeta_header.hash_offset 576*d289c2baSAndroid Build Coastguard Worker digest_size = vbmeta_header.hash_size 577*d289c2baSAndroid Build Coastguard Worker digest_blob = vbmeta_blob[digest_offset:digest_offset + digest_size] 578*d289c2baSAndroid Build Coastguard Worker 579*d289c2baSAndroid Build Coastguard Worker sig_offset = auth_offset + vbmeta_header.signature_offset 580*d289c2baSAndroid Build Coastguard Worker sig_size = vbmeta_header.signature_size 581*d289c2baSAndroid Build Coastguard Worker sig_blob = vbmeta_blob[sig_offset:sig_offset + sig_size] 582*d289c2baSAndroid Build Coastguard Worker 583*d289c2baSAndroid Build Coastguard Worker # Now that we've got the stored digest, public key, and signature 584*d289c2baSAndroid Build Coastguard Worker # all we need to do is to verify. This is the exactly the same 585*d289c2baSAndroid Build Coastguard Worker # steps as performed in the avb_vbmeta_image_verify() function in 586*d289c2baSAndroid Build Coastguard Worker # libavb/avb_vbmeta_image.c. 587*d289c2baSAndroid Build Coastguard Worker 588*d289c2baSAndroid Build Coastguard Worker ha = hashlib.new(alg.hash_name) 589*d289c2baSAndroid Build Coastguard Worker ha.update(header_blob) 590*d289c2baSAndroid Build Coastguard Worker ha.update(aux_blob) 591*d289c2baSAndroid Build Coastguard Worker computed_digest = ha.digest() 592*d289c2baSAndroid Build Coastguard Worker 593*d289c2baSAndroid Build Coastguard Worker if computed_digest != digest_blob: 594*d289c2baSAndroid Build Coastguard Worker return False 595*d289c2baSAndroid Build Coastguard Worker 596*d289c2baSAndroid Build Coastguard Worker padding_and_digest = alg.padding + computed_digest 597*d289c2baSAndroid Build Coastguard Worker 598*d289c2baSAndroid Build Coastguard Worker (num_bits,) = struct.unpack('!I', pubkey_blob[0:4]) 599*d289c2baSAndroid Build Coastguard Worker modulus_blob = pubkey_blob[8:8 + num_bits//8] 600*d289c2baSAndroid Build Coastguard Worker modulus = decode_long(modulus_blob) 601*d289c2baSAndroid Build Coastguard Worker exponent = 65537 602*d289c2baSAndroid Build Coastguard Worker 603*d289c2baSAndroid Build Coastguard Worker # We used to have this: 604*d289c2baSAndroid Build Coastguard Worker # 605*d289c2baSAndroid Build Coastguard Worker # import Crypto.PublicKey.RSA 606*d289c2baSAndroid Build Coastguard Worker # key = Crypto.PublicKey.RSA.construct((modulus, long(exponent))) 607*d289c2baSAndroid Build Coastguard Worker # if not key.verify(decode_long(padding_and_digest), 608*d289c2baSAndroid Build Coastguard Worker # (decode_long(sig_blob), None)): 609*d289c2baSAndroid Build Coastguard Worker # return False 610*d289c2baSAndroid Build Coastguard Worker # return True 611*d289c2baSAndroid Build Coastguard Worker # 612*d289c2baSAndroid Build Coastguard Worker # but since 'avbtool verify_image' is used on the builders we don't want 613*d289c2baSAndroid Build Coastguard Worker # to rely on Crypto.PublicKey.RSA. Instead just use openssl(1) to verify. 614*d289c2baSAndroid Build Coastguard Worker asn1_str = ('asn1=SEQUENCE:pubkeyinfo\n' 615*d289c2baSAndroid Build Coastguard Worker '\n' 616*d289c2baSAndroid Build Coastguard Worker '[pubkeyinfo]\n' 617*d289c2baSAndroid Build Coastguard Worker 'algorithm=SEQUENCE:rsa_alg\n' 618*d289c2baSAndroid Build Coastguard Worker 'pubkey=BITWRAP,SEQUENCE:rsapubkey\n' 619*d289c2baSAndroid Build Coastguard Worker '\n' 620*d289c2baSAndroid Build Coastguard Worker '[rsa_alg]\n' 621*d289c2baSAndroid Build Coastguard Worker 'algorithm=OID:rsaEncryption\n' 622*d289c2baSAndroid Build Coastguard Worker 'parameter=NULL\n' 623*d289c2baSAndroid Build Coastguard Worker '\n' 624*d289c2baSAndroid Build Coastguard Worker '[rsapubkey]\n' 625*d289c2baSAndroid Build Coastguard Worker 'n=INTEGER:{}\n' 626*d289c2baSAndroid Build Coastguard Worker 'e=INTEGER:{}\n').format(hex(modulus).rstrip('L'), 627*d289c2baSAndroid Build Coastguard Worker hex(exponent).rstrip('L')) 628*d289c2baSAndroid Build Coastguard Worker 629*d289c2baSAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as asn1_tmpfile: 630*d289c2baSAndroid Build Coastguard Worker asn1_tmpfile.write(asn1_str.encode('ascii')) 631*d289c2baSAndroid Build Coastguard Worker asn1_tmpfile.flush() 632*d289c2baSAndroid Build Coastguard Worker 633*d289c2baSAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as der_tmpfile: 634*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen( 635*d289c2baSAndroid Build Coastguard Worker ['openssl', 'asn1parse', '-genconf', asn1_tmpfile.name, '-out', 636*d289c2baSAndroid Build Coastguard Worker der_tmpfile.name, '-noout']) 637*d289c2baSAndroid Build Coastguard Worker retcode = p.wait() 638*d289c2baSAndroid Build Coastguard Worker if retcode != 0: 639*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error generating DER file') 640*d289c2baSAndroid Build Coastguard Worker 641*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen( 642*d289c2baSAndroid Build Coastguard Worker ['openssl', 'rsautl', '-verify', '-pubin', '-inkey', der_tmpfile.name, 643*d289c2baSAndroid Build Coastguard Worker '-keyform', 'DER', '-raw'], 644*d289c2baSAndroid Build Coastguard Worker stdin=subprocess.PIPE, 645*d289c2baSAndroid Build Coastguard Worker stdout=subprocess.PIPE, 646*d289c2baSAndroid Build Coastguard Worker stderr=subprocess.PIPE) 647*d289c2baSAndroid Build Coastguard Worker (pout, perr) = p.communicate(sig_blob) 648*d289c2baSAndroid Build Coastguard Worker retcode = p.wait() 649*d289c2baSAndroid Build Coastguard Worker if retcode != 0: 650*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error verifying data: {}'.format(perr)) 651*d289c2baSAndroid Build Coastguard Worker if pout != padding_and_digest: 652*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('Signature not correct\n') 653*d289c2baSAndroid Build Coastguard Worker return False 654*d289c2baSAndroid Build Coastguard Worker return True 655*d289c2baSAndroid Build Coastguard Worker 656*d289c2baSAndroid Build Coastguard Worker 657*d289c2baSAndroid Build Coastguard Workerdef create_avb_hashtree_hasher(algorithm, salt): 658*d289c2baSAndroid Build Coastguard Worker """Create the hasher for AVB hashtree based on the input algorithm.""" 659*d289c2baSAndroid Build Coastguard Worker 660*d289c2baSAndroid Build Coastguard Worker if algorithm.lower() == 'blake2b-256': 661*d289c2baSAndroid Build Coastguard Worker return hashlib.new('blake2b', salt, digest_size=32) 662*d289c2baSAndroid Build Coastguard Worker 663*d289c2baSAndroid Build Coastguard Worker return hashlib.new(algorithm, salt) 664*d289c2baSAndroid Build Coastguard Worker 665*d289c2baSAndroid Build Coastguard Worker 666*d289c2baSAndroid Build Coastguard Workerclass ImageChunk(object): 667*d289c2baSAndroid Build Coastguard Worker """Data structure used for representing chunks in Android sparse files. 668*d289c2baSAndroid Build Coastguard Worker 669*d289c2baSAndroid Build Coastguard Worker Attributes: 670*d289c2baSAndroid Build Coastguard Worker chunk_type: One of TYPE_RAW, TYPE_FILL, or TYPE_DONT_CARE. 671*d289c2baSAndroid Build Coastguard Worker chunk_offset: Offset in the sparse file where this chunk begins. 672*d289c2baSAndroid Build Coastguard Worker output_offset: Offset in de-sparsified file where output begins. 673*d289c2baSAndroid Build Coastguard Worker output_size: Number of bytes in output. 674*d289c2baSAndroid Build Coastguard Worker input_offset: Offset in sparse file for data if TYPE_RAW otherwise None. 675*d289c2baSAndroid Build Coastguard Worker fill_data: Blob with data to fill if TYPE_FILL otherwise None. 676*d289c2baSAndroid Build Coastguard Worker """ 677*d289c2baSAndroid Build Coastguard Worker 678*d289c2baSAndroid Build Coastguard Worker FORMAT = '<2H2I' 679*d289c2baSAndroid Build Coastguard Worker TYPE_RAW = 0xcac1 680*d289c2baSAndroid Build Coastguard Worker TYPE_FILL = 0xcac2 681*d289c2baSAndroid Build Coastguard Worker TYPE_DONT_CARE = 0xcac3 682*d289c2baSAndroid Build Coastguard Worker TYPE_CRC32 = 0xcac4 683*d289c2baSAndroid Build Coastguard Worker 684*d289c2baSAndroid Build Coastguard Worker def __init__(self, chunk_type, chunk_offset, output_offset, output_size, 685*d289c2baSAndroid Build Coastguard Worker input_offset, fill_data): 686*d289c2baSAndroid Build Coastguard Worker """Initializes an ImageChunk object. 687*d289c2baSAndroid Build Coastguard Worker 688*d289c2baSAndroid Build Coastguard Worker Arguments: 689*d289c2baSAndroid Build Coastguard Worker chunk_type: One of TYPE_RAW, TYPE_FILL, or TYPE_DONT_CARE. 690*d289c2baSAndroid Build Coastguard Worker chunk_offset: Offset in the sparse file where this chunk begins. 691*d289c2baSAndroid Build Coastguard Worker output_offset: Offset in de-sparsified file. 692*d289c2baSAndroid Build Coastguard Worker output_size: Number of bytes in output. 693*d289c2baSAndroid Build Coastguard Worker input_offset: Offset in sparse file if TYPE_RAW otherwise None. 694*d289c2baSAndroid Build Coastguard Worker fill_data: Blob as bytes with data to fill if TYPE_FILL otherwise None. 695*d289c2baSAndroid Build Coastguard Worker 696*d289c2baSAndroid Build Coastguard Worker Raises: 697*d289c2baSAndroid Build Coastguard Worker ValueError: If given chunk parameters are invalid. 698*d289c2baSAndroid Build Coastguard Worker """ 699*d289c2baSAndroid Build Coastguard Worker self.chunk_type = chunk_type 700*d289c2baSAndroid Build Coastguard Worker self.chunk_offset = chunk_offset 701*d289c2baSAndroid Build Coastguard Worker self.output_offset = output_offset 702*d289c2baSAndroid Build Coastguard Worker self.output_size = output_size 703*d289c2baSAndroid Build Coastguard Worker self.input_offset = input_offset 704*d289c2baSAndroid Build Coastguard Worker self.fill_data = fill_data 705*d289c2baSAndroid Build Coastguard Worker # Check invariants. 706*d289c2baSAndroid Build Coastguard Worker if self.chunk_type == self.TYPE_RAW: 707*d289c2baSAndroid Build Coastguard Worker if self.fill_data is not None: 708*d289c2baSAndroid Build Coastguard Worker raise ValueError('RAW chunk cannot have fill_data set.') 709*d289c2baSAndroid Build Coastguard Worker if not self.input_offset: 710*d289c2baSAndroid Build Coastguard Worker raise ValueError('RAW chunk must have input_offset set.') 711*d289c2baSAndroid Build Coastguard Worker elif self.chunk_type == self.TYPE_FILL: 712*d289c2baSAndroid Build Coastguard Worker if self.fill_data is None: 713*d289c2baSAndroid Build Coastguard Worker raise ValueError('FILL chunk must have fill_data set.') 714*d289c2baSAndroid Build Coastguard Worker if self.input_offset: 715*d289c2baSAndroid Build Coastguard Worker raise ValueError('FILL chunk cannot have input_offset set.') 716*d289c2baSAndroid Build Coastguard Worker elif self.chunk_type == self.TYPE_DONT_CARE: 717*d289c2baSAndroid Build Coastguard Worker if self.fill_data is not None: 718*d289c2baSAndroid Build Coastguard Worker raise ValueError('DONT_CARE chunk cannot have fill_data set.') 719*d289c2baSAndroid Build Coastguard Worker if self.input_offset: 720*d289c2baSAndroid Build Coastguard Worker raise ValueError('DONT_CARE chunk cannot have input_offset set.') 721*d289c2baSAndroid Build Coastguard Worker else: 722*d289c2baSAndroid Build Coastguard Worker raise ValueError('Invalid chunk type') 723*d289c2baSAndroid Build Coastguard Worker 724*d289c2baSAndroid Build Coastguard Worker 725*d289c2baSAndroid Build Coastguard Workerclass ImageHandler(object): 726*d289c2baSAndroid Build Coastguard Worker """Abstraction for image I/O with support for Android sparse images. 727*d289c2baSAndroid Build Coastguard Worker 728*d289c2baSAndroid Build Coastguard Worker This class provides an interface for working with image files that 729*d289c2baSAndroid Build Coastguard Worker may be using the Android Sparse Image format. When an instance is 730*d289c2baSAndroid Build Coastguard Worker constructed, we test whether it's an Android sparse file. If so, 731*d289c2baSAndroid Build Coastguard Worker operations will be on the sparse file by interpreting the sparse 732*d289c2baSAndroid Build Coastguard Worker format, otherwise they will be directly on the file. Either way the 733*d289c2baSAndroid Build Coastguard Worker operations do the same. 734*d289c2baSAndroid Build Coastguard Worker 735*d289c2baSAndroid Build Coastguard Worker For reading, this interface mimics a file object - it has seek(), 736*d289c2baSAndroid Build Coastguard Worker tell(), and read() methods. For writing, only truncation 737*d289c2baSAndroid Build Coastguard Worker (truncate()) and appending is supported (append_raw() and 738*d289c2baSAndroid Build Coastguard Worker append_dont_care()). Additionally, data can only be written in units 739*d289c2baSAndroid Build Coastguard Worker of the block size. 740*d289c2baSAndroid Build Coastguard Worker 741*d289c2baSAndroid Build Coastguard Worker Attributes: 742*d289c2baSAndroid Build Coastguard Worker filename: Name of file. 743*d289c2baSAndroid Build Coastguard Worker is_sparse: Whether the file being operated on is sparse. 744*d289c2baSAndroid Build Coastguard Worker block_size: The block size, typically 4096. 745*d289c2baSAndroid Build Coastguard Worker image_size: The size of the unsparsified file. 746*d289c2baSAndroid Build Coastguard Worker """ 747*d289c2baSAndroid Build Coastguard Worker # See system/core/libsparse/sparse_format.h for details. 748*d289c2baSAndroid Build Coastguard Worker MAGIC = 0xed26ff3a 749*d289c2baSAndroid Build Coastguard Worker HEADER_FORMAT = '<I4H4I' 750*d289c2baSAndroid Build Coastguard Worker 751*d289c2baSAndroid Build Coastguard Worker # These are formats and offset of just the |total_chunks| and 752*d289c2baSAndroid Build Coastguard Worker # |total_blocks| fields. 753*d289c2baSAndroid Build Coastguard Worker NUM_CHUNKS_AND_BLOCKS_FORMAT = '<II' 754*d289c2baSAndroid Build Coastguard Worker NUM_CHUNKS_AND_BLOCKS_OFFSET = 16 755*d289c2baSAndroid Build Coastguard Worker 756*d289c2baSAndroid Build Coastguard Worker def __init__(self, image_filename, read_only=False): 757*d289c2baSAndroid Build Coastguard Worker """Initializes an image handler. 758*d289c2baSAndroid Build Coastguard Worker 759*d289c2baSAndroid Build Coastguard Worker Arguments: 760*d289c2baSAndroid Build Coastguard Worker image_filename: The name of the file to operate on. 761*d289c2baSAndroid Build Coastguard Worker read_only: True if file is only opened for read-only operations. 762*d289c2baSAndroid Build Coastguard Worker 763*d289c2baSAndroid Build Coastguard Worker Raises: 764*d289c2baSAndroid Build Coastguard Worker ValueError: If data in the file is invalid. 765*d289c2baSAndroid Build Coastguard Worker """ 766*d289c2baSAndroid Build Coastguard Worker self.filename = image_filename 767*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks = 0 768*d289c2baSAndroid Build Coastguard Worker self._num_total_chunks = 0 769*d289c2baSAndroid Build Coastguard Worker self._file_pos = 0 770*d289c2baSAndroid Build Coastguard Worker self._read_only = read_only 771*d289c2baSAndroid Build Coastguard Worker self._read_header() 772*d289c2baSAndroid Build Coastguard Worker 773*d289c2baSAndroid Build Coastguard Worker def _read_header(self): 774*d289c2baSAndroid Build Coastguard Worker """Initializes internal data structures used for reading file. 775*d289c2baSAndroid Build Coastguard Worker 776*d289c2baSAndroid Build Coastguard Worker This may be called multiple times and is typically called after 777*d289c2baSAndroid Build Coastguard Worker modifying the file (e.g. appending, truncation). 778*d289c2baSAndroid Build Coastguard Worker 779*d289c2baSAndroid Build Coastguard Worker Raises: 780*d289c2baSAndroid Build Coastguard Worker ValueError: If data in the file is invalid. 781*d289c2baSAndroid Build Coastguard Worker """ 782*d289c2baSAndroid Build Coastguard Worker self.is_sparse = False 783*d289c2baSAndroid Build Coastguard Worker self.block_size = 4096 784*d289c2baSAndroid Build Coastguard Worker self._file_pos = 0 785*d289c2baSAndroid Build Coastguard Worker if self._read_only: 786*d289c2baSAndroid Build Coastguard Worker self._image = open(self.filename, 'rb') 787*d289c2baSAndroid Build Coastguard Worker else: 788*d289c2baSAndroid Build Coastguard Worker self._image = open(self.filename, 'r+b') 789*d289c2baSAndroid Build Coastguard Worker self._image.seek(0, os.SEEK_END) 790*d289c2baSAndroid Build Coastguard Worker self.image_size = self._image.tell() 791*d289c2baSAndroid Build Coastguard Worker 792*d289c2baSAndroid Build Coastguard Worker self._image.seek(0, os.SEEK_SET) 793*d289c2baSAndroid Build Coastguard Worker header_bin = self._image.read(struct.calcsize(self.HEADER_FORMAT)) 794*d289c2baSAndroid Build Coastguard Worker (magic, major_version, minor_version, file_hdr_sz, chunk_hdr_sz, 795*d289c2baSAndroid Build Coastguard Worker block_size, self._num_total_blocks, self._num_total_chunks, 796*d289c2baSAndroid Build Coastguard Worker _) = struct.unpack(self.HEADER_FORMAT, header_bin) 797*d289c2baSAndroid Build Coastguard Worker if magic != self.MAGIC: 798*d289c2baSAndroid Build Coastguard Worker # Not a sparse image, our job here is done. 799*d289c2baSAndroid Build Coastguard Worker return 800*d289c2baSAndroid Build Coastguard Worker if not (major_version == 1 and minor_version == 0): 801*d289c2baSAndroid Build Coastguard Worker raise ValueError('Encountered sparse image format version {}.{} but ' 802*d289c2baSAndroid Build Coastguard Worker 'only 1.0 is supported'.format(major_version, 803*d289c2baSAndroid Build Coastguard Worker minor_version)) 804*d289c2baSAndroid Build Coastguard Worker if file_hdr_sz != struct.calcsize(self.HEADER_FORMAT): 805*d289c2baSAndroid Build Coastguard Worker raise ValueError('Unexpected file_hdr_sz value {}.'. 806*d289c2baSAndroid Build Coastguard Worker format(file_hdr_sz)) 807*d289c2baSAndroid Build Coastguard Worker if chunk_hdr_sz != struct.calcsize(ImageChunk.FORMAT): 808*d289c2baSAndroid Build Coastguard Worker raise ValueError('Unexpected chunk_hdr_sz value {}.'. 809*d289c2baSAndroid Build Coastguard Worker format(chunk_hdr_sz)) 810*d289c2baSAndroid Build Coastguard Worker 811*d289c2baSAndroid Build Coastguard Worker self.block_size = block_size 812*d289c2baSAndroid Build Coastguard Worker 813*d289c2baSAndroid Build Coastguard Worker # Build an list of chunks by parsing the file. 814*d289c2baSAndroid Build Coastguard Worker self._chunks = [] 815*d289c2baSAndroid Build Coastguard Worker 816*d289c2baSAndroid Build Coastguard Worker # Find the smallest offset where only "Don't care" chunks 817*d289c2baSAndroid Build Coastguard Worker # follow. This will be the size of the content in the sparse 818*d289c2baSAndroid Build Coastguard Worker # image. 819*d289c2baSAndroid Build Coastguard Worker offset = 0 820*d289c2baSAndroid Build Coastguard Worker output_offset = 0 821*d289c2baSAndroid Build Coastguard Worker for _ in range(1, self._num_total_chunks + 1): 822*d289c2baSAndroid Build Coastguard Worker chunk_offset = self._image.tell() 823*d289c2baSAndroid Build Coastguard Worker 824*d289c2baSAndroid Build Coastguard Worker header_bin = self._image.read(struct.calcsize(ImageChunk.FORMAT)) 825*d289c2baSAndroid Build Coastguard Worker (chunk_type, _, chunk_sz, total_sz) = struct.unpack(ImageChunk.FORMAT, 826*d289c2baSAndroid Build Coastguard Worker header_bin) 827*d289c2baSAndroid Build Coastguard Worker data_sz = total_sz - struct.calcsize(ImageChunk.FORMAT) 828*d289c2baSAndroid Build Coastguard Worker 829*d289c2baSAndroid Build Coastguard Worker if chunk_type == ImageChunk.TYPE_RAW: 830*d289c2baSAndroid Build Coastguard Worker if data_sz != (chunk_sz * self.block_size): 831*d289c2baSAndroid Build Coastguard Worker raise ValueError('Raw chunk input size ({}) does not match output ' 832*d289c2baSAndroid Build Coastguard Worker 'size ({})'. 833*d289c2baSAndroid Build Coastguard Worker format(data_sz, chunk_sz*self.block_size)) 834*d289c2baSAndroid Build Coastguard Worker self._chunks.append(ImageChunk(ImageChunk.TYPE_RAW, 835*d289c2baSAndroid Build Coastguard Worker chunk_offset, 836*d289c2baSAndroid Build Coastguard Worker output_offset, 837*d289c2baSAndroid Build Coastguard Worker chunk_sz*self.block_size, 838*d289c2baSAndroid Build Coastguard Worker self._image.tell(), 839*d289c2baSAndroid Build Coastguard Worker None)) 840*d289c2baSAndroid Build Coastguard Worker self._image.seek(data_sz, os.SEEK_CUR) 841*d289c2baSAndroid Build Coastguard Worker 842*d289c2baSAndroid Build Coastguard Worker elif chunk_type == ImageChunk.TYPE_FILL: 843*d289c2baSAndroid Build Coastguard Worker if data_sz != 4: 844*d289c2baSAndroid Build Coastguard Worker raise ValueError('Fill chunk should have 4 bytes of fill, but this ' 845*d289c2baSAndroid Build Coastguard Worker 'has {}'.format(data_sz)) 846*d289c2baSAndroid Build Coastguard Worker fill_data = self._image.read(4) 847*d289c2baSAndroid Build Coastguard Worker self._chunks.append(ImageChunk(ImageChunk.TYPE_FILL, 848*d289c2baSAndroid Build Coastguard Worker chunk_offset, 849*d289c2baSAndroid Build Coastguard Worker output_offset, 850*d289c2baSAndroid Build Coastguard Worker chunk_sz*self.block_size, 851*d289c2baSAndroid Build Coastguard Worker None, 852*d289c2baSAndroid Build Coastguard Worker fill_data)) 853*d289c2baSAndroid Build Coastguard Worker elif chunk_type == ImageChunk.TYPE_DONT_CARE: 854*d289c2baSAndroid Build Coastguard Worker if data_sz != 0: 855*d289c2baSAndroid Build Coastguard Worker raise ValueError('Don\'t care chunk input size is non-zero ({})'. 856*d289c2baSAndroid Build Coastguard Worker format(data_sz)) 857*d289c2baSAndroid Build Coastguard Worker self._chunks.append(ImageChunk(ImageChunk.TYPE_DONT_CARE, 858*d289c2baSAndroid Build Coastguard Worker chunk_offset, 859*d289c2baSAndroid Build Coastguard Worker output_offset, 860*d289c2baSAndroid Build Coastguard Worker chunk_sz*self.block_size, 861*d289c2baSAndroid Build Coastguard Worker None, 862*d289c2baSAndroid Build Coastguard Worker None)) 863*d289c2baSAndroid Build Coastguard Worker elif chunk_type == ImageChunk.TYPE_CRC32: 864*d289c2baSAndroid Build Coastguard Worker if data_sz != 4: 865*d289c2baSAndroid Build Coastguard Worker raise ValueError('CRC32 chunk should have 4 bytes of CRC, but ' 866*d289c2baSAndroid Build Coastguard Worker 'this has {}'.format(data_sz)) 867*d289c2baSAndroid Build Coastguard Worker self._image.read(4) 868*d289c2baSAndroid Build Coastguard Worker else: 869*d289c2baSAndroid Build Coastguard Worker raise ValueError('Unknown chunk type {}'.format(chunk_type)) 870*d289c2baSAndroid Build Coastguard Worker 871*d289c2baSAndroid Build Coastguard Worker offset += chunk_sz 872*d289c2baSAndroid Build Coastguard Worker output_offset += chunk_sz*self.block_size 873*d289c2baSAndroid Build Coastguard Worker 874*d289c2baSAndroid Build Coastguard Worker # Record where sparse data end. 875*d289c2baSAndroid Build Coastguard Worker self._sparse_end = self._image.tell() 876*d289c2baSAndroid Build Coastguard Worker 877*d289c2baSAndroid Build Coastguard Worker # Now that we've traversed all chunks, sanity check. 878*d289c2baSAndroid Build Coastguard Worker if self._num_total_blocks != offset: 879*d289c2baSAndroid Build Coastguard Worker raise ValueError('The header said we should have {} output blocks, ' 880*d289c2baSAndroid Build Coastguard Worker 'but we saw {}'.format(self._num_total_blocks, offset)) 881*d289c2baSAndroid Build Coastguard Worker junk_len = len(self._image.read()) 882*d289c2baSAndroid Build Coastguard Worker if junk_len > 0: 883*d289c2baSAndroid Build Coastguard Worker raise ValueError('There were {} bytes of extra data at the end of the ' 884*d289c2baSAndroid Build Coastguard Worker 'file.'.format(junk_len)) 885*d289c2baSAndroid Build Coastguard Worker 886*d289c2baSAndroid Build Coastguard Worker # Assign |image_size|. 887*d289c2baSAndroid Build Coastguard Worker self.image_size = output_offset 888*d289c2baSAndroid Build Coastguard Worker 889*d289c2baSAndroid Build Coastguard Worker # This is used when bisecting in read() to find the initial slice. 890*d289c2baSAndroid Build Coastguard Worker self._chunk_output_offsets = [i.output_offset for i in self._chunks] 891*d289c2baSAndroid Build Coastguard Worker 892*d289c2baSAndroid Build Coastguard Worker self.is_sparse = True 893*d289c2baSAndroid Build Coastguard Worker 894*d289c2baSAndroid Build Coastguard Worker def _update_chunks_and_blocks(self): 895*d289c2baSAndroid Build Coastguard Worker """Helper function to update the image header. 896*d289c2baSAndroid Build Coastguard Worker 897*d289c2baSAndroid Build Coastguard Worker The the |total_chunks| and |total_blocks| fields in the header 898*d289c2baSAndroid Build Coastguard Worker will be set to value of the |_num_total_blocks| and 899*d289c2baSAndroid Build Coastguard Worker |_num_total_chunks| attributes. 900*d289c2baSAndroid Build Coastguard Worker 901*d289c2baSAndroid Build Coastguard Worker """ 902*d289c2baSAndroid Build Coastguard Worker self._image.seek(self.NUM_CHUNKS_AND_BLOCKS_OFFSET, os.SEEK_SET) 903*d289c2baSAndroid Build Coastguard Worker self._image.write(struct.pack(self.NUM_CHUNKS_AND_BLOCKS_FORMAT, 904*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks, 905*d289c2baSAndroid Build Coastguard Worker self._num_total_chunks)) 906*d289c2baSAndroid Build Coastguard Worker 907*d289c2baSAndroid Build Coastguard Worker def append_dont_care(self, num_bytes): 908*d289c2baSAndroid Build Coastguard Worker """Appends a DONT_CARE chunk to the sparse file. 909*d289c2baSAndroid Build Coastguard Worker 910*d289c2baSAndroid Build Coastguard Worker The given number of bytes must be a multiple of the block size. 911*d289c2baSAndroid Build Coastguard Worker 912*d289c2baSAndroid Build Coastguard Worker Arguments: 913*d289c2baSAndroid Build Coastguard Worker num_bytes: Size in number of bytes of the DONT_CARE chunk. 914*d289c2baSAndroid Build Coastguard Worker 915*d289c2baSAndroid Build Coastguard Worker Raises: 916*d289c2baSAndroid Build Coastguard Worker OSError: If ImageHandler was initialized in read-only mode. 917*d289c2baSAndroid Build Coastguard Worker """ 918*d289c2baSAndroid Build Coastguard Worker assert num_bytes % self.block_size == 0 919*d289c2baSAndroid Build Coastguard Worker 920*d289c2baSAndroid Build Coastguard Worker if self._read_only: 921*d289c2baSAndroid Build Coastguard Worker raise OSError('ImageHandler is in read-only mode.') 922*d289c2baSAndroid Build Coastguard Worker 923*d289c2baSAndroid Build Coastguard Worker if not self.is_sparse: 924*d289c2baSAndroid Build Coastguard Worker self._image.seek(0, os.SEEK_END) 925*d289c2baSAndroid Build Coastguard Worker # This is more efficient that writing NUL bytes since it'll add 926*d289c2baSAndroid Build Coastguard Worker # a hole on file systems that support sparse files (native 927*d289c2baSAndroid Build Coastguard Worker # sparse, not Android sparse). 928*d289c2baSAndroid Build Coastguard Worker self._image.truncate(self._image.tell() + num_bytes) 929*d289c2baSAndroid Build Coastguard Worker self._read_header() 930*d289c2baSAndroid Build Coastguard Worker return 931*d289c2baSAndroid Build Coastguard Worker 932*d289c2baSAndroid Build Coastguard Worker self._num_total_chunks += 1 933*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks += num_bytes // self.block_size 934*d289c2baSAndroid Build Coastguard Worker self._update_chunks_and_blocks() 935*d289c2baSAndroid Build Coastguard Worker 936*d289c2baSAndroid Build Coastguard Worker self._image.seek(self._sparse_end, os.SEEK_SET) 937*d289c2baSAndroid Build Coastguard Worker self._image.write(struct.pack(ImageChunk.FORMAT, 938*d289c2baSAndroid Build Coastguard Worker ImageChunk.TYPE_DONT_CARE, 939*d289c2baSAndroid Build Coastguard Worker 0, # Reserved 940*d289c2baSAndroid Build Coastguard Worker num_bytes // self.block_size, 941*d289c2baSAndroid Build Coastguard Worker struct.calcsize(ImageChunk.FORMAT))) 942*d289c2baSAndroid Build Coastguard Worker self._read_header() 943*d289c2baSAndroid Build Coastguard Worker 944*d289c2baSAndroid Build Coastguard Worker def append_raw(self, data, multiple_block_size=True): 945*d289c2baSAndroid Build Coastguard Worker """Appends a RAW chunk to the sparse file. 946*d289c2baSAndroid Build Coastguard Worker 947*d289c2baSAndroid Build Coastguard Worker The length of the given data must be a multiple of the block size, 948*d289c2baSAndroid Build Coastguard Worker unless |multiple_block_size| is False. 949*d289c2baSAndroid Build Coastguard Worker 950*d289c2baSAndroid Build Coastguard Worker Arguments: 951*d289c2baSAndroid Build Coastguard Worker data: Data to append as bytes. 952*d289c2baSAndroid Build Coastguard Worker multiple_block_size: whether to check the length of the 953*d289c2baSAndroid Build Coastguard Worker data is a multiple of the block size. 954*d289c2baSAndroid Build Coastguard Worker 955*d289c2baSAndroid Build Coastguard Worker Raises: 956*d289c2baSAndroid Build Coastguard Worker OSError: If ImageHandler was initialized in read-only mode. 957*d289c2baSAndroid Build Coastguard Worker """ 958*d289c2baSAndroid Build Coastguard Worker if multiple_block_size: 959*d289c2baSAndroid Build Coastguard Worker assert len(data) % self.block_size == 0 960*d289c2baSAndroid Build Coastguard Worker 961*d289c2baSAndroid Build Coastguard Worker if self._read_only: 962*d289c2baSAndroid Build Coastguard Worker raise OSError('ImageHandler is in read-only mode.') 963*d289c2baSAndroid Build Coastguard Worker 964*d289c2baSAndroid Build Coastguard Worker if not self.is_sparse: 965*d289c2baSAndroid Build Coastguard Worker self._image.seek(0, os.SEEK_END) 966*d289c2baSAndroid Build Coastguard Worker self._image.write(data) 967*d289c2baSAndroid Build Coastguard Worker self._read_header() 968*d289c2baSAndroid Build Coastguard Worker return 969*d289c2baSAndroid Build Coastguard Worker 970*d289c2baSAndroid Build Coastguard Worker self._num_total_chunks += 1 971*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks += len(data) // self.block_size 972*d289c2baSAndroid Build Coastguard Worker self._update_chunks_and_blocks() 973*d289c2baSAndroid Build Coastguard Worker 974*d289c2baSAndroid Build Coastguard Worker self._image.seek(self._sparse_end, os.SEEK_SET) 975*d289c2baSAndroid Build Coastguard Worker self._image.write(struct.pack(ImageChunk.FORMAT, 976*d289c2baSAndroid Build Coastguard Worker ImageChunk.TYPE_RAW, 977*d289c2baSAndroid Build Coastguard Worker 0, # Reserved 978*d289c2baSAndroid Build Coastguard Worker len(data) // self.block_size, 979*d289c2baSAndroid Build Coastguard Worker len(data) + 980*d289c2baSAndroid Build Coastguard Worker struct.calcsize(ImageChunk.FORMAT))) 981*d289c2baSAndroid Build Coastguard Worker self._image.write(data) 982*d289c2baSAndroid Build Coastguard Worker self._read_header() 983*d289c2baSAndroid Build Coastguard Worker 984*d289c2baSAndroid Build Coastguard Worker def append_fill(self, fill_data, size): 985*d289c2baSAndroid Build Coastguard Worker """Appends a fill chunk to the sparse file. 986*d289c2baSAndroid Build Coastguard Worker 987*d289c2baSAndroid Build Coastguard Worker The total length of the fill data must be a multiple of the block size. 988*d289c2baSAndroid Build Coastguard Worker 989*d289c2baSAndroid Build Coastguard Worker Arguments: 990*d289c2baSAndroid Build Coastguard Worker fill_data: Fill data to append - must be four bytes. 991*d289c2baSAndroid Build Coastguard Worker size: Number of chunk - must be a multiple of four and the block size. 992*d289c2baSAndroid Build Coastguard Worker 993*d289c2baSAndroid Build Coastguard Worker Raises: 994*d289c2baSAndroid Build Coastguard Worker OSError: If ImageHandler was initialized in read-only mode. 995*d289c2baSAndroid Build Coastguard Worker """ 996*d289c2baSAndroid Build Coastguard Worker assert len(fill_data) == 4 997*d289c2baSAndroid Build Coastguard Worker assert size % 4 == 0 998*d289c2baSAndroid Build Coastguard Worker assert size % self.block_size == 0 999*d289c2baSAndroid Build Coastguard Worker 1000*d289c2baSAndroid Build Coastguard Worker if self._read_only: 1001*d289c2baSAndroid Build Coastguard Worker raise OSError('ImageHandler is in read-only mode.') 1002*d289c2baSAndroid Build Coastguard Worker 1003*d289c2baSAndroid Build Coastguard Worker if not self.is_sparse: 1004*d289c2baSAndroid Build Coastguard Worker self._image.seek(0, os.SEEK_END) 1005*d289c2baSAndroid Build Coastguard Worker self._image.write(fill_data * (size//4)) 1006*d289c2baSAndroid Build Coastguard Worker self._read_header() 1007*d289c2baSAndroid Build Coastguard Worker return 1008*d289c2baSAndroid Build Coastguard Worker 1009*d289c2baSAndroid Build Coastguard Worker self._num_total_chunks += 1 1010*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks += size // self.block_size 1011*d289c2baSAndroid Build Coastguard Worker self._update_chunks_and_blocks() 1012*d289c2baSAndroid Build Coastguard Worker 1013*d289c2baSAndroid Build Coastguard Worker self._image.seek(self._sparse_end, os.SEEK_SET) 1014*d289c2baSAndroid Build Coastguard Worker self._image.write(struct.pack(ImageChunk.FORMAT, 1015*d289c2baSAndroid Build Coastguard Worker ImageChunk.TYPE_FILL, 1016*d289c2baSAndroid Build Coastguard Worker 0, # Reserved 1017*d289c2baSAndroid Build Coastguard Worker size // self.block_size, 1018*d289c2baSAndroid Build Coastguard Worker 4 + struct.calcsize(ImageChunk.FORMAT))) 1019*d289c2baSAndroid Build Coastguard Worker self._image.write(fill_data) 1020*d289c2baSAndroid Build Coastguard Worker self._read_header() 1021*d289c2baSAndroid Build Coastguard Worker 1022*d289c2baSAndroid Build Coastguard Worker def seek(self, offset): 1023*d289c2baSAndroid Build Coastguard Worker """Sets the cursor position for reading from unsparsified file. 1024*d289c2baSAndroid Build Coastguard Worker 1025*d289c2baSAndroid Build Coastguard Worker Arguments: 1026*d289c2baSAndroid Build Coastguard Worker offset: Offset to seek to from the beginning of the file. 1027*d289c2baSAndroid Build Coastguard Worker 1028*d289c2baSAndroid Build Coastguard Worker Raises: 1029*d289c2baSAndroid Build Coastguard Worker RuntimeError: If the given offset is negative. 1030*d289c2baSAndroid Build Coastguard Worker """ 1031*d289c2baSAndroid Build Coastguard Worker if offset < 0: 1032*d289c2baSAndroid Build Coastguard Worker raise RuntimeError('Seeking with negative offset: {}'.format(offset)) 1033*d289c2baSAndroid Build Coastguard Worker self._file_pos = offset 1034*d289c2baSAndroid Build Coastguard Worker 1035*d289c2baSAndroid Build Coastguard Worker def read(self, size): 1036*d289c2baSAndroid Build Coastguard Worker """Reads data from the unsparsified file. 1037*d289c2baSAndroid Build Coastguard Worker 1038*d289c2baSAndroid Build Coastguard Worker This method may return fewer than |size| bytes of data if the end 1039*d289c2baSAndroid Build Coastguard Worker of the file was encountered. 1040*d289c2baSAndroid Build Coastguard Worker 1041*d289c2baSAndroid Build Coastguard Worker The file cursor for reading is advanced by the number of bytes 1042*d289c2baSAndroid Build Coastguard Worker read. 1043*d289c2baSAndroid Build Coastguard Worker 1044*d289c2baSAndroid Build Coastguard Worker Arguments: 1045*d289c2baSAndroid Build Coastguard Worker size: Number of bytes to read. 1046*d289c2baSAndroid Build Coastguard Worker 1047*d289c2baSAndroid Build Coastguard Worker Returns: 1048*d289c2baSAndroid Build Coastguard Worker The data as bytes. 1049*d289c2baSAndroid Build Coastguard Worker """ 1050*d289c2baSAndroid Build Coastguard Worker if not self.is_sparse: 1051*d289c2baSAndroid Build Coastguard Worker self._image.seek(self._file_pos) 1052*d289c2baSAndroid Build Coastguard Worker data = self._image.read(size) 1053*d289c2baSAndroid Build Coastguard Worker self._file_pos += len(data) 1054*d289c2baSAndroid Build Coastguard Worker return data 1055*d289c2baSAndroid Build Coastguard Worker 1056*d289c2baSAndroid Build Coastguard Worker # Iterate over all chunks. 1057*d289c2baSAndroid Build Coastguard Worker chunk_idx = bisect.bisect_right(self._chunk_output_offsets, 1058*d289c2baSAndroid Build Coastguard Worker self._file_pos) - 1 1059*d289c2baSAndroid Build Coastguard Worker data = bytearray() 1060*d289c2baSAndroid Build Coastguard Worker to_go = size 1061*d289c2baSAndroid Build Coastguard Worker while to_go > 0: 1062*d289c2baSAndroid Build Coastguard Worker chunk = self._chunks[chunk_idx] 1063*d289c2baSAndroid Build Coastguard Worker chunk_pos_offset = self._file_pos - chunk.output_offset 1064*d289c2baSAndroid Build Coastguard Worker chunk_pos_to_go = min(chunk.output_size - chunk_pos_offset, to_go) 1065*d289c2baSAndroid Build Coastguard Worker 1066*d289c2baSAndroid Build Coastguard Worker if chunk.chunk_type == ImageChunk.TYPE_RAW: 1067*d289c2baSAndroid Build Coastguard Worker self._image.seek(chunk.input_offset + chunk_pos_offset) 1068*d289c2baSAndroid Build Coastguard Worker data.extend(self._image.read(chunk_pos_to_go)) 1069*d289c2baSAndroid Build Coastguard Worker elif chunk.chunk_type == ImageChunk.TYPE_FILL: 1070*d289c2baSAndroid Build Coastguard Worker all_data = chunk.fill_data*(chunk_pos_to_go // len(chunk.fill_data) + 2) 1071*d289c2baSAndroid Build Coastguard Worker offset_mod = chunk_pos_offset % len(chunk.fill_data) 1072*d289c2baSAndroid Build Coastguard Worker data.extend(all_data[offset_mod:(offset_mod + chunk_pos_to_go)]) 1073*d289c2baSAndroid Build Coastguard Worker else: 1074*d289c2baSAndroid Build Coastguard Worker assert chunk.chunk_type == ImageChunk.TYPE_DONT_CARE 1075*d289c2baSAndroid Build Coastguard Worker data.extend(b'\0' * chunk_pos_to_go) 1076*d289c2baSAndroid Build Coastguard Worker 1077*d289c2baSAndroid Build Coastguard Worker to_go -= chunk_pos_to_go 1078*d289c2baSAndroid Build Coastguard Worker self._file_pos += chunk_pos_to_go 1079*d289c2baSAndroid Build Coastguard Worker chunk_idx += 1 1080*d289c2baSAndroid Build Coastguard Worker # Generate partial read in case of EOF. 1081*d289c2baSAndroid Build Coastguard Worker if chunk_idx >= len(self._chunks): 1082*d289c2baSAndroid Build Coastguard Worker break 1083*d289c2baSAndroid Build Coastguard Worker 1084*d289c2baSAndroid Build Coastguard Worker return bytes(data) 1085*d289c2baSAndroid Build Coastguard Worker 1086*d289c2baSAndroid Build Coastguard Worker def tell(self): 1087*d289c2baSAndroid Build Coastguard Worker """Returns the file cursor position for reading from unsparsified file. 1088*d289c2baSAndroid Build Coastguard Worker 1089*d289c2baSAndroid Build Coastguard Worker Returns: 1090*d289c2baSAndroid Build Coastguard Worker The file cursor position for reading. 1091*d289c2baSAndroid Build Coastguard Worker """ 1092*d289c2baSAndroid Build Coastguard Worker return self._file_pos 1093*d289c2baSAndroid Build Coastguard Worker 1094*d289c2baSAndroid Build Coastguard Worker def truncate(self, size): 1095*d289c2baSAndroid Build Coastguard Worker """Truncates the unsparsified file. 1096*d289c2baSAndroid Build Coastguard Worker 1097*d289c2baSAndroid Build Coastguard Worker Arguments: 1098*d289c2baSAndroid Build Coastguard Worker size: Desired size of unsparsified file. 1099*d289c2baSAndroid Build Coastguard Worker 1100*d289c2baSAndroid Build Coastguard Worker Raises: 1101*d289c2baSAndroid Build Coastguard Worker ValueError: If desired size isn't a multiple of the block size. 1102*d289c2baSAndroid Build Coastguard Worker OSError: If ImageHandler was initialized in read-only mode. 1103*d289c2baSAndroid Build Coastguard Worker """ 1104*d289c2baSAndroid Build Coastguard Worker if self._read_only: 1105*d289c2baSAndroid Build Coastguard Worker raise OSError('ImageHandler is in read-only mode.') 1106*d289c2baSAndroid Build Coastguard Worker 1107*d289c2baSAndroid Build Coastguard Worker if not self.is_sparse: 1108*d289c2baSAndroid Build Coastguard Worker self._image.truncate(size) 1109*d289c2baSAndroid Build Coastguard Worker self._read_header() 1110*d289c2baSAndroid Build Coastguard Worker return 1111*d289c2baSAndroid Build Coastguard Worker 1112*d289c2baSAndroid Build Coastguard Worker if size % self.block_size != 0: 1113*d289c2baSAndroid Build Coastguard Worker raise ValueError('Cannot truncate to a size which is not a multiple ' 1114*d289c2baSAndroid Build Coastguard Worker 'of the block size') 1115*d289c2baSAndroid Build Coastguard Worker 1116*d289c2baSAndroid Build Coastguard Worker if size == self.image_size: 1117*d289c2baSAndroid Build Coastguard Worker # Trivial where there's nothing to do. 1118*d289c2baSAndroid Build Coastguard Worker return 1119*d289c2baSAndroid Build Coastguard Worker 1120*d289c2baSAndroid Build Coastguard Worker if size < self.image_size: 1121*d289c2baSAndroid Build Coastguard Worker chunk_idx = bisect.bisect_right(self._chunk_output_offsets, size) - 1 1122*d289c2baSAndroid Build Coastguard Worker chunk = self._chunks[chunk_idx] 1123*d289c2baSAndroid Build Coastguard Worker if chunk.output_offset != size: 1124*d289c2baSAndroid Build Coastguard Worker # Truncation in the middle of a trunk - need to keep the chunk 1125*d289c2baSAndroid Build Coastguard Worker # and modify it. 1126*d289c2baSAndroid Build Coastguard Worker chunk_idx_for_update = chunk_idx + 1 1127*d289c2baSAndroid Build Coastguard Worker num_to_keep = size - chunk.output_offset 1128*d289c2baSAndroid Build Coastguard Worker assert num_to_keep % self.block_size == 0 1129*d289c2baSAndroid Build Coastguard Worker if chunk.chunk_type == ImageChunk.TYPE_RAW: 1130*d289c2baSAndroid Build Coastguard Worker truncate_at = (chunk.chunk_offset + 1131*d289c2baSAndroid Build Coastguard Worker struct.calcsize(ImageChunk.FORMAT) + num_to_keep) 1132*d289c2baSAndroid Build Coastguard Worker data_sz = num_to_keep 1133*d289c2baSAndroid Build Coastguard Worker elif chunk.chunk_type == ImageChunk.TYPE_FILL: 1134*d289c2baSAndroid Build Coastguard Worker truncate_at = (chunk.chunk_offset + 1135*d289c2baSAndroid Build Coastguard Worker struct.calcsize(ImageChunk.FORMAT) + 4) 1136*d289c2baSAndroid Build Coastguard Worker data_sz = 4 1137*d289c2baSAndroid Build Coastguard Worker else: 1138*d289c2baSAndroid Build Coastguard Worker assert chunk.chunk_type == ImageChunk.TYPE_DONT_CARE 1139*d289c2baSAndroid Build Coastguard Worker truncate_at = chunk.chunk_offset + struct.calcsize(ImageChunk.FORMAT) 1140*d289c2baSAndroid Build Coastguard Worker data_sz = 0 1141*d289c2baSAndroid Build Coastguard Worker chunk_sz = num_to_keep // self.block_size 1142*d289c2baSAndroid Build Coastguard Worker total_sz = data_sz + struct.calcsize(ImageChunk.FORMAT) 1143*d289c2baSAndroid Build Coastguard Worker self._image.seek(chunk.chunk_offset) 1144*d289c2baSAndroid Build Coastguard Worker self._image.write(struct.pack(ImageChunk.FORMAT, 1145*d289c2baSAndroid Build Coastguard Worker chunk.chunk_type, 1146*d289c2baSAndroid Build Coastguard Worker 0, # Reserved 1147*d289c2baSAndroid Build Coastguard Worker chunk_sz, 1148*d289c2baSAndroid Build Coastguard Worker total_sz)) 1149*d289c2baSAndroid Build Coastguard Worker chunk.output_size = num_to_keep 1150*d289c2baSAndroid Build Coastguard Worker else: 1151*d289c2baSAndroid Build Coastguard Worker # Truncation at trunk boundary. 1152*d289c2baSAndroid Build Coastguard Worker truncate_at = chunk.chunk_offset 1153*d289c2baSAndroid Build Coastguard Worker chunk_idx_for_update = chunk_idx 1154*d289c2baSAndroid Build Coastguard Worker 1155*d289c2baSAndroid Build Coastguard Worker self._num_total_chunks = chunk_idx_for_update 1156*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks = 0 1157*d289c2baSAndroid Build Coastguard Worker for i in range(0, chunk_idx_for_update): 1158*d289c2baSAndroid Build Coastguard Worker self._num_total_blocks += self._chunks[i].output_size // self.block_size 1159*d289c2baSAndroid Build Coastguard Worker self._update_chunks_and_blocks() 1160*d289c2baSAndroid Build Coastguard Worker self._image.truncate(truncate_at) 1161*d289c2baSAndroid Build Coastguard Worker 1162*d289c2baSAndroid Build Coastguard Worker # We've modified the file so re-read all data. 1163*d289c2baSAndroid Build Coastguard Worker self._read_header() 1164*d289c2baSAndroid Build Coastguard Worker else: 1165*d289c2baSAndroid Build Coastguard Worker # Truncating to grow - just add a DONT_CARE section. 1166*d289c2baSAndroid Build Coastguard Worker self.append_dont_care(size - self.image_size) 1167*d289c2baSAndroid Build Coastguard Worker 1168*d289c2baSAndroid Build Coastguard Worker 1169*d289c2baSAndroid Build Coastguard Workerclass AvbDescriptor(object): 1170*d289c2baSAndroid Build Coastguard Worker """Class for AVB descriptor. 1171*d289c2baSAndroid Build Coastguard Worker 1172*d289c2baSAndroid Build Coastguard Worker See the |AvbDescriptor| C struct for more information. 1173*d289c2baSAndroid Build Coastguard Worker 1174*d289c2baSAndroid Build Coastguard Worker Attributes: 1175*d289c2baSAndroid Build Coastguard Worker tag: The tag identifying what kind of descriptor this is. 1176*d289c2baSAndroid Build Coastguard Worker data: The data in the descriptor. 1177*d289c2baSAndroid Build Coastguard Worker """ 1178*d289c2baSAndroid Build Coastguard Worker 1179*d289c2baSAndroid Build Coastguard Worker SIZE = 16 1180*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!QQ') # tag, num_bytes_following (descriptor header) 1181*d289c2baSAndroid Build Coastguard Worker 1182*d289c2baSAndroid Build Coastguard Worker def __init__(self, data): 1183*d289c2baSAndroid Build Coastguard Worker """Initializes a new property descriptor. 1184*d289c2baSAndroid Build Coastguard Worker 1185*d289c2baSAndroid Build Coastguard Worker Arguments: 1186*d289c2baSAndroid Build Coastguard Worker data: If not None, must be a bytearray(). 1187*d289c2baSAndroid Build Coastguard Worker 1188*d289c2baSAndroid Build Coastguard Worker Raises: 1189*d289c2baSAndroid Build Coastguard Worker LookupError: If the given descriptor is malformed. 1190*d289c2baSAndroid Build Coastguard Worker """ 1191*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 1192*d289c2baSAndroid Build Coastguard Worker 1193*d289c2baSAndroid Build Coastguard Worker if data: 1194*d289c2baSAndroid Build Coastguard Worker (self.tag, num_bytes_following) = ( 1195*d289c2baSAndroid Build Coastguard Worker struct.unpack(self.FORMAT_STRING, data[0:self.SIZE])) 1196*d289c2baSAndroid Build Coastguard Worker self.data = data[self.SIZE:self.SIZE + num_bytes_following] 1197*d289c2baSAndroid Build Coastguard Worker else: 1198*d289c2baSAndroid Build Coastguard Worker self.tag = None 1199*d289c2baSAndroid Build Coastguard Worker self.data = None 1200*d289c2baSAndroid Build Coastguard Worker 1201*d289c2baSAndroid Build Coastguard Worker def print_desc(self, o): 1202*d289c2baSAndroid Build Coastguard Worker """Print the descriptor. 1203*d289c2baSAndroid Build Coastguard Worker 1204*d289c2baSAndroid Build Coastguard Worker Arguments: 1205*d289c2baSAndroid Build Coastguard Worker o: The object to write the output to. 1206*d289c2baSAndroid Build Coastguard Worker """ 1207*d289c2baSAndroid Build Coastguard Worker o.write(' Unknown descriptor:\n') 1208*d289c2baSAndroid Build Coastguard Worker o.write(' Tag: {}\n'.format(self.tag)) 1209*d289c2baSAndroid Build Coastguard Worker if len(self.data) < 256: 1210*d289c2baSAndroid Build Coastguard Worker o.write(' Data: {} ({} bytes)\n'.format( 1211*d289c2baSAndroid Build Coastguard Worker repr(str(self.data)), len(self.data))) 1212*d289c2baSAndroid Build Coastguard Worker else: 1213*d289c2baSAndroid Build Coastguard Worker o.write(' Data: {} bytes\n'.format(len(self.data))) 1214*d289c2baSAndroid Build Coastguard Worker 1215*d289c2baSAndroid Build Coastguard Worker def encode(self): 1216*d289c2baSAndroid Build Coastguard Worker """Serializes the descriptor. 1217*d289c2baSAndroid Build Coastguard Worker 1218*d289c2baSAndroid Build Coastguard Worker Returns: 1219*d289c2baSAndroid Build Coastguard Worker A bytearray() with the descriptor data. 1220*d289c2baSAndroid Build Coastguard Worker """ 1221*d289c2baSAndroid Build Coastguard Worker num_bytes_following = len(self.data) 1222*d289c2baSAndroid Build Coastguard Worker nbf_with_padding = round_to_multiple(num_bytes_following, 8) 1223*d289c2baSAndroid Build Coastguard Worker padding_size = nbf_with_padding - num_bytes_following 1224*d289c2baSAndroid Build Coastguard Worker desc = struct.pack(self.FORMAT_STRING, self.tag, nbf_with_padding) 1225*d289c2baSAndroid Build Coastguard Worker padding = struct.pack(str(padding_size) + 'x') 1226*d289c2baSAndroid Build Coastguard Worker ret = desc + self.data + padding 1227*d289c2baSAndroid Build Coastguard Worker return bytearray(ret) 1228*d289c2baSAndroid Build Coastguard Worker 1229*d289c2baSAndroid Build Coastguard Worker def verify(self, image_dir, image_ext, expected_chain_partitions_map, 1230*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor, accept_zeroed_hashtree): 1231*d289c2baSAndroid Build Coastguard Worker """Verifies contents of the descriptor - used in verify_image sub-command. 1232*d289c2baSAndroid Build Coastguard Worker 1233*d289c2baSAndroid Build Coastguard Worker Arguments: 1234*d289c2baSAndroid Build Coastguard Worker image_dir: The directory of the file being verified. 1235*d289c2baSAndroid Build Coastguard Worker image_ext: The extension of the file being verified (e.g. '.img'). 1236*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map: A map from partition name to the 1237*d289c2baSAndroid Build Coastguard Worker tuple (rollback_index_location, key_blob). 1238*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor: The image the descriptor is in. 1239*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 1240*d289c2baSAndroid Build Coastguard Worker zeroed out. 1241*d289c2baSAndroid Build Coastguard Worker 1242*d289c2baSAndroid Build Coastguard Worker Returns: 1243*d289c2baSAndroid Build Coastguard Worker True if the descriptor verifies, False otherwise. 1244*d289c2baSAndroid Build Coastguard Worker """ 1245*d289c2baSAndroid Build Coastguard Worker # Deletes unused parameters to prevent pylint warning unused-argument. 1246*d289c2baSAndroid Build Coastguard Worker del image_dir, image_ext, expected_chain_partitions_map 1247*d289c2baSAndroid Build Coastguard Worker del image_containing_descriptor, accept_zeroed_hashtree 1248*d289c2baSAndroid Build Coastguard Worker 1249*d289c2baSAndroid Build Coastguard Worker # Nothing to do. 1250*d289c2baSAndroid Build Coastguard Worker return True 1251*d289c2baSAndroid Build Coastguard Worker 1252*d289c2baSAndroid Build Coastguard Worker 1253*d289c2baSAndroid Build Coastguard Workerclass AvbPropertyDescriptor(AvbDescriptor): 1254*d289c2baSAndroid Build Coastguard Worker """A class for property descriptors. 1255*d289c2baSAndroid Build Coastguard Worker 1256*d289c2baSAndroid Build Coastguard Worker See the |AvbPropertyDescriptor| C struct for more information. 1257*d289c2baSAndroid Build Coastguard Worker 1258*d289c2baSAndroid Build Coastguard Worker Attributes: 1259*d289c2baSAndroid Build Coastguard Worker key: The key as string. 1260*d289c2baSAndroid Build Coastguard Worker value: The value as bytes. 1261*d289c2baSAndroid Build Coastguard Worker """ 1262*d289c2baSAndroid Build Coastguard Worker 1263*d289c2baSAndroid Build Coastguard Worker TAG = 0 1264*d289c2baSAndroid Build Coastguard Worker SIZE = 32 1265*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!QQ' # tag, num_bytes_following (descriptor header) 1266*d289c2baSAndroid Build Coastguard Worker 'Q' # key size (bytes) 1267*d289c2baSAndroid Build Coastguard Worker 'Q') # value size (bytes) 1268*d289c2baSAndroid Build Coastguard Worker 1269*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 1270*d289c2baSAndroid Build Coastguard Worker """Initializes a new property descriptor. 1271*d289c2baSAndroid Build Coastguard Worker 1272*d289c2baSAndroid Build Coastguard Worker Arguments: 1273*d289c2baSAndroid Build Coastguard Worker data: If not None, must be as bytes of size |SIZE|. 1274*d289c2baSAndroid Build Coastguard Worker 1275*d289c2baSAndroid Build Coastguard Worker Raises: 1276*d289c2baSAndroid Build Coastguard Worker LookupError: If the given descriptor is malformed. 1277*d289c2baSAndroid Build Coastguard Worker """ 1278*d289c2baSAndroid Build Coastguard Worker super().__init__(None) 1279*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 1280*d289c2baSAndroid Build Coastguard Worker 1281*d289c2baSAndroid Build Coastguard Worker if data: 1282*d289c2baSAndroid Build Coastguard Worker (tag, num_bytes_following, key_size, 1283*d289c2baSAndroid Build Coastguard Worker value_size) = struct.unpack(self.FORMAT_STRING, data[0:self.SIZE]) 1284*d289c2baSAndroid Build Coastguard Worker expected_size = round_to_multiple( 1285*d289c2baSAndroid Build Coastguard Worker self.SIZE - 16 + key_size + 1 + value_size + 1, 8) 1286*d289c2baSAndroid Build Coastguard Worker if tag != self.TAG or num_bytes_following != expected_size: 1287*d289c2baSAndroid Build Coastguard Worker raise LookupError('Given data does not look like a property ' 1288*d289c2baSAndroid Build Coastguard Worker 'descriptor.') 1289*d289c2baSAndroid Build Coastguard Worker try: 1290*d289c2baSAndroid Build Coastguard Worker self.key = data[self.SIZE:(self.SIZE + key_size)].decode('utf-8') 1291*d289c2baSAndroid Build Coastguard Worker except UnicodeDecodeError as e: 1292*d289c2baSAndroid Build Coastguard Worker raise LookupError('Key cannot be decoded as UTF-8: {}.' 1293*d289c2baSAndroid Build Coastguard Worker .format(e)) from e 1294*d289c2baSAndroid Build Coastguard Worker self.value = data[(self.SIZE + key_size + 1):(self.SIZE + key_size + 1 + 1295*d289c2baSAndroid Build Coastguard Worker value_size)] 1296*d289c2baSAndroid Build Coastguard Worker else: 1297*d289c2baSAndroid Build Coastguard Worker self.key = '' 1298*d289c2baSAndroid Build Coastguard Worker self.value = b'' 1299*d289c2baSAndroid Build Coastguard Worker 1300*d289c2baSAndroid Build Coastguard Worker def print_desc(self, o): 1301*d289c2baSAndroid Build Coastguard Worker """Print the descriptor. 1302*d289c2baSAndroid Build Coastguard Worker 1303*d289c2baSAndroid Build Coastguard Worker Arguments: 1304*d289c2baSAndroid Build Coastguard Worker o: The object to write the output to. 1305*d289c2baSAndroid Build Coastguard Worker """ 1306*d289c2baSAndroid Build Coastguard Worker # Go forward with python 3, bytes are represented with the 'b' prefix, 1307*d289c2baSAndroid Build Coastguard Worker # e.g. b'foobar'. Thus, we trim off the 'b' to keep the print output 1308*d289c2baSAndroid Build Coastguard Worker # the same between python 2 and python 3. 1309*d289c2baSAndroid Build Coastguard Worker printable_value = repr(self.value) 1310*d289c2baSAndroid Build Coastguard Worker if printable_value.startswith('b\''): 1311*d289c2baSAndroid Build Coastguard Worker printable_value = printable_value[1:] 1312*d289c2baSAndroid Build Coastguard Worker 1313*d289c2baSAndroid Build Coastguard Worker if len(self.value) < 256: 1314*d289c2baSAndroid Build Coastguard Worker o.write(' Prop: {} -> {}\n'.format(self.key, printable_value)) 1315*d289c2baSAndroid Build Coastguard Worker else: 1316*d289c2baSAndroid Build Coastguard Worker o.write(' Prop: {} -> ({} bytes)\n'.format(self.key, len(self.value))) 1317*d289c2baSAndroid Build Coastguard Worker 1318*d289c2baSAndroid Build Coastguard Worker def encode(self): 1319*d289c2baSAndroid Build Coastguard Worker """Serializes the descriptor. 1320*d289c2baSAndroid Build Coastguard Worker 1321*d289c2baSAndroid Build Coastguard Worker Returns: 1322*d289c2baSAndroid Build Coastguard Worker The descriptor data as bytes. 1323*d289c2baSAndroid Build Coastguard Worker """ 1324*d289c2baSAndroid Build Coastguard Worker key_encoded = self.key.encode('utf-8') 1325*d289c2baSAndroid Build Coastguard Worker num_bytes_following = ( 1326*d289c2baSAndroid Build Coastguard Worker self.SIZE + len(key_encoded) + len(self.value) + 2 - 16) 1327*d289c2baSAndroid Build Coastguard Worker nbf_with_padding = round_to_multiple(num_bytes_following, 8) 1328*d289c2baSAndroid Build Coastguard Worker padding_size = nbf_with_padding - num_bytes_following 1329*d289c2baSAndroid Build Coastguard Worker desc = struct.pack(self.FORMAT_STRING, self.TAG, nbf_with_padding, 1330*d289c2baSAndroid Build Coastguard Worker len(key_encoded), len(self.value)) 1331*d289c2baSAndroid Build Coastguard Worker ret = (desc + key_encoded + b'\0' + self.value + b'\0' + 1332*d289c2baSAndroid Build Coastguard Worker padding_size * b'\0') 1333*d289c2baSAndroid Build Coastguard Worker return ret 1334*d289c2baSAndroid Build Coastguard Worker 1335*d289c2baSAndroid Build Coastguard Worker def verify(self, image_dir, image_ext, expected_chain_partitions_map, 1336*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor, accept_zeroed_hashtree): 1337*d289c2baSAndroid Build Coastguard Worker """Verifies contents of the descriptor - used in verify_image sub-command. 1338*d289c2baSAndroid Build Coastguard Worker 1339*d289c2baSAndroid Build Coastguard Worker Arguments: 1340*d289c2baSAndroid Build Coastguard Worker image_dir: The directory of the file being verified. 1341*d289c2baSAndroid Build Coastguard Worker image_ext: The extension of the file being verified (e.g. '.img'). 1342*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map: A map from partition name to the 1343*d289c2baSAndroid Build Coastguard Worker tuple (rollback_index_location, key_blob). 1344*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor: The image the descriptor is in. 1345*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 1346*d289c2baSAndroid Build Coastguard Worker zeroed out. 1347*d289c2baSAndroid Build Coastguard Worker 1348*d289c2baSAndroid Build Coastguard Worker Returns: 1349*d289c2baSAndroid Build Coastguard Worker True if the descriptor verifies, False otherwise. 1350*d289c2baSAndroid Build Coastguard Worker """ 1351*d289c2baSAndroid Build Coastguard Worker # Nothing to do. 1352*d289c2baSAndroid Build Coastguard Worker return True 1353*d289c2baSAndroid Build Coastguard Worker 1354*d289c2baSAndroid Build Coastguard Worker 1355*d289c2baSAndroid Build Coastguard Workerclass AvbHashtreeDescriptor(AvbDescriptor): 1356*d289c2baSAndroid Build Coastguard Worker """A class for hashtree descriptors. 1357*d289c2baSAndroid Build Coastguard Worker 1358*d289c2baSAndroid Build Coastguard Worker See the |AvbHashtreeDescriptor| C struct for more information. 1359*d289c2baSAndroid Build Coastguard Worker 1360*d289c2baSAndroid Build Coastguard Worker Attributes: 1361*d289c2baSAndroid Build Coastguard Worker dm_verity_version: dm-verity version used. 1362*d289c2baSAndroid Build Coastguard Worker image_size: Size of the image, after rounding up to |block_size|. 1363*d289c2baSAndroid Build Coastguard Worker tree_offset: Offset of the hash tree in the file. 1364*d289c2baSAndroid Build Coastguard Worker tree_size: Size of the tree. 1365*d289c2baSAndroid Build Coastguard Worker data_block_size: Data block size. 1366*d289c2baSAndroid Build Coastguard Worker hash_block_size: Hash block size. 1367*d289c2baSAndroid Build Coastguard Worker fec_num_roots: Number of roots used for FEC (0 if FEC is not used). 1368*d289c2baSAndroid Build Coastguard Worker fec_offset: Offset of FEC data (0 if FEC is not used). 1369*d289c2baSAndroid Build Coastguard Worker fec_size: Size of FEC data (0 if FEC is not used). 1370*d289c2baSAndroid Build Coastguard Worker hash_algorithm: Hash algorithm used as string. 1371*d289c2baSAndroid Build Coastguard Worker partition_name: Partition name as string. 1372*d289c2baSAndroid Build Coastguard Worker salt: Salt used as bytes. 1373*d289c2baSAndroid Build Coastguard Worker root_digest: Root digest as bytes. 1374*d289c2baSAndroid Build Coastguard Worker flags: Descriptor flags (see avb_hashtree_descriptor.h). 1375*d289c2baSAndroid Build Coastguard Worker """ 1376*d289c2baSAndroid Build Coastguard Worker 1377*d289c2baSAndroid Build Coastguard Worker TAG = 1 1378*d289c2baSAndroid Build Coastguard Worker RESERVED = 60 1379*d289c2baSAndroid Build Coastguard Worker SIZE = 120 + RESERVED 1380*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!QQ' # tag, num_bytes_following (descriptor header) 1381*d289c2baSAndroid Build Coastguard Worker 'L' # dm-verity version used 1382*d289c2baSAndroid Build Coastguard Worker 'Q' # image size (bytes) 1383*d289c2baSAndroid Build Coastguard Worker 'Q' # tree offset (bytes) 1384*d289c2baSAndroid Build Coastguard Worker 'Q' # tree size (bytes) 1385*d289c2baSAndroid Build Coastguard Worker 'L' # data block size (bytes) 1386*d289c2baSAndroid Build Coastguard Worker 'L' # hash block size (bytes) 1387*d289c2baSAndroid Build Coastguard Worker 'L' # FEC number of roots 1388*d289c2baSAndroid Build Coastguard Worker 'Q' # FEC offset (bytes) 1389*d289c2baSAndroid Build Coastguard Worker 'Q' # FEC size (bytes) 1390*d289c2baSAndroid Build Coastguard Worker '32s' # hash algorithm used 1391*d289c2baSAndroid Build Coastguard Worker 'L' # partition name (bytes) 1392*d289c2baSAndroid Build Coastguard Worker 'L' # salt length (bytes) 1393*d289c2baSAndroid Build Coastguard Worker 'L' # root digest length (bytes) 1394*d289c2baSAndroid Build Coastguard Worker 'L' + # flags 1395*d289c2baSAndroid Build Coastguard Worker str(RESERVED) + 's') # reserved 1396*d289c2baSAndroid Build Coastguard Worker 1397*d289c2baSAndroid Build Coastguard Worker FLAGS_DO_NOT_USE_AB = (1 << 0) 1398*d289c2baSAndroid Build Coastguard Worker FLAGS_CHECK_AT_MOST_ONCE = (1 << 1) 1399*d289c2baSAndroid Build Coastguard Worker 1400*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 1401*d289c2baSAndroid Build Coastguard Worker """Initializes a new hashtree descriptor. 1402*d289c2baSAndroid Build Coastguard Worker 1403*d289c2baSAndroid Build Coastguard Worker Arguments: 1404*d289c2baSAndroid Build Coastguard Worker data: If not None, must be bytes of size |SIZE|. 1405*d289c2baSAndroid Build Coastguard Worker 1406*d289c2baSAndroid Build Coastguard Worker Raises: 1407*d289c2baSAndroid Build Coastguard Worker LookupError: If the given descriptor is malformed. 1408*d289c2baSAndroid Build Coastguard Worker """ 1409*d289c2baSAndroid Build Coastguard Worker super().__init__(None) 1410*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 1411*d289c2baSAndroid Build Coastguard Worker 1412*d289c2baSAndroid Build Coastguard Worker if data: 1413*d289c2baSAndroid Build Coastguard Worker (tag, num_bytes_following, self.dm_verity_version, self.image_size, 1414*d289c2baSAndroid Build Coastguard Worker self.tree_offset, self.tree_size, self.data_block_size, 1415*d289c2baSAndroid Build Coastguard Worker self.hash_block_size, self.fec_num_roots, self.fec_offset, self.fec_size, 1416*d289c2baSAndroid Build Coastguard Worker self.hash_algorithm, partition_name_len, salt_len, 1417*d289c2baSAndroid Build Coastguard Worker root_digest_len, self.flags, _) = struct.unpack(self.FORMAT_STRING, 1418*d289c2baSAndroid Build Coastguard Worker data[0:self.SIZE]) 1419*d289c2baSAndroid Build Coastguard Worker expected_size = round_to_multiple( 1420*d289c2baSAndroid Build Coastguard Worker self.SIZE - 16 + partition_name_len + salt_len + root_digest_len, 8) 1421*d289c2baSAndroid Build Coastguard Worker if tag != self.TAG or num_bytes_following != expected_size: 1422*d289c2baSAndroid Build Coastguard Worker raise LookupError('Given data does not look like a hashtree ' 1423*d289c2baSAndroid Build Coastguard Worker 'descriptor.') 1424*d289c2baSAndroid Build Coastguard Worker # Nuke NUL-bytes at the end. 1425*d289c2baSAndroid Build Coastguard Worker self.hash_algorithm = self.hash_algorithm.rstrip(b'\0').decode('ascii') 1426*d289c2baSAndroid Build Coastguard Worker o = 0 1427*d289c2baSAndroid Build Coastguard Worker try: 1428*d289c2baSAndroid Build Coastguard Worker self.partition_name = data[ 1429*d289c2baSAndroid Build Coastguard Worker (self.SIZE + o):(self.SIZE + o + partition_name_len) 1430*d289c2baSAndroid Build Coastguard Worker ].decode('utf-8') 1431*d289c2baSAndroid Build Coastguard Worker except UnicodeDecodeError as e: 1432*d289c2baSAndroid Build Coastguard Worker raise LookupError('Partition name cannot be decoded as UTF-8: {}.' 1433*d289c2baSAndroid Build Coastguard Worker .format(e)) from e 1434*d289c2baSAndroid Build Coastguard Worker o += partition_name_len 1435*d289c2baSAndroid Build Coastguard Worker self.salt = data[(self.SIZE + o):(self.SIZE + o + salt_len)] 1436*d289c2baSAndroid Build Coastguard Worker o += salt_len 1437*d289c2baSAndroid Build Coastguard Worker self.root_digest = data[(self.SIZE + o):(self.SIZE + o + root_digest_len)] 1438*d289c2baSAndroid Build Coastguard Worker 1439*d289c2baSAndroid Build Coastguard Worker if root_digest_len != self._hashtree_digest_size(): 1440*d289c2baSAndroid Build Coastguard Worker if root_digest_len != 0: 1441*d289c2baSAndroid Build Coastguard Worker raise LookupError('root_digest_len doesn\'t match hash algorithm') 1442*d289c2baSAndroid Build Coastguard Worker 1443*d289c2baSAndroid Build Coastguard Worker else: 1444*d289c2baSAndroid Build Coastguard Worker self.dm_verity_version = 0 1445*d289c2baSAndroid Build Coastguard Worker self.image_size = 0 1446*d289c2baSAndroid Build Coastguard Worker self.tree_offset = 0 1447*d289c2baSAndroid Build Coastguard Worker self.tree_size = 0 1448*d289c2baSAndroid Build Coastguard Worker self.data_block_size = 0 1449*d289c2baSAndroid Build Coastguard Worker self.hash_block_size = 0 1450*d289c2baSAndroid Build Coastguard Worker self.fec_num_roots = 0 1451*d289c2baSAndroid Build Coastguard Worker self.fec_offset = 0 1452*d289c2baSAndroid Build Coastguard Worker self.fec_size = 0 1453*d289c2baSAndroid Build Coastguard Worker self.hash_algorithm = '' 1454*d289c2baSAndroid Build Coastguard Worker self.partition_name = '' 1455*d289c2baSAndroid Build Coastguard Worker self.salt = b'' 1456*d289c2baSAndroid Build Coastguard Worker self.root_digest = b'' 1457*d289c2baSAndroid Build Coastguard Worker self.flags = 0 1458*d289c2baSAndroid Build Coastguard Worker 1459*d289c2baSAndroid Build Coastguard Worker def _hashtree_digest_size(self): 1460*d289c2baSAndroid Build Coastguard Worker return len(create_avb_hashtree_hasher(self.hash_algorithm, b'').digest()) 1461*d289c2baSAndroid Build Coastguard Worker 1462*d289c2baSAndroid Build Coastguard Worker def print_desc(self, o): 1463*d289c2baSAndroid Build Coastguard Worker """Print the descriptor. 1464*d289c2baSAndroid Build Coastguard Worker 1465*d289c2baSAndroid Build Coastguard Worker Arguments: 1466*d289c2baSAndroid Build Coastguard Worker o: The object to write the output to. 1467*d289c2baSAndroid Build Coastguard Worker """ 1468*d289c2baSAndroid Build Coastguard Worker o.write(' Hashtree descriptor:\n') 1469*d289c2baSAndroid Build Coastguard Worker o.write(' Version of dm-verity: {}\n'.format(self.dm_verity_version)) 1470*d289c2baSAndroid Build Coastguard Worker o.write(' Image Size: {} bytes\n'.format(self.image_size)) 1471*d289c2baSAndroid Build Coastguard Worker o.write(' Tree Offset: {}\n'.format(self.tree_offset)) 1472*d289c2baSAndroid Build Coastguard Worker o.write(' Tree Size: {} bytes\n'.format(self.tree_size)) 1473*d289c2baSAndroid Build Coastguard Worker o.write(' Data Block Size: {} bytes\n'.format( 1474*d289c2baSAndroid Build Coastguard Worker self.data_block_size)) 1475*d289c2baSAndroid Build Coastguard Worker o.write(' Hash Block Size: {} bytes\n'.format( 1476*d289c2baSAndroid Build Coastguard Worker self.hash_block_size)) 1477*d289c2baSAndroid Build Coastguard Worker o.write(' FEC num roots: {}\n'.format(self.fec_num_roots)) 1478*d289c2baSAndroid Build Coastguard Worker o.write(' FEC offset: {}\n'.format(self.fec_offset)) 1479*d289c2baSAndroid Build Coastguard Worker o.write(' FEC size: {} bytes\n'.format(self.fec_size)) 1480*d289c2baSAndroid Build Coastguard Worker o.write(' Hash Algorithm: {}\n'.format(self.hash_algorithm)) 1481*d289c2baSAndroid Build Coastguard Worker o.write(' Partition Name: {}\n'.format(self.partition_name)) 1482*d289c2baSAndroid Build Coastguard Worker o.write(' Salt: {}\n'.format(self.salt.hex())) 1483*d289c2baSAndroid Build Coastguard Worker o.write(' Root Digest: {}\n'.format(self.root_digest.hex())) 1484*d289c2baSAndroid Build Coastguard Worker o.write(' Flags: {}\n'.format(self.flags)) 1485*d289c2baSAndroid Build Coastguard Worker 1486*d289c2baSAndroid Build Coastguard Worker def encode(self): 1487*d289c2baSAndroid Build Coastguard Worker """Serializes the descriptor. 1488*d289c2baSAndroid Build Coastguard Worker 1489*d289c2baSAndroid Build Coastguard Worker Returns: 1490*d289c2baSAndroid Build Coastguard Worker The descriptor data as bytes. 1491*d289c2baSAndroid Build Coastguard Worker """ 1492*d289c2baSAndroid Build Coastguard Worker hash_algorithm_encoded = self.hash_algorithm.encode('ascii') 1493*d289c2baSAndroid Build Coastguard Worker partition_name_encoded = self.partition_name.encode('utf-8') 1494*d289c2baSAndroid Build Coastguard Worker num_bytes_following = (self.SIZE + len(partition_name_encoded) 1495*d289c2baSAndroid Build Coastguard Worker + len(self.salt) + len(self.root_digest) - 16) 1496*d289c2baSAndroid Build Coastguard Worker nbf_with_padding = round_to_multiple(num_bytes_following, 8) 1497*d289c2baSAndroid Build Coastguard Worker padding_size = nbf_with_padding - num_bytes_following 1498*d289c2baSAndroid Build Coastguard Worker desc = struct.pack(self.FORMAT_STRING, self.TAG, nbf_with_padding, 1499*d289c2baSAndroid Build Coastguard Worker self.dm_verity_version, self.image_size, 1500*d289c2baSAndroid Build Coastguard Worker self.tree_offset, self.tree_size, self.data_block_size, 1501*d289c2baSAndroid Build Coastguard Worker self.hash_block_size, self.fec_num_roots, 1502*d289c2baSAndroid Build Coastguard Worker self.fec_offset, self.fec_size, hash_algorithm_encoded, 1503*d289c2baSAndroid Build Coastguard Worker len(partition_name_encoded), len(self.salt), 1504*d289c2baSAndroid Build Coastguard Worker len(self.root_digest), self.flags, self.RESERVED * b'\0') 1505*d289c2baSAndroid Build Coastguard Worker ret = (desc + partition_name_encoded + self.salt + self.root_digest + 1506*d289c2baSAndroid Build Coastguard Worker padding_size * b'\0') 1507*d289c2baSAndroid Build Coastguard Worker return ret 1508*d289c2baSAndroid Build Coastguard Worker 1509*d289c2baSAndroid Build Coastguard Worker def verify(self, image_dir, image_ext, expected_chain_partitions_map, 1510*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor, accept_zeroed_hashtree): 1511*d289c2baSAndroid Build Coastguard Worker """Verifies contents of the descriptor - used in verify_image sub-command. 1512*d289c2baSAndroid Build Coastguard Worker 1513*d289c2baSAndroid Build Coastguard Worker Arguments: 1514*d289c2baSAndroid Build Coastguard Worker image_dir: The directory of the file being verified. 1515*d289c2baSAndroid Build Coastguard Worker image_ext: The extension of the file being verified (e.g. '.img'). 1516*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map: A map from partition name to the 1517*d289c2baSAndroid Build Coastguard Worker tuple (rollback_index_location, key_blob). 1518*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor: The image the descriptor is in. 1519*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 1520*d289c2baSAndroid Build Coastguard Worker zeroed out. 1521*d289c2baSAndroid Build Coastguard Worker 1522*d289c2baSAndroid Build Coastguard Worker Returns: 1523*d289c2baSAndroid Build Coastguard Worker True if the descriptor verifies, False otherwise. 1524*d289c2baSAndroid Build Coastguard Worker """ 1525*d289c2baSAndroid Build Coastguard Worker if not self.partition_name: 1526*d289c2baSAndroid Build Coastguard Worker image_filename = image_containing_descriptor.filename 1527*d289c2baSAndroid Build Coastguard Worker image = image_containing_descriptor 1528*d289c2baSAndroid Build Coastguard Worker else: 1529*d289c2baSAndroid Build Coastguard Worker image_filename = os.path.join(image_dir, self.partition_name + image_ext) 1530*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 1531*d289c2baSAndroid Build Coastguard Worker # Generate the hashtree and checks that it matches what's in the file. 1532*d289c2baSAndroid Build Coastguard Worker digest_size = self._hashtree_digest_size() 1533*d289c2baSAndroid Build Coastguard Worker digest_padding = round_to_pow2(digest_size) - digest_size 1534*d289c2baSAndroid Build Coastguard Worker (hash_level_offsets, tree_size) = calc_hash_level_offsets( 1535*d289c2baSAndroid Build Coastguard Worker self.image_size, self.data_block_size, digest_size + digest_padding) 1536*d289c2baSAndroid Build Coastguard Worker root_digest, hash_tree = generate_hash_tree(image, self.image_size, 1537*d289c2baSAndroid Build Coastguard Worker self.data_block_size, 1538*d289c2baSAndroid Build Coastguard Worker self.hash_algorithm, self.salt, 1539*d289c2baSAndroid Build Coastguard Worker digest_padding, 1540*d289c2baSAndroid Build Coastguard Worker hash_level_offsets, 1541*d289c2baSAndroid Build Coastguard Worker tree_size) 1542*d289c2baSAndroid Build Coastguard Worker # The root digest must match unless it is not embedded in the descriptor. 1543*d289c2baSAndroid Build Coastguard Worker if self.root_digest and root_digest != self.root_digest: 1544*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('hashtree of {} does not match descriptor\n'. 1545*d289c2baSAndroid Build Coastguard Worker format(image_filename)) 1546*d289c2baSAndroid Build Coastguard Worker return False 1547*d289c2baSAndroid Build Coastguard Worker # ... also check that the on-disk hashtree matches 1548*d289c2baSAndroid Build Coastguard Worker image.seek(self.tree_offset) 1549*d289c2baSAndroid Build Coastguard Worker hash_tree_ondisk = image.read(self.tree_size) 1550*d289c2baSAndroid Build Coastguard Worker is_zeroed = (self.tree_size == 0) or (hash_tree_ondisk[0:8] == b'ZeRoHaSH') 1551*d289c2baSAndroid Build Coastguard Worker if is_zeroed and accept_zeroed_hashtree: 1552*d289c2baSAndroid Build Coastguard Worker print('{}: skipping verification since hashtree is zeroed and ' 1553*d289c2baSAndroid Build Coastguard Worker '--accept_zeroed_hashtree was given' 1554*d289c2baSAndroid Build Coastguard Worker .format(self.partition_name)) 1555*d289c2baSAndroid Build Coastguard Worker else: 1556*d289c2baSAndroid Build Coastguard Worker if hash_tree != hash_tree_ondisk: 1557*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('hashtree of {} contains invalid data\n'. 1558*d289c2baSAndroid Build Coastguard Worker format(image_filename)) 1559*d289c2baSAndroid Build Coastguard Worker return False 1560*d289c2baSAndroid Build Coastguard Worker print('{}: Successfully verified {} hashtree of {} for image of {} bytes' 1561*d289c2baSAndroid Build Coastguard Worker .format(self.partition_name, self.hash_algorithm, image.filename, 1562*d289c2baSAndroid Build Coastguard Worker self.image_size)) 1563*d289c2baSAndroid Build Coastguard Worker # TODO(zeuthen): we could also verify that the FEC stored in the image is 1564*d289c2baSAndroid Build Coastguard Worker # correct but this a) currently requires the 'fec' binary; and b) takes a 1565*d289c2baSAndroid Build Coastguard Worker # long time; and c) is not strictly needed for verification purposes as 1566*d289c2baSAndroid Build Coastguard Worker # we've already verified the root hash. 1567*d289c2baSAndroid Build Coastguard Worker return True 1568*d289c2baSAndroid Build Coastguard Worker 1569*d289c2baSAndroid Build Coastguard Worker 1570*d289c2baSAndroid Build Coastguard Workerclass AvbHashDescriptor(AvbDescriptor): 1571*d289c2baSAndroid Build Coastguard Worker """A class for hash descriptors. 1572*d289c2baSAndroid Build Coastguard Worker 1573*d289c2baSAndroid Build Coastguard Worker See the |AvbHashDescriptor| C struct for more information. 1574*d289c2baSAndroid Build Coastguard Worker 1575*d289c2baSAndroid Build Coastguard Worker Attributes: 1576*d289c2baSAndroid Build Coastguard Worker image_size: Image size, in bytes. 1577*d289c2baSAndroid Build Coastguard Worker hash_algorithm: Hash algorithm used as string. 1578*d289c2baSAndroid Build Coastguard Worker partition_name: Partition name as string. 1579*d289c2baSAndroid Build Coastguard Worker salt: Salt used as bytes. 1580*d289c2baSAndroid Build Coastguard Worker digest: The hash value of salt and data combined as bytes. 1581*d289c2baSAndroid Build Coastguard Worker flags: The descriptor flags (see avb_hash_descriptor.h). 1582*d289c2baSAndroid Build Coastguard Worker """ 1583*d289c2baSAndroid Build Coastguard Worker 1584*d289c2baSAndroid Build Coastguard Worker TAG = 2 1585*d289c2baSAndroid Build Coastguard Worker RESERVED = 60 1586*d289c2baSAndroid Build Coastguard Worker SIZE = 72 + RESERVED 1587*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!QQ' # tag, num_bytes_following (descriptor header) 1588*d289c2baSAndroid Build Coastguard Worker 'Q' # image size (bytes) 1589*d289c2baSAndroid Build Coastguard Worker '32s' # hash algorithm used 1590*d289c2baSAndroid Build Coastguard Worker 'L' # partition name (bytes) 1591*d289c2baSAndroid Build Coastguard Worker 'L' # salt length (bytes) 1592*d289c2baSAndroid Build Coastguard Worker 'L' # digest length (bytes) 1593*d289c2baSAndroid Build Coastguard Worker 'L' + # flags 1594*d289c2baSAndroid Build Coastguard Worker str(RESERVED) + 's') # reserved 1595*d289c2baSAndroid Build Coastguard Worker 1596*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 1597*d289c2baSAndroid Build Coastguard Worker """Initializes a new hash descriptor. 1598*d289c2baSAndroid Build Coastguard Worker 1599*d289c2baSAndroid Build Coastguard Worker Arguments: 1600*d289c2baSAndroid Build Coastguard Worker data: If not None, must be bytes of size |SIZE|. 1601*d289c2baSAndroid Build Coastguard Worker 1602*d289c2baSAndroid Build Coastguard Worker Raises: 1603*d289c2baSAndroid Build Coastguard Worker LookupError: If the given descriptor is malformed. 1604*d289c2baSAndroid Build Coastguard Worker """ 1605*d289c2baSAndroid Build Coastguard Worker super().__init__(None) 1606*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 1607*d289c2baSAndroid Build Coastguard Worker 1608*d289c2baSAndroid Build Coastguard Worker if data: 1609*d289c2baSAndroid Build Coastguard Worker (tag, num_bytes_following, self.image_size, self.hash_algorithm, 1610*d289c2baSAndroid Build Coastguard Worker partition_name_len, salt_len, 1611*d289c2baSAndroid Build Coastguard Worker digest_len, self.flags, _) = struct.unpack(self.FORMAT_STRING, 1612*d289c2baSAndroid Build Coastguard Worker data[0:self.SIZE]) 1613*d289c2baSAndroid Build Coastguard Worker expected_size = round_to_multiple( 1614*d289c2baSAndroid Build Coastguard Worker self.SIZE - 16 + partition_name_len + salt_len + digest_len, 8) 1615*d289c2baSAndroid Build Coastguard Worker if tag != self.TAG or num_bytes_following != expected_size: 1616*d289c2baSAndroid Build Coastguard Worker raise LookupError('Given data does not look like a hash descriptor.') 1617*d289c2baSAndroid Build Coastguard Worker # Nuke NUL-bytes at the end. 1618*d289c2baSAndroid Build Coastguard Worker self.hash_algorithm = self.hash_algorithm.rstrip(b'\0').decode('ascii') 1619*d289c2baSAndroid Build Coastguard Worker o = 0 1620*d289c2baSAndroid Build Coastguard Worker try: 1621*d289c2baSAndroid Build Coastguard Worker self.partition_name = data[ 1622*d289c2baSAndroid Build Coastguard Worker (self.SIZE + o):(self.SIZE + o + partition_name_len) 1623*d289c2baSAndroid Build Coastguard Worker ].decode('utf-8') 1624*d289c2baSAndroid Build Coastguard Worker except UnicodeDecodeError as e: 1625*d289c2baSAndroid Build Coastguard Worker raise LookupError('Partition name cannot be decoded as UTF-8: {}.' 1626*d289c2baSAndroid Build Coastguard Worker .format(e)) from e 1627*d289c2baSAndroid Build Coastguard Worker o += partition_name_len 1628*d289c2baSAndroid Build Coastguard Worker self.salt = data[(self.SIZE + o):(self.SIZE + o + salt_len)] 1629*d289c2baSAndroid Build Coastguard Worker o += salt_len 1630*d289c2baSAndroid Build Coastguard Worker self.digest = data[(self.SIZE + o):(self.SIZE + o + digest_len)] 1631*d289c2baSAndroid Build Coastguard Worker if digest_len != len(hashlib.new(self.hash_algorithm).digest()): 1632*d289c2baSAndroid Build Coastguard Worker if digest_len != 0: 1633*d289c2baSAndroid Build Coastguard Worker raise LookupError('digest_len doesn\'t match hash algorithm') 1634*d289c2baSAndroid Build Coastguard Worker 1635*d289c2baSAndroid Build Coastguard Worker else: 1636*d289c2baSAndroid Build Coastguard Worker self.image_size = 0 1637*d289c2baSAndroid Build Coastguard Worker self.hash_algorithm = '' 1638*d289c2baSAndroid Build Coastguard Worker self.partition_name = '' 1639*d289c2baSAndroid Build Coastguard Worker self.salt = b'' 1640*d289c2baSAndroid Build Coastguard Worker self.digest = b'' 1641*d289c2baSAndroid Build Coastguard Worker self.flags = 0 1642*d289c2baSAndroid Build Coastguard Worker 1643*d289c2baSAndroid Build Coastguard Worker def print_desc(self, o): 1644*d289c2baSAndroid Build Coastguard Worker """Print the descriptor. 1645*d289c2baSAndroid Build Coastguard Worker 1646*d289c2baSAndroid Build Coastguard Worker Arguments: 1647*d289c2baSAndroid Build Coastguard Worker o: The object to write the output to. 1648*d289c2baSAndroid Build Coastguard Worker """ 1649*d289c2baSAndroid Build Coastguard Worker o.write(' Hash descriptor:\n') 1650*d289c2baSAndroid Build Coastguard Worker o.write(' Image Size: {} bytes\n'.format(self.image_size)) 1651*d289c2baSAndroid Build Coastguard Worker o.write(' Hash Algorithm: {}\n'.format(self.hash_algorithm)) 1652*d289c2baSAndroid Build Coastguard Worker o.write(' Partition Name: {}\n'.format(self.partition_name)) 1653*d289c2baSAndroid Build Coastguard Worker o.write(' Salt: {}\n'.format(self.salt.hex())) 1654*d289c2baSAndroid Build Coastguard Worker o.write(' Digest: {}\n'.format(self.digest.hex())) 1655*d289c2baSAndroid Build Coastguard Worker o.write(' Flags: {}\n'.format(self.flags)) 1656*d289c2baSAndroid Build Coastguard Worker 1657*d289c2baSAndroid Build Coastguard Worker def encode(self): 1658*d289c2baSAndroid Build Coastguard Worker """Serializes the descriptor. 1659*d289c2baSAndroid Build Coastguard Worker 1660*d289c2baSAndroid Build Coastguard Worker Returns: 1661*d289c2baSAndroid Build Coastguard Worker The descriptor data as bytes. 1662*d289c2baSAndroid Build Coastguard Worker """ 1663*d289c2baSAndroid Build Coastguard Worker hash_algorithm_encoded = self.hash_algorithm.encode('ascii') 1664*d289c2baSAndroid Build Coastguard Worker partition_name_encoded = self.partition_name.encode('utf-8') 1665*d289c2baSAndroid Build Coastguard Worker num_bytes_following = (self.SIZE + len(partition_name_encoded) + 1666*d289c2baSAndroid Build Coastguard Worker len(self.salt) + len(self.digest) - 16) 1667*d289c2baSAndroid Build Coastguard Worker nbf_with_padding = round_to_multiple(num_bytes_following, 8) 1668*d289c2baSAndroid Build Coastguard Worker padding_size = nbf_with_padding - num_bytes_following 1669*d289c2baSAndroid Build Coastguard Worker desc = struct.pack(self.FORMAT_STRING, self.TAG, nbf_with_padding, 1670*d289c2baSAndroid Build Coastguard Worker self.image_size, hash_algorithm_encoded, 1671*d289c2baSAndroid Build Coastguard Worker len(partition_name_encoded), len(self.salt), 1672*d289c2baSAndroid Build Coastguard Worker len(self.digest), self.flags, self.RESERVED * b'\0') 1673*d289c2baSAndroid Build Coastguard Worker ret = (desc + partition_name_encoded + self.salt + self.digest + 1674*d289c2baSAndroid Build Coastguard Worker padding_size * b'\0') 1675*d289c2baSAndroid Build Coastguard Worker return ret 1676*d289c2baSAndroid Build Coastguard Worker 1677*d289c2baSAndroid Build Coastguard Worker def verify(self, image_dir, image_ext, expected_chain_partitions_map, 1678*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor, accept_zeroed_hashtree): 1679*d289c2baSAndroid Build Coastguard Worker """Verifies contents of the descriptor - used in verify_image sub-command. 1680*d289c2baSAndroid Build Coastguard Worker 1681*d289c2baSAndroid Build Coastguard Worker Arguments: 1682*d289c2baSAndroid Build Coastguard Worker image_dir: The directory of the file being verified. 1683*d289c2baSAndroid Build Coastguard Worker image_ext: The extension of the file being verified (e.g. '.img'). 1684*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map: A map from partition name to the 1685*d289c2baSAndroid Build Coastguard Worker tuple (rollback_index_location, key_blob). 1686*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor: The image the descriptor is in. 1687*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 1688*d289c2baSAndroid Build Coastguard Worker zeroed out. 1689*d289c2baSAndroid Build Coastguard Worker 1690*d289c2baSAndroid Build Coastguard Worker Returns: 1691*d289c2baSAndroid Build Coastguard Worker True if the descriptor verifies, False otherwise. 1692*d289c2baSAndroid Build Coastguard Worker """ 1693*d289c2baSAndroid Build Coastguard Worker if not self.partition_name: 1694*d289c2baSAndroid Build Coastguard Worker image_filename = image_containing_descriptor.filename 1695*d289c2baSAndroid Build Coastguard Worker image = image_containing_descriptor 1696*d289c2baSAndroid Build Coastguard Worker else: 1697*d289c2baSAndroid Build Coastguard Worker image_filename = os.path.join(image_dir, self.partition_name + image_ext) 1698*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 1699*d289c2baSAndroid Build Coastguard Worker data = image.read(self.image_size) 1700*d289c2baSAndroid Build Coastguard Worker ha = hashlib.new(self.hash_algorithm) 1701*d289c2baSAndroid Build Coastguard Worker ha.update(self.salt) 1702*d289c2baSAndroid Build Coastguard Worker ha.update(data) 1703*d289c2baSAndroid Build Coastguard Worker digest = ha.digest() 1704*d289c2baSAndroid Build Coastguard Worker # The digest must match unless there is no digest in the descriptor. 1705*d289c2baSAndroid Build Coastguard Worker if self.digest and digest != self.digest: 1706*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('{} digest of {} does not match digest in descriptor\n'. 1707*d289c2baSAndroid Build Coastguard Worker format(self.hash_algorithm, image_filename)) 1708*d289c2baSAndroid Build Coastguard Worker return False 1709*d289c2baSAndroid Build Coastguard Worker print('{}: Successfully verified {} hash of {} for image of {} bytes' 1710*d289c2baSAndroid Build Coastguard Worker .format(self.partition_name, self.hash_algorithm, image.filename, 1711*d289c2baSAndroid Build Coastguard Worker self.image_size)) 1712*d289c2baSAndroid Build Coastguard Worker return True 1713*d289c2baSAndroid Build Coastguard Worker 1714*d289c2baSAndroid Build Coastguard Worker 1715*d289c2baSAndroid Build Coastguard Workerclass AvbKernelCmdlineDescriptor(AvbDescriptor): 1716*d289c2baSAndroid Build Coastguard Worker """A class for kernel command-line descriptors. 1717*d289c2baSAndroid Build Coastguard Worker 1718*d289c2baSAndroid Build Coastguard Worker See the |AvbKernelCmdlineDescriptor| C struct for more information. 1719*d289c2baSAndroid Build Coastguard Worker 1720*d289c2baSAndroid Build Coastguard Worker Attributes: 1721*d289c2baSAndroid Build Coastguard Worker flags: Flags. 1722*d289c2baSAndroid Build Coastguard Worker kernel_cmdline: The kernel command-line as string. 1723*d289c2baSAndroid Build Coastguard Worker """ 1724*d289c2baSAndroid Build Coastguard Worker 1725*d289c2baSAndroid Build Coastguard Worker TAG = 3 1726*d289c2baSAndroid Build Coastguard Worker SIZE = 24 1727*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!QQ' # tag, num_bytes_following (descriptor header) 1728*d289c2baSAndroid Build Coastguard Worker 'L' # flags 1729*d289c2baSAndroid Build Coastguard Worker 'L') # cmdline length (bytes) 1730*d289c2baSAndroid Build Coastguard Worker 1731*d289c2baSAndroid Build Coastguard Worker FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED = (1 << 0) 1732*d289c2baSAndroid Build Coastguard Worker FLAGS_USE_ONLY_IF_HASHTREE_DISABLED = (1 << 1) 1733*d289c2baSAndroid Build Coastguard Worker 1734*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 1735*d289c2baSAndroid Build Coastguard Worker """Initializes a new kernel cmdline descriptor. 1736*d289c2baSAndroid Build Coastguard Worker 1737*d289c2baSAndroid Build Coastguard Worker Arguments: 1738*d289c2baSAndroid Build Coastguard Worker data: If not None, must be bytes of size |SIZE|. 1739*d289c2baSAndroid Build Coastguard Worker 1740*d289c2baSAndroid Build Coastguard Worker Raises: 1741*d289c2baSAndroid Build Coastguard Worker LookupError: If the given descriptor is malformed. 1742*d289c2baSAndroid Build Coastguard Worker """ 1743*d289c2baSAndroid Build Coastguard Worker super().__init__(None) 1744*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 1745*d289c2baSAndroid Build Coastguard Worker 1746*d289c2baSAndroid Build Coastguard Worker if data: 1747*d289c2baSAndroid Build Coastguard Worker (tag, num_bytes_following, self.flags, kernel_cmdline_length) = ( 1748*d289c2baSAndroid Build Coastguard Worker struct.unpack(self.FORMAT_STRING, data[0:self.SIZE])) 1749*d289c2baSAndroid Build Coastguard Worker expected_size = round_to_multiple(self.SIZE - 16 + kernel_cmdline_length, 1750*d289c2baSAndroid Build Coastguard Worker 8) 1751*d289c2baSAndroid Build Coastguard Worker if tag != self.TAG or num_bytes_following != expected_size: 1752*d289c2baSAndroid Build Coastguard Worker raise LookupError('Given data does not look like a kernel cmdline ' 1753*d289c2baSAndroid Build Coastguard Worker 'descriptor.') 1754*d289c2baSAndroid Build Coastguard Worker # Nuke NUL-bytes at the end. 1755*d289c2baSAndroid Build Coastguard Worker try: 1756*d289c2baSAndroid Build Coastguard Worker self.kernel_cmdline = data[ 1757*d289c2baSAndroid Build Coastguard Worker self.SIZE:(self.SIZE + kernel_cmdline_length)].decode('utf-8') 1758*d289c2baSAndroid Build Coastguard Worker except UnicodeDecodeError as e: 1759*d289c2baSAndroid Build Coastguard Worker raise LookupError('Kernel command-line cannot be decoded as UTF-8: {}.' 1760*d289c2baSAndroid Build Coastguard Worker .format(e)) from e 1761*d289c2baSAndroid Build Coastguard Worker else: 1762*d289c2baSAndroid Build Coastguard Worker self.flags = 0 1763*d289c2baSAndroid Build Coastguard Worker self.kernel_cmdline = '' 1764*d289c2baSAndroid Build Coastguard Worker 1765*d289c2baSAndroid Build Coastguard Worker def print_desc(self, o): 1766*d289c2baSAndroid Build Coastguard Worker """Print the descriptor. 1767*d289c2baSAndroid Build Coastguard Worker 1768*d289c2baSAndroid Build Coastguard Worker Arguments: 1769*d289c2baSAndroid Build Coastguard Worker o: The object to write the output to. 1770*d289c2baSAndroid Build Coastguard Worker """ 1771*d289c2baSAndroid Build Coastguard Worker o.write(' Kernel Cmdline descriptor:\n') 1772*d289c2baSAndroid Build Coastguard Worker o.write(' Flags: {}\n'.format(self.flags)) 1773*d289c2baSAndroid Build Coastguard Worker o.write(' Kernel Cmdline: \'{}\'\n'.format(self.kernel_cmdline)) 1774*d289c2baSAndroid Build Coastguard Worker 1775*d289c2baSAndroid Build Coastguard Worker def encode(self): 1776*d289c2baSAndroid Build Coastguard Worker """Serializes the descriptor. 1777*d289c2baSAndroid Build Coastguard Worker 1778*d289c2baSAndroid Build Coastguard Worker Returns: 1779*d289c2baSAndroid Build Coastguard Worker The descriptor data as bytes. 1780*d289c2baSAndroid Build Coastguard Worker """ 1781*d289c2baSAndroid Build Coastguard Worker kernel_cmd_encoded = self.kernel_cmdline.encode('utf-8') 1782*d289c2baSAndroid Build Coastguard Worker num_bytes_following = (self.SIZE + len(kernel_cmd_encoded) - 16) 1783*d289c2baSAndroid Build Coastguard Worker nbf_with_padding = round_to_multiple(num_bytes_following, 8) 1784*d289c2baSAndroid Build Coastguard Worker padding_size = nbf_with_padding - num_bytes_following 1785*d289c2baSAndroid Build Coastguard Worker desc = struct.pack(self.FORMAT_STRING, self.TAG, nbf_with_padding, 1786*d289c2baSAndroid Build Coastguard Worker self.flags, len(kernel_cmd_encoded)) 1787*d289c2baSAndroid Build Coastguard Worker ret = desc + kernel_cmd_encoded + padding_size * b'\0' 1788*d289c2baSAndroid Build Coastguard Worker return ret 1789*d289c2baSAndroid Build Coastguard Worker 1790*d289c2baSAndroid Build Coastguard Worker def verify(self, image_dir, image_ext, expected_chain_partitions_map, 1791*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor, accept_zeroed_hashtree): 1792*d289c2baSAndroid Build Coastguard Worker """Verifies contents of the descriptor - used in verify_image sub-command. 1793*d289c2baSAndroid Build Coastguard Worker 1794*d289c2baSAndroid Build Coastguard Worker Arguments: 1795*d289c2baSAndroid Build Coastguard Worker image_dir: The directory of the file being verified. 1796*d289c2baSAndroid Build Coastguard Worker image_ext: The extension of the file being verified (e.g. '.img'). 1797*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map: A map from partition name to the 1798*d289c2baSAndroid Build Coastguard Worker tuple (rollback_index_location, key_blob). 1799*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor: The image the descriptor is in. 1800*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 1801*d289c2baSAndroid Build Coastguard Worker zeroed out. 1802*d289c2baSAndroid Build Coastguard Worker 1803*d289c2baSAndroid Build Coastguard Worker Returns: 1804*d289c2baSAndroid Build Coastguard Worker True if the descriptor verifies, False otherwise. 1805*d289c2baSAndroid Build Coastguard Worker """ 1806*d289c2baSAndroid Build Coastguard Worker # Nothing to verify. 1807*d289c2baSAndroid Build Coastguard Worker return True 1808*d289c2baSAndroid Build Coastguard Worker 1809*d289c2baSAndroid Build Coastguard Worker 1810*d289c2baSAndroid Build Coastguard Workerclass AvbChainPartitionDescriptor(AvbDescriptor): 1811*d289c2baSAndroid Build Coastguard Worker """A class for chained partition descriptors. 1812*d289c2baSAndroid Build Coastguard Worker 1813*d289c2baSAndroid Build Coastguard Worker See the |AvbChainPartitionDescriptor| C struct for more information. 1814*d289c2baSAndroid Build Coastguard Worker 1815*d289c2baSAndroid Build Coastguard Worker Attributes: 1816*d289c2baSAndroid Build Coastguard Worker rollback_index_location: The rollback index location to use. 1817*d289c2baSAndroid Build Coastguard Worker partition_name: Partition name as string. 1818*d289c2baSAndroid Build Coastguard Worker public_key: The public key as bytes. 1819*d289c2baSAndroid Build Coastguard Worker flags: Descriptor flags (see avb_chain_partition_descriptor.h). 1820*d289c2baSAndroid Build Coastguard Worker """ 1821*d289c2baSAndroid Build Coastguard Worker 1822*d289c2baSAndroid Build Coastguard Worker TAG = 4 1823*d289c2baSAndroid Build Coastguard Worker RESERVED = 60 1824*d289c2baSAndroid Build Coastguard Worker SIZE = 32 + RESERVED 1825*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!QQ' # tag, num_bytes_following (descriptor header) 1826*d289c2baSAndroid Build Coastguard Worker 'L' # rollback_index_location 1827*d289c2baSAndroid Build Coastguard Worker 'L' # partition_name_size (bytes) 1828*d289c2baSAndroid Build Coastguard Worker 'L' + # public_key_size (bytes) 1829*d289c2baSAndroid Build Coastguard Worker 'L' + # flags 1830*d289c2baSAndroid Build Coastguard Worker str(RESERVED) + 's') # reserved 1831*d289c2baSAndroid Build Coastguard Worker 1832*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 1833*d289c2baSAndroid Build Coastguard Worker """Initializes a new chain partition descriptor. 1834*d289c2baSAndroid Build Coastguard Worker 1835*d289c2baSAndroid Build Coastguard Worker Arguments: 1836*d289c2baSAndroid Build Coastguard Worker data: If not None, must be a bytearray of size |SIZE|. 1837*d289c2baSAndroid Build Coastguard Worker 1838*d289c2baSAndroid Build Coastguard Worker Raises: 1839*d289c2baSAndroid Build Coastguard Worker LookupError: If the given descriptor is malformed. 1840*d289c2baSAndroid Build Coastguard Worker """ 1841*d289c2baSAndroid Build Coastguard Worker AvbDescriptor.__init__(self, None) 1842*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 1843*d289c2baSAndroid Build Coastguard Worker 1844*d289c2baSAndroid Build Coastguard Worker if data: 1845*d289c2baSAndroid Build Coastguard Worker (tag, num_bytes_following, self.rollback_index_location, 1846*d289c2baSAndroid Build Coastguard Worker partition_name_len, 1847*d289c2baSAndroid Build Coastguard Worker public_key_len, self.flags, _) = struct.unpack(self.FORMAT_STRING, 1848*d289c2baSAndroid Build Coastguard Worker data[0:self.SIZE]) 1849*d289c2baSAndroid Build Coastguard Worker expected_size = round_to_multiple( 1850*d289c2baSAndroid Build Coastguard Worker self.SIZE - 16 + partition_name_len + public_key_len, 8) 1851*d289c2baSAndroid Build Coastguard Worker if tag != self.TAG or num_bytes_following != expected_size: 1852*d289c2baSAndroid Build Coastguard Worker raise LookupError('Given data does not look like a chain partition ' 1853*d289c2baSAndroid Build Coastguard Worker 'descriptor.') 1854*d289c2baSAndroid Build Coastguard Worker o = 0 1855*d289c2baSAndroid Build Coastguard Worker try: 1856*d289c2baSAndroid Build Coastguard Worker self.partition_name = data[ 1857*d289c2baSAndroid Build Coastguard Worker (self.SIZE + o):(self.SIZE + o + partition_name_len) 1858*d289c2baSAndroid Build Coastguard Worker ].decode('utf-8') 1859*d289c2baSAndroid Build Coastguard Worker except UnicodeDecodeError as e: 1860*d289c2baSAndroid Build Coastguard Worker raise LookupError('Partition name cannot be decoded as UTF-8: {}.' 1861*d289c2baSAndroid Build Coastguard Worker .format(e)) from e 1862*d289c2baSAndroid Build Coastguard Worker o += partition_name_len 1863*d289c2baSAndroid Build Coastguard Worker self.public_key = data[(self.SIZE + o):(self.SIZE + o + public_key_len)] 1864*d289c2baSAndroid Build Coastguard Worker 1865*d289c2baSAndroid Build Coastguard Worker else: 1866*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location = 0 1867*d289c2baSAndroid Build Coastguard Worker self.partition_name = '' 1868*d289c2baSAndroid Build Coastguard Worker self.public_key = b'' 1869*d289c2baSAndroid Build Coastguard Worker self.flags = 0 1870*d289c2baSAndroid Build Coastguard Worker 1871*d289c2baSAndroid Build Coastguard Worker def print_desc(self, o): 1872*d289c2baSAndroid Build Coastguard Worker """Print the descriptor. 1873*d289c2baSAndroid Build Coastguard Worker 1874*d289c2baSAndroid Build Coastguard Worker Arguments: 1875*d289c2baSAndroid Build Coastguard Worker o: The object to write the output to. 1876*d289c2baSAndroid Build Coastguard Worker """ 1877*d289c2baSAndroid Build Coastguard Worker o.write(' Chain Partition descriptor:\n') 1878*d289c2baSAndroid Build Coastguard Worker o.write(' Partition Name: {}\n'.format(self.partition_name)) 1879*d289c2baSAndroid Build Coastguard Worker o.write(' Rollback Index Location: {}\n'.format( 1880*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location)) 1881*d289c2baSAndroid Build Coastguard Worker # Just show the SHA1 of the key, for size reasons. 1882*d289c2baSAndroid Build Coastguard Worker pubkey_digest = hashlib.sha1(self.public_key).hexdigest() 1883*d289c2baSAndroid Build Coastguard Worker o.write(' Public key (sha1): {}\n'.format(pubkey_digest)) 1884*d289c2baSAndroid Build Coastguard Worker o.write(' Flags: {}\n'.format(self.flags)) 1885*d289c2baSAndroid Build Coastguard Worker 1886*d289c2baSAndroid Build Coastguard Worker def encode(self): 1887*d289c2baSAndroid Build Coastguard Worker """Serializes the descriptor. 1888*d289c2baSAndroid Build Coastguard Worker 1889*d289c2baSAndroid Build Coastguard Worker Returns: 1890*d289c2baSAndroid Build Coastguard Worker The descriptor data as bytes. 1891*d289c2baSAndroid Build Coastguard Worker """ 1892*d289c2baSAndroid Build Coastguard Worker partition_name_encoded = self.partition_name.encode('utf-8') 1893*d289c2baSAndroid Build Coastguard Worker num_bytes_following = ( 1894*d289c2baSAndroid Build Coastguard Worker self.SIZE + len(partition_name_encoded) + len(self.public_key) - 16) 1895*d289c2baSAndroid Build Coastguard Worker nbf_with_padding = round_to_multiple(num_bytes_following, 8) 1896*d289c2baSAndroid Build Coastguard Worker padding_size = nbf_with_padding - num_bytes_following 1897*d289c2baSAndroid Build Coastguard Worker desc = struct.pack(self.FORMAT_STRING, self.TAG, nbf_with_padding, 1898*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location, 1899*d289c2baSAndroid Build Coastguard Worker len(partition_name_encoded), len(self.public_key), 1900*d289c2baSAndroid Build Coastguard Worker self.flags, self.RESERVED * b'\0') 1901*d289c2baSAndroid Build Coastguard Worker ret = desc + partition_name_encoded + self.public_key + padding_size * b'\0' 1902*d289c2baSAndroid Build Coastguard Worker return ret 1903*d289c2baSAndroid Build Coastguard Worker 1904*d289c2baSAndroid Build Coastguard Worker def verify(self, image_dir, image_ext, expected_chain_partitions_map, 1905*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor, accept_zeroed_hashtree): 1906*d289c2baSAndroid Build Coastguard Worker """Verifies contents of the descriptor - used in verify_image sub-command. 1907*d289c2baSAndroid Build Coastguard Worker 1908*d289c2baSAndroid Build Coastguard Worker Arguments: 1909*d289c2baSAndroid Build Coastguard Worker image_dir: The directory of the file being verified. 1910*d289c2baSAndroid Build Coastguard Worker image_ext: The extension of the file being verified (e.g. '.img'). 1911*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map: A map from partition name to the 1912*d289c2baSAndroid Build Coastguard Worker tuple (rollback_index_location, key_blob). 1913*d289c2baSAndroid Build Coastguard Worker image_containing_descriptor: The image the descriptor is in. 1914*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 1915*d289c2baSAndroid Build Coastguard Worker zeroed out. 1916*d289c2baSAndroid Build Coastguard Worker 1917*d289c2baSAndroid Build Coastguard Worker Returns: 1918*d289c2baSAndroid Build Coastguard Worker True if the descriptor verifies, False otherwise. 1919*d289c2baSAndroid Build Coastguard Worker """ 1920*d289c2baSAndroid Build Coastguard Worker value = expected_chain_partitions_map.get(self.partition_name) 1921*d289c2baSAndroid Build Coastguard Worker if not value: 1922*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('No expected chain partition for partition {}. Use ' 1923*d289c2baSAndroid Build Coastguard Worker '--expected_chain_partition to specify expected ' 1924*d289c2baSAndroid Build Coastguard Worker 'contents or --follow_chain_partitions.\n'. 1925*d289c2baSAndroid Build Coastguard Worker format(self.partition_name)) 1926*d289c2baSAndroid Build Coastguard Worker return False 1927*d289c2baSAndroid Build Coastguard Worker rollback_index_location, pk_blob = value 1928*d289c2baSAndroid Build Coastguard Worker 1929*d289c2baSAndroid Build Coastguard Worker if self.rollback_index_location != rollback_index_location: 1930*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('Expected rollback_index_location {} does not ' 1931*d289c2baSAndroid Build Coastguard Worker 'match {} in descriptor for partition {}\n'. 1932*d289c2baSAndroid Build Coastguard Worker format(rollback_index_location, 1933*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location, 1934*d289c2baSAndroid Build Coastguard Worker self.partition_name)) 1935*d289c2baSAndroid Build Coastguard Worker return False 1936*d289c2baSAndroid Build Coastguard Worker 1937*d289c2baSAndroid Build Coastguard Worker if self.public_key != pk_blob: 1938*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('Expected public key blob does not match public ' 1939*d289c2baSAndroid Build Coastguard Worker 'key blob in descriptor for partition {}\n'. 1940*d289c2baSAndroid Build Coastguard Worker format(self.partition_name)) 1941*d289c2baSAndroid Build Coastguard Worker return False 1942*d289c2baSAndroid Build Coastguard Worker 1943*d289c2baSAndroid Build Coastguard Worker print('{}: Successfully verified chain partition descriptor matches ' 1944*d289c2baSAndroid Build Coastguard Worker 'expected data'.format(self.partition_name)) 1945*d289c2baSAndroid Build Coastguard Worker 1946*d289c2baSAndroid Build Coastguard Worker return True 1947*d289c2baSAndroid Build Coastguard Worker 1948*d289c2baSAndroid Build Coastguard WorkerDESCRIPTOR_CLASSES = [ 1949*d289c2baSAndroid Build Coastguard Worker AvbPropertyDescriptor, AvbHashtreeDescriptor, AvbHashDescriptor, 1950*d289c2baSAndroid Build Coastguard Worker AvbKernelCmdlineDescriptor, AvbChainPartitionDescriptor 1951*d289c2baSAndroid Build Coastguard Worker] 1952*d289c2baSAndroid Build Coastguard Worker 1953*d289c2baSAndroid Build Coastguard Worker 1954*d289c2baSAndroid Build Coastguard Workerdef parse_descriptors(data): 1955*d289c2baSAndroid Build Coastguard Worker """Parses a blob of data into descriptors. 1956*d289c2baSAndroid Build Coastguard Worker 1957*d289c2baSAndroid Build Coastguard Worker Arguments: 1958*d289c2baSAndroid Build Coastguard Worker data: Encoded descriptors as bytes. 1959*d289c2baSAndroid Build Coastguard Worker 1960*d289c2baSAndroid Build Coastguard Worker Returns: 1961*d289c2baSAndroid Build Coastguard Worker A list of instances of objects derived from AvbDescriptor. For 1962*d289c2baSAndroid Build Coastguard Worker unknown descriptors, the class AvbDescriptor is used. 1963*d289c2baSAndroid Build Coastguard Worker """ 1964*d289c2baSAndroid Build Coastguard Worker o = 0 1965*d289c2baSAndroid Build Coastguard Worker ret = [] 1966*d289c2baSAndroid Build Coastguard Worker while o < len(data): 1967*d289c2baSAndroid Build Coastguard Worker tag, nb_following = struct.unpack('!2Q', data[o:o + 16]) 1968*d289c2baSAndroid Build Coastguard Worker if tag < len(DESCRIPTOR_CLASSES): 1969*d289c2baSAndroid Build Coastguard Worker clazz = DESCRIPTOR_CLASSES[tag] 1970*d289c2baSAndroid Build Coastguard Worker else: 1971*d289c2baSAndroid Build Coastguard Worker clazz = AvbDescriptor 1972*d289c2baSAndroid Build Coastguard Worker ret.append(clazz(data[o:o + 16 + nb_following])) 1973*d289c2baSAndroid Build Coastguard Worker o += 16 + nb_following 1974*d289c2baSAndroid Build Coastguard Worker return ret 1975*d289c2baSAndroid Build Coastguard Worker 1976*d289c2baSAndroid Build Coastguard Worker 1977*d289c2baSAndroid Build Coastguard Workerclass AvbFooter(object): 1978*d289c2baSAndroid Build Coastguard Worker """A class for parsing and writing footers. 1979*d289c2baSAndroid Build Coastguard Worker 1980*d289c2baSAndroid Build Coastguard Worker Footers are stored at the end of partitions and point to where the 1981*d289c2baSAndroid Build Coastguard Worker AvbVBMeta blob is located. They also contain the original size of 1982*d289c2baSAndroid Build Coastguard Worker the image before AVB information was added. 1983*d289c2baSAndroid Build Coastguard Worker 1984*d289c2baSAndroid Build Coastguard Worker Attributes: 1985*d289c2baSAndroid Build Coastguard Worker magic: Magic for identifying the footer, see |MAGIC|. 1986*d289c2baSAndroid Build Coastguard Worker version_major: The major version of avbtool that wrote the footer. 1987*d289c2baSAndroid Build Coastguard Worker version_minor: The minor version of avbtool that wrote the footer. 1988*d289c2baSAndroid Build Coastguard Worker original_image_size: Original image size. 1989*d289c2baSAndroid Build Coastguard Worker vbmeta_offset: Offset of where the AvbVBMeta blob is stored. 1990*d289c2baSAndroid Build Coastguard Worker vbmeta_size: Size of the AvbVBMeta blob. 1991*d289c2baSAndroid Build Coastguard Worker """ 1992*d289c2baSAndroid Build Coastguard Worker 1993*d289c2baSAndroid Build Coastguard Worker MAGIC = b'AVBf' 1994*d289c2baSAndroid Build Coastguard Worker SIZE = 64 1995*d289c2baSAndroid Build Coastguard Worker RESERVED = 28 1996*d289c2baSAndroid Build Coastguard Worker FOOTER_VERSION_MAJOR = AVB_FOOTER_VERSION_MAJOR 1997*d289c2baSAndroid Build Coastguard Worker FOOTER_VERSION_MINOR = AVB_FOOTER_VERSION_MINOR 1998*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!4s2L' # magic, 2 x version. 1999*d289c2baSAndroid Build Coastguard Worker 'Q' # Original image size. 2000*d289c2baSAndroid Build Coastguard Worker 'Q' # Offset of VBMeta blob. 2001*d289c2baSAndroid Build Coastguard Worker 'Q' + # Size of VBMeta blob. 2002*d289c2baSAndroid Build Coastguard Worker str(RESERVED) + 'x') # padding for reserved bytes 2003*d289c2baSAndroid Build Coastguard Worker 2004*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 2005*d289c2baSAndroid Build Coastguard Worker """Initializes a new footer object. 2006*d289c2baSAndroid Build Coastguard Worker 2007*d289c2baSAndroid Build Coastguard Worker Arguments: 2008*d289c2baSAndroid Build Coastguard Worker data: If not None, must be bytes of size 4096. 2009*d289c2baSAndroid Build Coastguard Worker 2010*d289c2baSAndroid Build Coastguard Worker Raises: 2011*d289c2baSAndroid Build Coastguard Worker LookupError: If the given footer is malformed. 2012*d289c2baSAndroid Build Coastguard Worker struct.error: If the given data has no footer. 2013*d289c2baSAndroid Build Coastguard Worker """ 2014*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 2015*d289c2baSAndroid Build Coastguard Worker 2016*d289c2baSAndroid Build Coastguard Worker if data: 2017*d289c2baSAndroid Build Coastguard Worker (self.magic, self.version_major, self.version_minor, 2018*d289c2baSAndroid Build Coastguard Worker self.original_image_size, self.vbmeta_offset, 2019*d289c2baSAndroid Build Coastguard Worker self.vbmeta_size) = struct.unpack(self.FORMAT_STRING, data) 2020*d289c2baSAndroid Build Coastguard Worker if self.magic != self.MAGIC: 2021*d289c2baSAndroid Build Coastguard Worker raise LookupError('Given data does not look like a AVB footer.') 2022*d289c2baSAndroid Build Coastguard Worker else: 2023*d289c2baSAndroid Build Coastguard Worker self.magic = self.MAGIC 2024*d289c2baSAndroid Build Coastguard Worker self.version_major = self.FOOTER_VERSION_MAJOR 2025*d289c2baSAndroid Build Coastguard Worker self.version_minor = self.FOOTER_VERSION_MINOR 2026*d289c2baSAndroid Build Coastguard Worker self.original_image_size = 0 2027*d289c2baSAndroid Build Coastguard Worker self.vbmeta_offset = 0 2028*d289c2baSAndroid Build Coastguard Worker self.vbmeta_size = 0 2029*d289c2baSAndroid Build Coastguard Worker 2030*d289c2baSAndroid Build Coastguard Worker def encode(self): 2031*d289c2baSAndroid Build Coastguard Worker """Serializes the footer. 2032*d289c2baSAndroid Build Coastguard Worker 2033*d289c2baSAndroid Build Coastguard Worker Returns: 2034*d289c2baSAndroid Build Coastguard Worker The footer as bytes. 2035*d289c2baSAndroid Build Coastguard Worker """ 2036*d289c2baSAndroid Build Coastguard Worker return struct.pack(self.FORMAT_STRING, self.magic, self.version_major, 2037*d289c2baSAndroid Build Coastguard Worker self.version_minor, self.original_image_size, 2038*d289c2baSAndroid Build Coastguard Worker self.vbmeta_offset, self.vbmeta_size) 2039*d289c2baSAndroid Build Coastguard Worker 2040*d289c2baSAndroid Build Coastguard Worker 2041*d289c2baSAndroid Build Coastguard Workerclass AvbVBMetaHeader(object): 2042*d289c2baSAndroid Build Coastguard Worker """A class for parsing and writing AVB vbmeta images. 2043*d289c2baSAndroid Build Coastguard Worker 2044*d289c2baSAndroid Build Coastguard Worker The attributes correspond to the |AvbVBMetaImageHeader| struct defined in 2045*d289c2baSAndroid Build Coastguard Worker avb_vbmeta_image.h. 2046*d289c2baSAndroid Build Coastguard Worker 2047*d289c2baSAndroid Build Coastguard Worker Attributes: 2048*d289c2baSAndroid Build Coastguard Worker magic: Four bytes equal to "AVB0" (AVB_MAGIC). 2049*d289c2baSAndroid Build Coastguard Worker required_libavb_version_major: The major version of libavb required for this 2050*d289c2baSAndroid Build Coastguard Worker header. 2051*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor: The minor version of libavb required for this 2052*d289c2baSAndroid Build Coastguard Worker header. 2053*d289c2baSAndroid Build Coastguard Worker authentication_data_block_size: The size of the signature block. 2054*d289c2baSAndroid Build Coastguard Worker auxiliary_data_block_size: The size of the auxiliary data block. 2055*d289c2baSAndroid Build Coastguard Worker algorithm_type: The verification algorithm used, see |AvbAlgorithmType| 2056*d289c2baSAndroid Build Coastguard Worker enum. 2057*d289c2baSAndroid Build Coastguard Worker hash_offset: Offset into the "Authentication data" block of hash data. 2058*d289c2baSAndroid Build Coastguard Worker hash_size: Length of the hash data. 2059*d289c2baSAndroid Build Coastguard Worker signature_offset: Offset into the "Authentication data" block of signature 2060*d289c2baSAndroid Build Coastguard Worker data. 2061*d289c2baSAndroid Build Coastguard Worker signature_size: Length of the signature data. 2062*d289c2baSAndroid Build Coastguard Worker public_key_offset: Offset into the "Auxiliary data" block of public key 2063*d289c2baSAndroid Build Coastguard Worker data. 2064*d289c2baSAndroid Build Coastguard Worker public_key_size: Length of the public key data. 2065*d289c2baSAndroid Build Coastguard Worker public_key_metadata_offset: Offset into the "Auxiliary data" block of public 2066*d289c2baSAndroid Build Coastguard Worker key metadata. 2067*d289c2baSAndroid Build Coastguard Worker public_key_metadata_size: Length of the public key metadata. Must be set to 2068*d289c2baSAndroid Build Coastguard Worker zero if there is no public key metadata. 2069*d289c2baSAndroid Build Coastguard Worker descriptors_offset: Offset into the "Auxiliary data" block of descriptor 2070*d289c2baSAndroid Build Coastguard Worker data. 2071*d289c2baSAndroid Build Coastguard Worker descriptors_size: Length of descriptor data. 2072*d289c2baSAndroid Build Coastguard Worker rollback_index: The rollback index which can be used to prevent rollback to 2073*d289c2baSAndroid Build Coastguard Worker older versions. 2074*d289c2baSAndroid Build Coastguard Worker flags: Flags from the AvbVBMetaImageFlags enumeration. This must be set to 2075*d289c2baSAndroid Build Coastguard Worker zero if the vbmeta image is not a top-level image. 2076*d289c2baSAndroid Build Coastguard Worker rollback_index_location: The location of the rollback index defined in this 2077*d289c2baSAndroid Build Coastguard Worker header. Only valid for the main vbmeta. For chained partitions, the 2078*d289c2baSAndroid Build Coastguard Worker rollback index location must be specified in the 2079*d289c2baSAndroid Build Coastguard Worker AvbChainPartitionDescriptor and this value must be set to 0. 2080*d289c2baSAndroid Build Coastguard Worker release_string: The release string from avbtool, e.g. "avbtool 1.0.0" or 2081*d289c2baSAndroid Build Coastguard Worker "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL 2082*d289c2baSAndroid Build Coastguard Worker terminated. Applications must not make assumptions about how this 2083*d289c2baSAndroid Build Coastguard Worker string is formatted. 2084*d289c2baSAndroid Build Coastguard Worker """ 2085*d289c2baSAndroid Build Coastguard Worker MAGIC = b'AVB0' 2086*d289c2baSAndroid Build Coastguard Worker SIZE = 256 2087*d289c2baSAndroid Build Coastguard Worker 2088*d289c2baSAndroid Build Coastguard Worker # Keep in sync with |reserved| field of |AvbVBMetaImageHeader|. 2089*d289c2baSAndroid Build Coastguard Worker RESERVED = 80 2090*d289c2baSAndroid Build Coastguard Worker 2091*d289c2baSAndroid Build Coastguard Worker # Keep in sync with |AvbVBMetaImageHeader|. 2092*d289c2baSAndroid Build Coastguard Worker FORMAT_STRING = ('!4s2L' # magic, 2 x version 2093*d289c2baSAndroid Build Coastguard Worker '2Q' # 2 x block size 2094*d289c2baSAndroid Build Coastguard Worker 'L' # algorithm type 2095*d289c2baSAndroid Build Coastguard Worker '2Q' # offset, size (hash) 2096*d289c2baSAndroid Build Coastguard Worker '2Q' # offset, size (signature) 2097*d289c2baSAndroid Build Coastguard Worker '2Q' # offset, size (public key) 2098*d289c2baSAndroid Build Coastguard Worker '2Q' # offset, size (public key metadata) 2099*d289c2baSAndroid Build Coastguard Worker '2Q' # offset, size (descriptors) 2100*d289c2baSAndroid Build Coastguard Worker 'Q' # rollback_index 2101*d289c2baSAndroid Build Coastguard Worker 'L' # flags 2102*d289c2baSAndroid Build Coastguard Worker 'L' # rollback_index_location 2103*d289c2baSAndroid Build Coastguard Worker '47sx' + # NUL-terminated release string 2104*d289c2baSAndroid Build Coastguard Worker str(RESERVED) + 'x') # padding for reserved bytes 2105*d289c2baSAndroid Build Coastguard Worker 2106*d289c2baSAndroid Build Coastguard Worker def __init__(self, data=None): 2107*d289c2baSAndroid Build Coastguard Worker """Initializes a new header object. 2108*d289c2baSAndroid Build Coastguard Worker 2109*d289c2baSAndroid Build Coastguard Worker Arguments: 2110*d289c2baSAndroid Build Coastguard Worker data: If not None, must be a bytearray of size 8192. 2111*d289c2baSAndroid Build Coastguard Worker 2112*d289c2baSAndroid Build Coastguard Worker Raises: 2113*d289c2baSAndroid Build Coastguard Worker Exception: If the given data is malformed. 2114*d289c2baSAndroid Build Coastguard Worker """ 2115*d289c2baSAndroid Build Coastguard Worker assert struct.calcsize(self.FORMAT_STRING) == self.SIZE 2116*d289c2baSAndroid Build Coastguard Worker 2117*d289c2baSAndroid Build Coastguard Worker if data: 2118*d289c2baSAndroid Build Coastguard Worker (self.magic, self.required_libavb_version_major, 2119*d289c2baSAndroid Build Coastguard Worker self.required_libavb_version_minor, 2120*d289c2baSAndroid Build Coastguard Worker self.authentication_data_block_size, self.auxiliary_data_block_size, 2121*d289c2baSAndroid Build Coastguard Worker self.algorithm_type, self.hash_offset, self.hash_size, 2122*d289c2baSAndroid Build Coastguard Worker self.signature_offset, self.signature_size, self.public_key_offset, 2123*d289c2baSAndroid Build Coastguard Worker self.public_key_size, self.public_key_metadata_offset, 2124*d289c2baSAndroid Build Coastguard Worker self.public_key_metadata_size, self.descriptors_offset, 2125*d289c2baSAndroid Build Coastguard Worker self.descriptors_size, 2126*d289c2baSAndroid Build Coastguard Worker self.rollback_index, 2127*d289c2baSAndroid Build Coastguard Worker self.flags, 2128*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location, 2129*d289c2baSAndroid Build Coastguard Worker release_string) = struct.unpack(self.FORMAT_STRING, data) 2130*d289c2baSAndroid Build Coastguard Worker # Nuke NUL-bytes at the end of the string. 2131*d289c2baSAndroid Build Coastguard Worker if self.magic != self.MAGIC: 2132*d289c2baSAndroid Build Coastguard Worker raise AvbError('Given image does not look like a vbmeta image.') 2133*d289c2baSAndroid Build Coastguard Worker self.release_string = release_string.rstrip(b'\0').decode('utf-8') 2134*d289c2baSAndroid Build Coastguard Worker else: 2135*d289c2baSAndroid Build Coastguard Worker self.magic = self.MAGIC 2136*d289c2baSAndroid Build Coastguard Worker # Start by just requiring version 1.0. Code that adds features 2137*d289c2baSAndroid Build Coastguard Worker # in a future version can use bump_required_libavb_version_minor() to 2138*d289c2baSAndroid Build Coastguard Worker # bump the minor. 2139*d289c2baSAndroid Build Coastguard Worker self.required_libavb_version_major = AVB_VERSION_MAJOR 2140*d289c2baSAndroid Build Coastguard Worker self.required_libavb_version_minor = 0 2141*d289c2baSAndroid Build Coastguard Worker self.authentication_data_block_size = 0 2142*d289c2baSAndroid Build Coastguard Worker self.auxiliary_data_block_size = 0 2143*d289c2baSAndroid Build Coastguard Worker self.algorithm_type = 0 2144*d289c2baSAndroid Build Coastguard Worker self.hash_offset = 0 2145*d289c2baSAndroid Build Coastguard Worker self.hash_size = 0 2146*d289c2baSAndroid Build Coastguard Worker self.signature_offset = 0 2147*d289c2baSAndroid Build Coastguard Worker self.signature_size = 0 2148*d289c2baSAndroid Build Coastguard Worker self.public_key_offset = 0 2149*d289c2baSAndroid Build Coastguard Worker self.public_key_size = 0 2150*d289c2baSAndroid Build Coastguard Worker self.public_key_metadata_offset = 0 2151*d289c2baSAndroid Build Coastguard Worker self.public_key_metadata_size = 0 2152*d289c2baSAndroid Build Coastguard Worker self.descriptors_offset = 0 2153*d289c2baSAndroid Build Coastguard Worker self.descriptors_size = 0 2154*d289c2baSAndroid Build Coastguard Worker self.rollback_index = 0 2155*d289c2baSAndroid Build Coastguard Worker self.flags = 0 2156*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location = 0 2157*d289c2baSAndroid Build Coastguard Worker self.release_string = get_release_string() 2158*d289c2baSAndroid Build Coastguard Worker 2159*d289c2baSAndroid Build Coastguard Worker def bump_required_libavb_version_minor(self, minor): 2160*d289c2baSAndroid Build Coastguard Worker """Function to bump required_libavb_version_minor. 2161*d289c2baSAndroid Build Coastguard Worker 2162*d289c2baSAndroid Build Coastguard Worker Call this when writing data that requires a specific libavb 2163*d289c2baSAndroid Build Coastguard Worker version to parse it. 2164*d289c2baSAndroid Build Coastguard Worker 2165*d289c2baSAndroid Build Coastguard Worker Arguments: 2166*d289c2baSAndroid Build Coastguard Worker minor: The minor version of libavb that has support for the feature. 2167*d289c2baSAndroid Build Coastguard Worker """ 2168*d289c2baSAndroid Build Coastguard Worker self.required_libavb_version_minor = ( 2169*d289c2baSAndroid Build Coastguard Worker max(self.required_libavb_version_minor, minor)) 2170*d289c2baSAndroid Build Coastguard Worker 2171*d289c2baSAndroid Build Coastguard Worker def encode(self): 2172*d289c2baSAndroid Build Coastguard Worker """Serializes the header. 2173*d289c2baSAndroid Build Coastguard Worker 2174*d289c2baSAndroid Build Coastguard Worker Returns: 2175*d289c2baSAndroid Build Coastguard Worker The header as bytes. 2176*d289c2baSAndroid Build Coastguard Worker """ 2177*d289c2baSAndroid Build Coastguard Worker release_string_encoded = self.release_string.encode('utf-8') 2178*d289c2baSAndroid Build Coastguard Worker return struct.pack(self.FORMAT_STRING, self.magic, 2179*d289c2baSAndroid Build Coastguard Worker self.required_libavb_version_major, 2180*d289c2baSAndroid Build Coastguard Worker self.required_libavb_version_minor, 2181*d289c2baSAndroid Build Coastguard Worker self.authentication_data_block_size, 2182*d289c2baSAndroid Build Coastguard Worker self.auxiliary_data_block_size, self.algorithm_type, 2183*d289c2baSAndroid Build Coastguard Worker self.hash_offset, self.hash_size, self.signature_offset, 2184*d289c2baSAndroid Build Coastguard Worker self.signature_size, self.public_key_offset, 2185*d289c2baSAndroid Build Coastguard Worker self.public_key_size, self.public_key_metadata_offset, 2186*d289c2baSAndroid Build Coastguard Worker self.public_key_metadata_size, self.descriptors_offset, 2187*d289c2baSAndroid Build Coastguard Worker self.descriptors_size, self.rollback_index, self.flags, 2188*d289c2baSAndroid Build Coastguard Worker self.rollback_index_location, release_string_encoded) 2189*d289c2baSAndroid Build Coastguard Worker 2190*d289c2baSAndroid Build Coastguard Worker 2191*d289c2baSAndroid Build Coastguard Workerclass Avb(object): 2192*d289c2baSAndroid Build Coastguard Worker """Business logic for avbtool command-line tool.""" 2193*d289c2baSAndroid Build Coastguard Worker 2194*d289c2baSAndroid Build Coastguard Worker # Keep in sync with avb_ab_flow.h. 2195*d289c2baSAndroid Build Coastguard Worker AB_FORMAT_NO_CRC = '!4sBB2xBBBxBBBx12x' 2196*d289c2baSAndroid Build Coastguard Worker AB_MAGIC = b'\0AB0' 2197*d289c2baSAndroid Build Coastguard Worker AB_MAJOR_VERSION = 1 2198*d289c2baSAndroid Build Coastguard Worker AB_MINOR_VERSION = 0 2199*d289c2baSAndroid Build Coastguard Worker AB_MISC_METADATA_OFFSET = 2048 2200*d289c2baSAndroid Build Coastguard Worker 2201*d289c2baSAndroid Build Coastguard Worker # Constants for maximum metadata size. These are used to give 2202*d289c2baSAndroid Build Coastguard Worker # meaningful errors if the value passed in via --partition_size is 2203*d289c2baSAndroid Build Coastguard Worker # too small and when --calc_max_image_size is used. We use 2204*d289c2baSAndroid Build Coastguard Worker # conservative figures. 2205*d289c2baSAndroid Build Coastguard Worker MAX_VBMETA_SIZE = 64 * 1024 2206*d289c2baSAndroid Build Coastguard Worker MAX_FOOTER_SIZE = 4096 2207*d289c2baSAndroid Build Coastguard Worker 2208*d289c2baSAndroid Build Coastguard Worker def generate_test_image(self, output, image_size, start_byte): 2209*d289c2baSAndroid Build Coastguard Worker """Generates a test image for testing avbtool with known content. 2210*d289c2baSAndroid Build Coastguard Worker 2211*d289c2baSAndroid Build Coastguard Worker The content has following pattern: 0x00 0x01 0x02 .. 0xff 0x00 0x01 ..). 2212*d289c2baSAndroid Build Coastguard Worker 2213*d289c2baSAndroid Build Coastguard Worker Arguments: 2214*d289c2baSAndroid Build Coastguard Worker output: Write test image to this file. 2215*d289c2baSAndroid Build Coastguard Worker image_size: The size of the requested file in bytes. 2216*d289c2baSAndroid Build Coastguard Worker start_byte: The integer value of the start byte to use for pattern 2217*d289c2baSAndroid Build Coastguard Worker generation. 2218*d289c2baSAndroid Build Coastguard Worker """ 2219*d289c2baSAndroid Build Coastguard Worker pattern = bytearray([x & 0xFF for x in range(start_byte, start_byte + 256)]) 2220*d289c2baSAndroid Build Coastguard Worker buf = bytearray() 2221*d289c2baSAndroid Build Coastguard Worker c = int(math.ceil(image_size / 256.0)) 2222*d289c2baSAndroid Build Coastguard Worker for _ in range(0, c): 2223*d289c2baSAndroid Build Coastguard Worker buf.extend(pattern) 2224*d289c2baSAndroid Build Coastguard Worker output.write(buf[0:image_size]) 2225*d289c2baSAndroid Build Coastguard Worker 2226*d289c2baSAndroid Build Coastguard Worker def extract_vbmeta_image(self, output, image_filename, padding_size): 2227*d289c2baSAndroid Build Coastguard Worker """Implements the 'extract_vbmeta_image' command. 2228*d289c2baSAndroid Build Coastguard Worker 2229*d289c2baSAndroid Build Coastguard Worker Arguments: 2230*d289c2baSAndroid Build Coastguard Worker output: Write vbmeta struct to this file. 2231*d289c2baSAndroid Build Coastguard Worker image_filename: File to extract vbmeta data from (with a footer). 2232*d289c2baSAndroid Build Coastguard Worker padding_size: If not 0, pads output so size is a multiple of the number. 2233*d289c2baSAndroid Build Coastguard Worker 2234*d289c2baSAndroid Build Coastguard Worker Raises: 2235*d289c2baSAndroid Build Coastguard Worker AvbError: If there's no footer in the image. 2236*d289c2baSAndroid Build Coastguard Worker """ 2237*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 2238*d289c2baSAndroid Build Coastguard Worker (footer, _, _, _) = self._parse_image(image) 2239*d289c2baSAndroid Build Coastguard Worker if not footer: 2240*d289c2baSAndroid Build Coastguard Worker raise AvbError('Given image does not have a footer.') 2241*d289c2baSAndroid Build Coastguard Worker 2242*d289c2baSAndroid Build Coastguard Worker image.seek(footer.vbmeta_offset) 2243*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = image.read(footer.vbmeta_size) 2244*d289c2baSAndroid Build Coastguard Worker output.write(vbmeta_blob) 2245*d289c2baSAndroid Build Coastguard Worker 2246*d289c2baSAndroid Build Coastguard Worker if padding_size > 0: 2247*d289c2baSAndroid Build Coastguard Worker padded_size = round_to_multiple(len(vbmeta_blob), padding_size) 2248*d289c2baSAndroid Build Coastguard Worker padding_needed = padded_size - len(vbmeta_blob) 2249*d289c2baSAndroid Build Coastguard Worker output.write(b'\0' * padding_needed) 2250*d289c2baSAndroid Build Coastguard Worker 2251*d289c2baSAndroid Build Coastguard Worker def erase_footer(self, image_filename, keep_hashtree): 2252*d289c2baSAndroid Build Coastguard Worker """Implements the 'erase_footer' command. 2253*d289c2baSAndroid Build Coastguard Worker 2254*d289c2baSAndroid Build Coastguard Worker Arguments: 2255*d289c2baSAndroid Build Coastguard Worker image_filename: File to erase a footer from. 2256*d289c2baSAndroid Build Coastguard Worker keep_hashtree: If True, keep the hashtree and FEC around. 2257*d289c2baSAndroid Build Coastguard Worker 2258*d289c2baSAndroid Build Coastguard Worker Raises: 2259*d289c2baSAndroid Build Coastguard Worker AvbError: If there's no footer in the image. 2260*d289c2baSAndroid Build Coastguard Worker """ 2261*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename) 2262*d289c2baSAndroid Build Coastguard Worker (footer, _, descriptors, _) = self._parse_image(image) 2263*d289c2baSAndroid Build Coastguard Worker if not footer: 2264*d289c2baSAndroid Build Coastguard Worker raise AvbError('Given image does not have a footer.') 2265*d289c2baSAndroid Build Coastguard Worker 2266*d289c2baSAndroid Build Coastguard Worker new_image_size = None 2267*d289c2baSAndroid Build Coastguard Worker if not keep_hashtree: 2268*d289c2baSAndroid Build Coastguard Worker new_image_size = footer.original_image_size 2269*d289c2baSAndroid Build Coastguard Worker else: 2270*d289c2baSAndroid Build Coastguard Worker # If requested to keep the hashtree, search for a hashtree 2271*d289c2baSAndroid Build Coastguard Worker # descriptor to figure out the location and size of the hashtree 2272*d289c2baSAndroid Build Coastguard Worker # and FEC. 2273*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2274*d289c2baSAndroid Build Coastguard Worker if isinstance(desc, AvbHashtreeDescriptor): 2275*d289c2baSAndroid Build Coastguard Worker # The hashtree is always just following the main data so the 2276*d289c2baSAndroid Build Coastguard Worker # new size is easily derived. 2277*d289c2baSAndroid Build Coastguard Worker new_image_size = desc.tree_offset + desc.tree_size 2278*d289c2baSAndroid Build Coastguard Worker # If the image has FEC codes, also keep those. 2279*d289c2baSAndroid Build Coastguard Worker if desc.fec_offset > 0: 2280*d289c2baSAndroid Build Coastguard Worker fec_end = desc.fec_offset + desc.fec_size 2281*d289c2baSAndroid Build Coastguard Worker new_image_size = max(new_image_size, fec_end) 2282*d289c2baSAndroid Build Coastguard Worker break 2283*d289c2baSAndroid Build Coastguard Worker if not new_image_size: 2284*d289c2baSAndroid Build Coastguard Worker raise AvbError('Requested to keep hashtree but no hashtree ' 2285*d289c2baSAndroid Build Coastguard Worker 'descriptor was found.') 2286*d289c2baSAndroid Build Coastguard Worker 2287*d289c2baSAndroid Build Coastguard Worker # And cut... 2288*d289c2baSAndroid Build Coastguard Worker image.truncate(new_image_size) 2289*d289c2baSAndroid Build Coastguard Worker 2290*d289c2baSAndroid Build Coastguard Worker def zero_hashtree(self, image_filename): 2291*d289c2baSAndroid Build Coastguard Worker """Implements the 'zero_hashtree' command. 2292*d289c2baSAndroid Build Coastguard Worker 2293*d289c2baSAndroid Build Coastguard Worker Arguments: 2294*d289c2baSAndroid Build Coastguard Worker image_filename: File to zero hashtree and FEC data from. 2295*d289c2baSAndroid Build Coastguard Worker 2296*d289c2baSAndroid Build Coastguard Worker Raises: 2297*d289c2baSAndroid Build Coastguard Worker AvbError: If there's no footer in the image. 2298*d289c2baSAndroid Build Coastguard Worker """ 2299*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename) 2300*d289c2baSAndroid Build Coastguard Worker (footer, _, descriptors, _) = self._parse_image(image) 2301*d289c2baSAndroid Build Coastguard Worker if not footer: 2302*d289c2baSAndroid Build Coastguard Worker raise AvbError('Given image does not have a footer.') 2303*d289c2baSAndroid Build Coastguard Worker 2304*d289c2baSAndroid Build Coastguard Worker # Search for a hashtree descriptor to figure out the location and 2305*d289c2baSAndroid Build Coastguard Worker # size of the hashtree and FEC. 2306*d289c2baSAndroid Build Coastguard Worker ht_desc = None 2307*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2308*d289c2baSAndroid Build Coastguard Worker if isinstance(desc, AvbHashtreeDescriptor): 2309*d289c2baSAndroid Build Coastguard Worker ht_desc = desc 2310*d289c2baSAndroid Build Coastguard Worker break 2311*d289c2baSAndroid Build Coastguard Worker 2312*d289c2baSAndroid Build Coastguard Worker if not ht_desc: 2313*d289c2baSAndroid Build Coastguard Worker raise AvbError('No hashtree descriptor was found.') 2314*d289c2baSAndroid Build Coastguard Worker 2315*d289c2baSAndroid Build Coastguard Worker zero_ht_start_offset = ht_desc.tree_offset 2316*d289c2baSAndroid Build Coastguard Worker zero_ht_num_bytes = ht_desc.tree_size 2317*d289c2baSAndroid Build Coastguard Worker zero_fec_start_offset = None 2318*d289c2baSAndroid Build Coastguard Worker zero_fec_num_bytes = 0 2319*d289c2baSAndroid Build Coastguard Worker if ht_desc.fec_offset > 0: 2320*d289c2baSAndroid Build Coastguard Worker if ht_desc.fec_offset != ht_desc.tree_offset + ht_desc.tree_size: 2321*d289c2baSAndroid Build Coastguard Worker raise AvbError('Hash-tree and FEC data must be adjacent.') 2322*d289c2baSAndroid Build Coastguard Worker zero_fec_start_offset = ht_desc.fec_offset 2323*d289c2baSAndroid Build Coastguard Worker zero_fec_num_bytes = ht_desc.fec_size 2324*d289c2baSAndroid Build Coastguard Worker zero_end_offset = (zero_ht_start_offset + zero_ht_num_bytes 2325*d289c2baSAndroid Build Coastguard Worker + zero_fec_num_bytes) 2326*d289c2baSAndroid Build Coastguard Worker image.seek(zero_end_offset) 2327*d289c2baSAndroid Build Coastguard Worker data = image.read(image.image_size - zero_end_offset) 2328*d289c2baSAndroid Build Coastguard Worker 2329*d289c2baSAndroid Build Coastguard Worker # Write zeroes all over hashtree and FEC, except for the first eight bytes 2330*d289c2baSAndroid Build Coastguard Worker # where a magic marker - ZeroHaSH - is placed. Place these markers in the 2331*d289c2baSAndroid Build Coastguard Worker # beginning of both hashtree and FEC. (That way, in the future we can add 2332*d289c2baSAndroid Build Coastguard Worker # options to 'avbtool zero_hashtree' so as to zero out only either/or.) 2333*d289c2baSAndroid Build Coastguard Worker # 2334*d289c2baSAndroid Build Coastguard Worker # Applications can use these markers to detect that the hashtree and/or 2335*d289c2baSAndroid Build Coastguard Worker # FEC needs to be recomputed. 2336*d289c2baSAndroid Build Coastguard Worker image.truncate(zero_ht_start_offset) 2337*d289c2baSAndroid Build Coastguard Worker data_zeroed_firstblock = b'ZeRoHaSH' + b'\0' * (image.block_size - 8) 2338*d289c2baSAndroid Build Coastguard Worker image.append_raw(data_zeroed_firstblock) 2339*d289c2baSAndroid Build Coastguard Worker image.append_fill(b'\0\0\0\0', zero_ht_num_bytes - image.block_size) 2340*d289c2baSAndroid Build Coastguard Worker if zero_fec_start_offset: 2341*d289c2baSAndroid Build Coastguard Worker image.append_raw(data_zeroed_firstblock) 2342*d289c2baSAndroid Build Coastguard Worker image.append_fill(b'\0\0\0\0', zero_fec_num_bytes - image.block_size) 2343*d289c2baSAndroid Build Coastguard Worker image.append_raw(data) 2344*d289c2baSAndroid Build Coastguard Worker 2345*d289c2baSAndroid Build Coastguard Worker def resize_image(self, image_filename, partition_size): 2346*d289c2baSAndroid Build Coastguard Worker """Implements the 'resize_image' command. 2347*d289c2baSAndroid Build Coastguard Worker 2348*d289c2baSAndroid Build Coastguard Worker Arguments: 2349*d289c2baSAndroid Build Coastguard Worker image_filename: File with footer to resize. 2350*d289c2baSAndroid Build Coastguard Worker partition_size: The new size of the image. 2351*d289c2baSAndroid Build Coastguard Worker 2352*d289c2baSAndroid Build Coastguard Worker Raises: 2353*d289c2baSAndroid Build Coastguard Worker AvbError: If there's no footer in the image. 2354*d289c2baSAndroid Build Coastguard Worker """ 2355*d289c2baSAndroid Build Coastguard Worker 2356*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename) 2357*d289c2baSAndroid Build Coastguard Worker if partition_size % image.block_size != 0: 2358*d289c2baSAndroid Build Coastguard Worker raise AvbError('Partition size of {} is not a multiple of the image ' 2359*d289c2baSAndroid Build Coastguard Worker 'block size {}.'.format(partition_size, 2360*d289c2baSAndroid Build Coastguard Worker image.block_size)) 2361*d289c2baSAndroid Build Coastguard Worker (footer, _, _, _) = self._parse_image(image) 2362*d289c2baSAndroid Build Coastguard Worker if not footer: 2363*d289c2baSAndroid Build Coastguard Worker raise AvbError('Given image does not have a footer.') 2364*d289c2baSAndroid Build Coastguard Worker 2365*d289c2baSAndroid Build Coastguard Worker # The vbmeta blob is always at the end of the data so resizing an 2366*d289c2baSAndroid Build Coastguard Worker # image amounts to just moving the footer around. 2367*d289c2baSAndroid Build Coastguard Worker vbmeta_end_offset = footer.vbmeta_offset + footer.vbmeta_size 2368*d289c2baSAndroid Build Coastguard Worker if vbmeta_end_offset % image.block_size != 0: 2369*d289c2baSAndroid Build Coastguard Worker vbmeta_end_offset += image.block_size - (vbmeta_end_offset 2370*d289c2baSAndroid Build Coastguard Worker % image.block_size) 2371*d289c2baSAndroid Build Coastguard Worker 2372*d289c2baSAndroid Build Coastguard Worker if partition_size < vbmeta_end_offset + 1 * image.block_size: 2373*d289c2baSAndroid Build Coastguard Worker raise AvbError('Requested size of {} is too small for an image ' 2374*d289c2baSAndroid Build Coastguard Worker 'of size {}.' 2375*d289c2baSAndroid Build Coastguard Worker .format(partition_size, 2376*d289c2baSAndroid Build Coastguard Worker vbmeta_end_offset + 1 * image.block_size)) 2377*d289c2baSAndroid Build Coastguard Worker 2378*d289c2baSAndroid Build Coastguard Worker # Cut at the end of the vbmeta blob and insert a DONT_CARE chunk 2379*d289c2baSAndroid Build Coastguard Worker # with enough bytes such that the final Footer block is at the end 2380*d289c2baSAndroid Build Coastguard Worker # of partition_size. 2381*d289c2baSAndroid Build Coastguard Worker image.truncate(vbmeta_end_offset) 2382*d289c2baSAndroid Build Coastguard Worker image.append_dont_care(partition_size - vbmeta_end_offset - 2383*d289c2baSAndroid Build Coastguard Worker 1 * image.block_size) 2384*d289c2baSAndroid Build Coastguard Worker 2385*d289c2baSAndroid Build Coastguard Worker # Just reuse the same footer - only difference is that we're 2386*d289c2baSAndroid Build Coastguard Worker # writing it in a different place. 2387*d289c2baSAndroid Build Coastguard Worker footer_blob = footer.encode() 2388*d289c2baSAndroid Build Coastguard Worker footer_blob_with_padding = (b'\0' * (image.block_size - AvbFooter.SIZE) + 2389*d289c2baSAndroid Build Coastguard Worker footer_blob) 2390*d289c2baSAndroid Build Coastguard Worker image.append_raw(footer_blob_with_padding) 2391*d289c2baSAndroid Build Coastguard Worker 2392*d289c2baSAndroid Build Coastguard Worker def set_ab_metadata(self, misc_image, slot_data): 2393*d289c2baSAndroid Build Coastguard Worker """Implements the 'set_ab_metadata' command. 2394*d289c2baSAndroid Build Coastguard Worker 2395*d289c2baSAndroid Build Coastguard Worker The |slot_data| argument must be of the form 'A_priority:A_tries_remaining: 2396*d289c2baSAndroid Build Coastguard Worker A_successful_boot:B_priority:B_tries_remaining:B_successful_boot'. 2397*d289c2baSAndroid Build Coastguard Worker 2398*d289c2baSAndroid Build Coastguard Worker Arguments: 2399*d289c2baSAndroid Build Coastguard Worker misc_image: The misc image to write to. 2400*d289c2baSAndroid Build Coastguard Worker slot_data: Slot data as a string 2401*d289c2baSAndroid Build Coastguard Worker 2402*d289c2baSAndroid Build Coastguard Worker Raises: 2403*d289c2baSAndroid Build Coastguard Worker AvbError: If slot data is malformed. 2404*d289c2baSAndroid Build Coastguard Worker """ 2405*d289c2baSAndroid Build Coastguard Worker tokens = slot_data.split(':') 2406*d289c2baSAndroid Build Coastguard Worker if len(tokens) != 6: 2407*d289c2baSAndroid Build Coastguard Worker raise AvbError('Malformed slot data "{}".'.format(slot_data)) 2408*d289c2baSAndroid Build Coastguard Worker a_priority = int(tokens[0]) 2409*d289c2baSAndroid Build Coastguard Worker a_tries_remaining = int(tokens[1]) 2410*d289c2baSAndroid Build Coastguard Worker a_success = int(tokens[2]) != 0 2411*d289c2baSAndroid Build Coastguard Worker b_priority = int(tokens[3]) 2412*d289c2baSAndroid Build Coastguard Worker b_tries_remaining = int(tokens[4]) 2413*d289c2baSAndroid Build Coastguard Worker b_success = int(tokens[5]) != 0 2414*d289c2baSAndroid Build Coastguard Worker 2415*d289c2baSAndroid Build Coastguard Worker ab_data_no_crc = struct.pack(self.AB_FORMAT_NO_CRC, 2416*d289c2baSAndroid Build Coastguard Worker self.AB_MAGIC, 2417*d289c2baSAndroid Build Coastguard Worker self.AB_MAJOR_VERSION, self.AB_MINOR_VERSION, 2418*d289c2baSAndroid Build Coastguard Worker a_priority, a_tries_remaining, a_success, 2419*d289c2baSAndroid Build Coastguard Worker b_priority, b_tries_remaining, b_success) 2420*d289c2baSAndroid Build Coastguard Worker # Force CRC to be unsigned, see https://bugs.python.org/issue4903 for why. 2421*d289c2baSAndroid Build Coastguard Worker crc_value = binascii.crc32(ab_data_no_crc) & 0xffffffff 2422*d289c2baSAndroid Build Coastguard Worker ab_data = ab_data_no_crc + struct.pack('!I', crc_value) 2423*d289c2baSAndroid Build Coastguard Worker misc_image.seek(self.AB_MISC_METADATA_OFFSET) 2424*d289c2baSAndroid Build Coastguard Worker misc_image.write(ab_data) 2425*d289c2baSAndroid Build Coastguard Worker 2426*d289c2baSAndroid Build Coastguard Worker def info_image(self, image_filename, output, cert): 2427*d289c2baSAndroid Build Coastguard Worker """Implements the 'info_image' command. 2428*d289c2baSAndroid Build Coastguard Worker 2429*d289c2baSAndroid Build Coastguard Worker Arguments: 2430*d289c2baSAndroid Build Coastguard Worker image_filename: Image file to get information from (file object). 2431*d289c2baSAndroid Build Coastguard Worker output: Output file to write human-readable information to (file object). 2432*d289c2baSAndroid Build Coastguard Worker cert: If True, show information about the avb_cert certificates. 2433*d289c2baSAndroid Build Coastguard Worker """ 2434*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 2435*d289c2baSAndroid Build Coastguard Worker o = output 2436*d289c2baSAndroid Build Coastguard Worker (footer, header, descriptors, image_size) = self._parse_image(image) 2437*d289c2baSAndroid Build Coastguard Worker 2438*d289c2baSAndroid Build Coastguard Worker # To show the SHA1 of the public key. 2439*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = self._load_vbmeta_blob(image) 2440*d289c2baSAndroid Build Coastguard Worker key_offset = (header.SIZE + 2441*d289c2baSAndroid Build Coastguard Worker header.authentication_data_block_size + 2442*d289c2baSAndroid Build Coastguard Worker header.public_key_offset) 2443*d289c2baSAndroid Build Coastguard Worker key_blob = vbmeta_blob[key_offset:key_offset + header.public_key_size] 2444*d289c2baSAndroid Build Coastguard Worker 2445*d289c2baSAndroid Build Coastguard Worker if footer: 2446*d289c2baSAndroid Build Coastguard Worker o.write('Footer version: {}.{}\n'.format(footer.version_major, 2447*d289c2baSAndroid Build Coastguard Worker footer.version_minor)) 2448*d289c2baSAndroid Build Coastguard Worker o.write('Image size: {} bytes\n'.format(image_size)) 2449*d289c2baSAndroid Build Coastguard Worker o.write('Original image size: {} bytes\n'.format( 2450*d289c2baSAndroid Build Coastguard Worker footer.original_image_size)) 2451*d289c2baSAndroid Build Coastguard Worker o.write('VBMeta offset: {}\n'.format(footer.vbmeta_offset)) 2452*d289c2baSAndroid Build Coastguard Worker o.write('VBMeta size: {} bytes\n'.format(footer.vbmeta_size)) 2453*d289c2baSAndroid Build Coastguard Worker o.write('--\n') 2454*d289c2baSAndroid Build Coastguard Worker 2455*d289c2baSAndroid Build Coastguard Worker (alg_name, _) = lookup_algorithm_by_type(header.algorithm_type) 2456*d289c2baSAndroid Build Coastguard Worker 2457*d289c2baSAndroid Build Coastguard Worker o.write('Minimum libavb version: {}.{}{}\n'.format( 2458*d289c2baSAndroid Build Coastguard Worker header.required_libavb_version_major, 2459*d289c2baSAndroid Build Coastguard Worker header.required_libavb_version_minor, 2460*d289c2baSAndroid Build Coastguard Worker ' (Sparse)' if image.is_sparse else '')) 2461*d289c2baSAndroid Build Coastguard Worker o.write('Header Block: {} bytes\n'.format(AvbVBMetaHeader.SIZE)) 2462*d289c2baSAndroid Build Coastguard Worker o.write('Authentication Block: {} bytes\n'.format( 2463*d289c2baSAndroid Build Coastguard Worker header.authentication_data_block_size)) 2464*d289c2baSAndroid Build Coastguard Worker o.write('Auxiliary Block: {} bytes\n'.format( 2465*d289c2baSAndroid Build Coastguard Worker header.auxiliary_data_block_size)) 2466*d289c2baSAndroid Build Coastguard Worker if key_blob: 2467*d289c2baSAndroid Build Coastguard Worker hexdig = hashlib.sha1(key_blob).hexdigest() 2468*d289c2baSAndroid Build Coastguard Worker o.write('Public key (sha1): {}\n'.format(hexdig)) 2469*d289c2baSAndroid Build Coastguard Worker o.write('Algorithm: {}\n'.format(alg_name)) 2470*d289c2baSAndroid Build Coastguard Worker o.write('Rollback Index: {}\n'.format(header.rollback_index)) 2471*d289c2baSAndroid Build Coastguard Worker o.write('Flags: {}\n'.format(header.flags)) 2472*d289c2baSAndroid Build Coastguard Worker o.write('Rollback Index Location: {}\n'.format( 2473*d289c2baSAndroid Build Coastguard Worker header.rollback_index_location)) 2474*d289c2baSAndroid Build Coastguard Worker o.write('Release String: \'{}\'\n'.format(header.release_string)) 2475*d289c2baSAndroid Build Coastguard Worker 2476*d289c2baSAndroid Build Coastguard Worker # Print descriptors. 2477*d289c2baSAndroid Build Coastguard Worker num_printed = 0 2478*d289c2baSAndroid Build Coastguard Worker o.write('Descriptors:\n') 2479*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2480*d289c2baSAndroid Build Coastguard Worker desc.print_desc(o) 2481*d289c2baSAndroid Build Coastguard Worker num_printed += 1 2482*d289c2baSAndroid Build Coastguard Worker if num_printed == 0: 2483*d289c2baSAndroid Build Coastguard Worker o.write(' (none)\n') 2484*d289c2baSAndroid Build Coastguard Worker 2485*d289c2baSAndroid Build Coastguard Worker if cert and header.public_key_metadata_size: 2486*d289c2baSAndroid Build Coastguard Worker o.write('avb_cert certificate:\n') 2487*d289c2baSAndroid Build Coastguard Worker key_metadata_offset = (header.SIZE + 2488*d289c2baSAndroid Build Coastguard Worker header.authentication_data_block_size + 2489*d289c2baSAndroid Build Coastguard Worker header.public_key_metadata_offset) 2490*d289c2baSAndroid Build Coastguard Worker key_metadata_blob = vbmeta_blob[key_metadata_offset: key_metadata_offset 2491*d289c2baSAndroid Build Coastguard Worker + header.public_key_metadata_size] 2492*d289c2baSAndroid Build Coastguard Worker version, pik, psk = struct.unpack('<I1620s1620s', key_metadata_blob) 2493*d289c2baSAndroid Build Coastguard Worker o.write(' Metadata version: {}\n'.format(version)) 2494*d289c2baSAndroid Build Coastguard Worker 2495*d289c2baSAndroid Build Coastguard Worker def print_certificate(cert): 2496*d289c2baSAndroid Build Coastguard Worker version, public_key, subject, usage, key_version, _ = ( 2497*d289c2baSAndroid Build Coastguard Worker struct.unpack('<I1032s32s32sQ512s', cert)) 2498*d289c2baSAndroid Build Coastguard Worker o.write(' Version: {}\n'.format(version)) 2499*d289c2baSAndroid Build Coastguard Worker o.write(' Public key (sha1): {}\n'.format( 2500*d289c2baSAndroid Build Coastguard Worker hashlib.sha1(public_key).hexdigest())) 2501*d289c2baSAndroid Build Coastguard Worker o.write(' Subject: {}\n'.format(subject.hex())) 2502*d289c2baSAndroid Build Coastguard Worker o.write(' Usage: {}\n'.format(usage.hex())) 2503*d289c2baSAndroid Build Coastguard Worker o.write(' Key version: {}\n'.format(key_version)) 2504*d289c2baSAndroid Build Coastguard Worker 2505*d289c2baSAndroid Build Coastguard Worker o.write(' Product Intermediate Key:\n') 2506*d289c2baSAndroid Build Coastguard Worker print_certificate(pik) 2507*d289c2baSAndroid Build Coastguard Worker o.write(' Product Signing Key:\n') 2508*d289c2baSAndroid Build Coastguard Worker print_certificate(psk) 2509*d289c2baSAndroid Build Coastguard Worker 2510*d289c2baSAndroid Build Coastguard Worker def verify_image(self, image_filename, key_path, expected_chain_partitions, 2511*d289c2baSAndroid Build Coastguard Worker follow_chain_partitions, accept_zeroed_hashtree): 2512*d289c2baSAndroid Build Coastguard Worker """Implements the 'verify_image' command. 2513*d289c2baSAndroid Build Coastguard Worker 2514*d289c2baSAndroid Build Coastguard Worker Arguments: 2515*d289c2baSAndroid Build Coastguard Worker image_filename: Image file to get information from (file object). 2516*d289c2baSAndroid Build Coastguard Worker key_path: None or check that embedded public key matches key at given 2517*d289c2baSAndroid Build Coastguard Worker path. 2518*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions: List of chain partitions to check or None. 2519*d289c2baSAndroid Build Coastguard Worker follow_chain_partitions: 2520*d289c2baSAndroid Build Coastguard Worker If True, will follows chain partitions even when not specified with 2521*d289c2baSAndroid Build Coastguard Worker the --expected_chain_partition option 2522*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree: If True, don't fail if hashtree or FEC data is 2523*d289c2baSAndroid Build Coastguard Worker zeroed out. 2524*d289c2baSAndroid Build Coastguard Worker 2525*d289c2baSAndroid Build Coastguard Worker Raises: 2526*d289c2baSAndroid Build Coastguard Worker AvbError: If verification of the image fails. 2527*d289c2baSAndroid Build Coastguard Worker """ 2528*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map = {} 2529*d289c2baSAndroid Build Coastguard Worker if expected_chain_partitions: 2530*d289c2baSAndroid Build Coastguard Worker for cp in expected_chain_partitions: 2531*d289c2baSAndroid Build Coastguard Worker cp_tokens = cp.split(':') 2532*d289c2baSAndroid Build Coastguard Worker if len(cp_tokens) != 3: 2533*d289c2baSAndroid Build Coastguard Worker raise AvbError('Malformed chained partition "{}".'.format(cp)) 2534*d289c2baSAndroid Build Coastguard Worker partition_name = cp_tokens[0] 2535*d289c2baSAndroid Build Coastguard Worker rollback_index_location = int(cp_tokens[1]) 2536*d289c2baSAndroid Build Coastguard Worker file_path = cp_tokens[2] 2537*d289c2baSAndroid Build Coastguard Worker with open(file_path, 'rb') as f: 2538*d289c2baSAndroid Build Coastguard Worker pk_blob = f.read() 2539*d289c2baSAndroid Build Coastguard Worker expected_chain_partitions_map[partition_name] = ( 2540*d289c2baSAndroid Build Coastguard Worker rollback_index_location, pk_blob) 2541*d289c2baSAndroid Build Coastguard Worker 2542*d289c2baSAndroid Build Coastguard Worker image_dir = os.path.dirname(image_filename) 2543*d289c2baSAndroid Build Coastguard Worker image_ext = os.path.splitext(image_filename)[1] 2544*d289c2baSAndroid Build Coastguard Worker 2545*d289c2baSAndroid Build Coastguard Worker key_blob = None 2546*d289c2baSAndroid Build Coastguard Worker if key_path: 2547*d289c2baSAndroid Build Coastguard Worker print('Verifying image {} using key at {}'.format(image_filename, 2548*d289c2baSAndroid Build Coastguard Worker key_path)) 2549*d289c2baSAndroid Build Coastguard Worker key_blob = RSAPublicKey(key_path).encode() 2550*d289c2baSAndroid Build Coastguard Worker else: 2551*d289c2baSAndroid Build Coastguard Worker print('Verifying image {} using embedded public key'.format( 2552*d289c2baSAndroid Build Coastguard Worker image_filename)) 2553*d289c2baSAndroid Build Coastguard Worker 2554*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 2555*d289c2baSAndroid Build Coastguard Worker (footer, header, descriptors, _) = self._parse_image(image) 2556*d289c2baSAndroid Build Coastguard Worker offset = 0 2557*d289c2baSAndroid Build Coastguard Worker if footer: 2558*d289c2baSAndroid Build Coastguard Worker offset = footer.vbmeta_offset 2559*d289c2baSAndroid Build Coastguard Worker 2560*d289c2baSAndroid Build Coastguard Worker image.seek(offset) 2561*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = image.read(header.SIZE 2562*d289c2baSAndroid Build Coastguard Worker + header.authentication_data_block_size 2563*d289c2baSAndroid Build Coastguard Worker + header.auxiliary_data_block_size) 2564*d289c2baSAndroid Build Coastguard Worker 2565*d289c2baSAndroid Build Coastguard Worker alg_name, _ = lookup_algorithm_by_type(header.algorithm_type) 2566*d289c2baSAndroid Build Coastguard Worker if not verify_vbmeta_signature(header, vbmeta_blob): 2567*d289c2baSAndroid Build Coastguard Worker raise AvbError('Signature check failed for {} vbmeta struct {}' 2568*d289c2baSAndroid Build Coastguard Worker .format(alg_name, image_filename)) 2569*d289c2baSAndroid Build Coastguard Worker 2570*d289c2baSAndroid Build Coastguard Worker if key_blob: 2571*d289c2baSAndroid Build Coastguard Worker # The embedded public key is in the auxiliary block at an offset. 2572*d289c2baSAndroid Build Coastguard Worker key_offset = AvbVBMetaHeader.SIZE 2573*d289c2baSAndroid Build Coastguard Worker key_offset += header.authentication_data_block_size 2574*d289c2baSAndroid Build Coastguard Worker key_offset += header.public_key_offset 2575*d289c2baSAndroid Build Coastguard Worker key_blob_in_vbmeta = vbmeta_blob[key_offset:key_offset 2576*d289c2baSAndroid Build Coastguard Worker + header.public_key_size] 2577*d289c2baSAndroid Build Coastguard Worker if key_blob != key_blob_in_vbmeta: 2578*d289c2baSAndroid Build Coastguard Worker raise AvbError('Embedded public key does not match given key.') 2579*d289c2baSAndroid Build Coastguard Worker 2580*d289c2baSAndroid Build Coastguard Worker if footer: 2581*d289c2baSAndroid Build Coastguard Worker print('vbmeta: Successfully verified footer and {} vbmeta struct in {}' 2582*d289c2baSAndroid Build Coastguard Worker .format(alg_name, image.filename)) 2583*d289c2baSAndroid Build Coastguard Worker else: 2584*d289c2baSAndroid Build Coastguard Worker print('vbmeta: Successfully verified {} vbmeta struct in {}' 2585*d289c2baSAndroid Build Coastguard Worker .format(alg_name, image.filename)) 2586*d289c2baSAndroid Build Coastguard Worker 2587*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2588*d289c2baSAndroid Build Coastguard Worker if (isinstance(desc, AvbChainPartitionDescriptor) 2589*d289c2baSAndroid Build Coastguard Worker and follow_chain_partitions 2590*d289c2baSAndroid Build Coastguard Worker and expected_chain_partitions_map.get(desc.partition_name) is None): 2591*d289c2baSAndroid Build Coastguard Worker # In this case we're processing a chain descriptor but don't have a 2592*d289c2baSAndroid Build Coastguard Worker # --expect_chain_partition ... however --follow_chain_partitions was 2593*d289c2baSAndroid Build Coastguard Worker # specified so we shouldn't error out in desc.verify(). 2594*d289c2baSAndroid Build Coastguard Worker print('{}: Chained but ROLLBACK_SLOT (which is {}) ' 2595*d289c2baSAndroid Build Coastguard Worker 'and KEY (which has sha1 {}) not specified' 2596*d289c2baSAndroid Build Coastguard Worker .format(desc.partition_name, desc.rollback_index_location, 2597*d289c2baSAndroid Build Coastguard Worker hashlib.sha1(desc.public_key).hexdigest())) 2598*d289c2baSAndroid Build Coastguard Worker elif not desc.verify(image_dir, image_ext, expected_chain_partitions_map, 2599*d289c2baSAndroid Build Coastguard Worker image, accept_zeroed_hashtree): 2600*d289c2baSAndroid Build Coastguard Worker raise AvbError('Error verifying descriptor.') 2601*d289c2baSAndroid Build Coastguard Worker # Honor --follow_chain_partitions - add '--' to make the output more 2602*d289c2baSAndroid Build Coastguard Worker # readable. 2603*d289c2baSAndroid Build Coastguard Worker if (isinstance(desc, AvbChainPartitionDescriptor) 2604*d289c2baSAndroid Build Coastguard Worker and follow_chain_partitions): 2605*d289c2baSAndroid Build Coastguard Worker print('--') 2606*d289c2baSAndroid Build Coastguard Worker chained_image_filename = os.path.join(image_dir, 2607*d289c2baSAndroid Build Coastguard Worker desc.partition_name + image_ext) 2608*d289c2baSAndroid Build Coastguard Worker self.verify_image(chained_image_filename, key_path, None, False, 2609*d289c2baSAndroid Build Coastguard Worker accept_zeroed_hashtree) 2610*d289c2baSAndroid Build Coastguard Worker 2611*d289c2baSAndroid Build Coastguard Worker def print_partition_digests(self, image_filename, output, as_json): 2612*d289c2baSAndroid Build Coastguard Worker """Implements the 'print_partition_digests' command. 2613*d289c2baSAndroid Build Coastguard Worker 2614*d289c2baSAndroid Build Coastguard Worker Arguments: 2615*d289c2baSAndroid Build Coastguard Worker image_filename: Image file to get information from (file object). 2616*d289c2baSAndroid Build Coastguard Worker output: Output file to write human-readable information to (file object). 2617*d289c2baSAndroid Build Coastguard Worker as_json: If True, print information as JSON 2618*d289c2baSAndroid Build Coastguard Worker 2619*d289c2baSAndroid Build Coastguard Worker Raises: 2620*d289c2baSAndroid Build Coastguard Worker AvbError: If getting the partition digests from the image fails. 2621*d289c2baSAndroid Build Coastguard Worker """ 2622*d289c2baSAndroid Build Coastguard Worker image_dir = os.path.dirname(image_filename) 2623*d289c2baSAndroid Build Coastguard Worker image_ext = os.path.splitext(image_filename)[1] 2624*d289c2baSAndroid Build Coastguard Worker json_partitions = None 2625*d289c2baSAndroid Build Coastguard Worker if as_json: 2626*d289c2baSAndroid Build Coastguard Worker json_partitions = [] 2627*d289c2baSAndroid Build Coastguard Worker self._print_partition_digests( 2628*d289c2baSAndroid Build Coastguard Worker image_filename, output, json_partitions, image_dir, image_ext) 2629*d289c2baSAndroid Build Coastguard Worker if as_json: 2630*d289c2baSAndroid Build Coastguard Worker output.write(json.dumps({'partitions': json_partitions}, indent=2)) 2631*d289c2baSAndroid Build Coastguard Worker 2632*d289c2baSAndroid Build Coastguard Worker def _print_partition_digests(self, image_filename, output, json_partitions, 2633*d289c2baSAndroid Build Coastguard Worker image_dir, image_ext): 2634*d289c2baSAndroid Build Coastguard Worker """Helper for printing partitions. 2635*d289c2baSAndroid Build Coastguard Worker 2636*d289c2baSAndroid Build Coastguard Worker Arguments: 2637*d289c2baSAndroid Build Coastguard Worker image_filename: Image file to get information from (file object). 2638*d289c2baSAndroid Build Coastguard Worker output: Output file to write human-readable information to (file object). 2639*d289c2baSAndroid Build Coastguard Worker json_partitions: If not None, don't print to output, instead add partition 2640*d289c2baSAndroid Build Coastguard Worker information to this list. 2641*d289c2baSAndroid Build Coastguard Worker image_dir: The directory to use when looking for chained partition files. 2642*d289c2baSAndroid Build Coastguard Worker image_ext: The extension to use for chained partition files. 2643*d289c2baSAndroid Build Coastguard Worker 2644*d289c2baSAndroid Build Coastguard Worker Raises: 2645*d289c2baSAndroid Build Coastguard Worker AvbError: If getting the partition digests from the image fails. 2646*d289c2baSAndroid Build Coastguard Worker """ 2647*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 2648*d289c2baSAndroid Build Coastguard Worker (_, _, descriptors, _) = self._parse_image(image) 2649*d289c2baSAndroid Build Coastguard Worker 2650*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2651*d289c2baSAndroid Build Coastguard Worker if isinstance(desc, AvbHashDescriptor): 2652*d289c2baSAndroid Build Coastguard Worker digest = desc.digest.hex() 2653*d289c2baSAndroid Build Coastguard Worker if json_partitions is not None: 2654*d289c2baSAndroid Build Coastguard Worker json_partitions.append({'name': desc.partition_name, 2655*d289c2baSAndroid Build Coastguard Worker 'digest': digest}) 2656*d289c2baSAndroid Build Coastguard Worker else: 2657*d289c2baSAndroid Build Coastguard Worker output.write('{}: {}\n'.format(desc.partition_name, digest)) 2658*d289c2baSAndroid Build Coastguard Worker elif isinstance(desc, AvbHashtreeDescriptor): 2659*d289c2baSAndroid Build Coastguard Worker digest = desc.root_digest.hex() 2660*d289c2baSAndroid Build Coastguard Worker if json_partitions is not None: 2661*d289c2baSAndroid Build Coastguard Worker json_partitions.append({'name': desc.partition_name, 2662*d289c2baSAndroid Build Coastguard Worker 'digest': digest}) 2663*d289c2baSAndroid Build Coastguard Worker else: 2664*d289c2baSAndroid Build Coastguard Worker output.write('{}: {}\n'.format(desc.partition_name, digest)) 2665*d289c2baSAndroid Build Coastguard Worker elif isinstance(desc, AvbChainPartitionDescriptor): 2666*d289c2baSAndroid Build Coastguard Worker chained_image_filename = os.path.join(image_dir, 2667*d289c2baSAndroid Build Coastguard Worker desc.partition_name + image_ext) 2668*d289c2baSAndroid Build Coastguard Worker self._print_partition_digests( 2669*d289c2baSAndroid Build Coastguard Worker chained_image_filename, output, json_partitions, image_dir, 2670*d289c2baSAndroid Build Coastguard Worker image_ext) 2671*d289c2baSAndroid Build Coastguard Worker 2672*d289c2baSAndroid Build Coastguard Worker def calculate_vbmeta_digest(self, image_filename, hash_algorithm, output): 2673*d289c2baSAndroid Build Coastguard Worker """Implements the 'calculate_vbmeta_digest' command. 2674*d289c2baSAndroid Build Coastguard Worker 2675*d289c2baSAndroid Build Coastguard Worker Arguments: 2676*d289c2baSAndroid Build Coastguard Worker image_filename: Image file to get information from (file object). 2677*d289c2baSAndroid Build Coastguard Worker hash_algorithm: Hash algorithm used. 2678*d289c2baSAndroid Build Coastguard Worker output: Output file to write human-readable information to (file object). 2679*d289c2baSAndroid Build Coastguard Worker """ 2680*d289c2baSAndroid Build Coastguard Worker 2681*d289c2baSAndroid Build Coastguard Worker image_dir = os.path.dirname(image_filename) 2682*d289c2baSAndroid Build Coastguard Worker image_ext = os.path.splitext(image_filename)[1] 2683*d289c2baSAndroid Build Coastguard Worker 2684*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 2685*d289c2baSAndroid Build Coastguard Worker (footer, header, descriptors, _) = self._parse_image(image) 2686*d289c2baSAndroid Build Coastguard Worker offset = 0 2687*d289c2baSAndroid Build Coastguard Worker if footer: 2688*d289c2baSAndroid Build Coastguard Worker offset = footer.vbmeta_offset 2689*d289c2baSAndroid Build Coastguard Worker size = (header.SIZE + header.authentication_data_block_size + 2690*d289c2baSAndroid Build Coastguard Worker header.auxiliary_data_block_size) 2691*d289c2baSAndroid Build Coastguard Worker image.seek(offset) 2692*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = image.read(size) 2693*d289c2baSAndroid Build Coastguard Worker 2694*d289c2baSAndroid Build Coastguard Worker hasher = hashlib.new(hash_algorithm) 2695*d289c2baSAndroid Build Coastguard Worker hasher.update(vbmeta_blob) 2696*d289c2baSAndroid Build Coastguard Worker 2697*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2698*d289c2baSAndroid Build Coastguard Worker if isinstance(desc, AvbChainPartitionDescriptor): 2699*d289c2baSAndroid Build Coastguard Worker ch_image_filename = os.path.join(image_dir, 2700*d289c2baSAndroid Build Coastguard Worker desc.partition_name + image_ext) 2701*d289c2baSAndroid Build Coastguard Worker ch_image = ImageHandler(ch_image_filename, read_only=True) 2702*d289c2baSAndroid Build Coastguard Worker (ch_footer, ch_header, _, _) = self._parse_image(ch_image) 2703*d289c2baSAndroid Build Coastguard Worker ch_offset = 0 2704*d289c2baSAndroid Build Coastguard Worker ch_size = (ch_header.SIZE + ch_header.authentication_data_block_size + 2705*d289c2baSAndroid Build Coastguard Worker ch_header.auxiliary_data_block_size) 2706*d289c2baSAndroid Build Coastguard Worker if ch_footer: 2707*d289c2baSAndroid Build Coastguard Worker ch_offset = ch_footer.vbmeta_offset 2708*d289c2baSAndroid Build Coastguard Worker ch_image.seek(ch_offset) 2709*d289c2baSAndroid Build Coastguard Worker ch_vbmeta_blob = ch_image.read(ch_size) 2710*d289c2baSAndroid Build Coastguard Worker hasher.update(ch_vbmeta_blob) 2711*d289c2baSAndroid Build Coastguard Worker 2712*d289c2baSAndroid Build Coastguard Worker digest = hasher.digest() 2713*d289c2baSAndroid Build Coastguard Worker output.write('{}\n'.format(digest.hex())) 2714*d289c2baSAndroid Build Coastguard Worker 2715*d289c2baSAndroid Build Coastguard Worker def calculate_kernel_cmdline(self, image_filename, hashtree_disabled, output): 2716*d289c2baSAndroid Build Coastguard Worker """Implements the 'calculate_kernel_cmdline' command. 2717*d289c2baSAndroid Build Coastguard Worker 2718*d289c2baSAndroid Build Coastguard Worker Arguments: 2719*d289c2baSAndroid Build Coastguard Worker image_filename: Image file to get information from (file object). 2720*d289c2baSAndroid Build Coastguard Worker hashtree_disabled: If True, returns the cmdline for hashtree disabled. 2721*d289c2baSAndroid Build Coastguard Worker output: Output file to write human-readable information to (file object). 2722*d289c2baSAndroid Build Coastguard Worker """ 2723*d289c2baSAndroid Build Coastguard Worker 2724*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, read_only=True) 2725*d289c2baSAndroid Build Coastguard Worker _, _, descriptors, _ = self._parse_image(image) 2726*d289c2baSAndroid Build Coastguard Worker 2727*d289c2baSAndroid Build Coastguard Worker image_dir = os.path.dirname(image_filename) 2728*d289c2baSAndroid Build Coastguard Worker image_ext = os.path.splitext(image_filename)[1] 2729*d289c2baSAndroid Build Coastguard Worker 2730*d289c2baSAndroid Build Coastguard Worker cmdline_descriptors = [] 2731*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2732*d289c2baSAndroid Build Coastguard Worker if isinstance(desc, AvbChainPartitionDescriptor): 2733*d289c2baSAndroid Build Coastguard Worker ch_image_filename = os.path.join(image_dir, 2734*d289c2baSAndroid Build Coastguard Worker desc.partition_name + image_ext) 2735*d289c2baSAndroid Build Coastguard Worker ch_image = ImageHandler(ch_image_filename, read_only=True) 2736*d289c2baSAndroid Build Coastguard Worker _, _, ch_descriptors, _ = self._parse_image(ch_image) 2737*d289c2baSAndroid Build Coastguard Worker for ch_desc in ch_descriptors: 2738*d289c2baSAndroid Build Coastguard Worker if isinstance(ch_desc, AvbKernelCmdlineDescriptor): 2739*d289c2baSAndroid Build Coastguard Worker cmdline_descriptors.append(ch_desc) 2740*d289c2baSAndroid Build Coastguard Worker elif isinstance(desc, AvbKernelCmdlineDescriptor): 2741*d289c2baSAndroid Build Coastguard Worker cmdline_descriptors.append(desc) 2742*d289c2baSAndroid Build Coastguard Worker 2743*d289c2baSAndroid Build Coastguard Worker kernel_cmdline_snippets = [] 2744*d289c2baSAndroid Build Coastguard Worker for desc in cmdline_descriptors: 2745*d289c2baSAndroid Build Coastguard Worker use_cmdline = True 2746*d289c2baSAndroid Build Coastguard Worker if ((desc.flags & 2747*d289c2baSAndroid Build Coastguard Worker AvbKernelCmdlineDescriptor.FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) 2748*d289c2baSAndroid Build Coastguard Worker != 0): 2749*d289c2baSAndroid Build Coastguard Worker if hashtree_disabled: 2750*d289c2baSAndroid Build Coastguard Worker use_cmdline = False 2751*d289c2baSAndroid Build Coastguard Worker if (desc.flags & 2752*d289c2baSAndroid Build Coastguard Worker AvbKernelCmdlineDescriptor.FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) != 0: 2753*d289c2baSAndroid Build Coastguard Worker if not hashtree_disabled: 2754*d289c2baSAndroid Build Coastguard Worker use_cmdline = False 2755*d289c2baSAndroid Build Coastguard Worker if use_cmdline: 2756*d289c2baSAndroid Build Coastguard Worker kernel_cmdline_snippets.append(desc.kernel_cmdline) 2757*d289c2baSAndroid Build Coastguard Worker output.write(' '.join(kernel_cmdline_snippets)) 2758*d289c2baSAndroid Build Coastguard Worker 2759*d289c2baSAndroid Build Coastguard Worker def _parse_image(self, image): 2760*d289c2baSAndroid Build Coastguard Worker """Gets information about an image. 2761*d289c2baSAndroid Build Coastguard Worker 2762*d289c2baSAndroid Build Coastguard Worker The image can either be a vbmeta or an image with a footer. 2763*d289c2baSAndroid Build Coastguard Worker 2764*d289c2baSAndroid Build Coastguard Worker Arguments: 2765*d289c2baSAndroid Build Coastguard Worker image: An ImageHandler (vbmeta or footer) with a hashtree descriptor. 2766*d289c2baSAndroid Build Coastguard Worker 2767*d289c2baSAndroid Build Coastguard Worker Returns: 2768*d289c2baSAndroid Build Coastguard Worker A tuple where the first argument is a AvbFooter (None if there 2769*d289c2baSAndroid Build Coastguard Worker is no footer on the image), the second argument is a 2770*d289c2baSAndroid Build Coastguard Worker AvbVBMetaHeader, the third argument is a list of 2771*d289c2baSAndroid Build Coastguard Worker AvbDescriptor-derived instances, and the fourth argument is the 2772*d289c2baSAndroid Build Coastguard Worker size of |image|. 2773*d289c2baSAndroid Build Coastguard Worker 2774*d289c2baSAndroid Build Coastguard Worker Raises: 2775*d289c2baSAndroid Build Coastguard Worker AvbError: In case the image cannot be parsed. 2776*d289c2baSAndroid Build Coastguard Worker """ 2777*d289c2baSAndroid Build Coastguard Worker assert isinstance(image, ImageHandler) 2778*d289c2baSAndroid Build Coastguard Worker footer = None 2779*d289c2baSAndroid Build Coastguard Worker image.seek(image.image_size - AvbFooter.SIZE) 2780*d289c2baSAndroid Build Coastguard Worker try: 2781*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter(image.read(AvbFooter.SIZE)) 2782*d289c2baSAndroid Build Coastguard Worker except (LookupError, struct.error): 2783*d289c2baSAndroid Build Coastguard Worker # Nope, just seek back to the start. 2784*d289c2baSAndroid Build Coastguard Worker image.seek(0) 2785*d289c2baSAndroid Build Coastguard Worker 2786*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = 0 2787*d289c2baSAndroid Build Coastguard Worker if footer: 2788*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = footer.vbmeta_offset 2789*d289c2baSAndroid Build Coastguard Worker 2790*d289c2baSAndroid Build Coastguard Worker image.seek(vbmeta_offset) 2791*d289c2baSAndroid Build Coastguard Worker h = AvbVBMetaHeader(image.read(AvbVBMetaHeader.SIZE)) 2792*d289c2baSAndroid Build Coastguard Worker 2793*d289c2baSAndroid Build Coastguard Worker auth_block_offset = vbmeta_offset + AvbVBMetaHeader.SIZE 2794*d289c2baSAndroid Build Coastguard Worker aux_block_offset = auth_block_offset + h.authentication_data_block_size 2795*d289c2baSAndroid Build Coastguard Worker desc_start_offset = aux_block_offset + h.descriptors_offset 2796*d289c2baSAndroid Build Coastguard Worker image.seek(desc_start_offset) 2797*d289c2baSAndroid Build Coastguard Worker descriptors = parse_descriptors(image.read(h.descriptors_size)) 2798*d289c2baSAndroid Build Coastguard Worker 2799*d289c2baSAndroid Build Coastguard Worker return footer, h, descriptors, image.image_size 2800*d289c2baSAndroid Build Coastguard Worker 2801*d289c2baSAndroid Build Coastguard Worker def _load_vbmeta_blob(self, image): 2802*d289c2baSAndroid Build Coastguard Worker """Gets the vbmeta struct and associated sections. 2803*d289c2baSAndroid Build Coastguard Worker 2804*d289c2baSAndroid Build Coastguard Worker The image can either be a vbmeta.img or an image with a footer. 2805*d289c2baSAndroid Build Coastguard Worker 2806*d289c2baSAndroid Build Coastguard Worker Arguments: 2807*d289c2baSAndroid Build Coastguard Worker image: An ImageHandler (vbmeta or footer). 2808*d289c2baSAndroid Build Coastguard Worker 2809*d289c2baSAndroid Build Coastguard Worker Returns: 2810*d289c2baSAndroid Build Coastguard Worker A blob with the vbmeta struct and other sections. 2811*d289c2baSAndroid Build Coastguard Worker """ 2812*d289c2baSAndroid Build Coastguard Worker assert isinstance(image, ImageHandler) 2813*d289c2baSAndroid Build Coastguard Worker footer = None 2814*d289c2baSAndroid Build Coastguard Worker image.seek(image.image_size - AvbFooter.SIZE) 2815*d289c2baSAndroid Build Coastguard Worker try: 2816*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter(image.read(AvbFooter.SIZE)) 2817*d289c2baSAndroid Build Coastguard Worker except (LookupError, struct.error): 2818*d289c2baSAndroid Build Coastguard Worker # Nope, just seek back to the start. 2819*d289c2baSAndroid Build Coastguard Worker image.seek(0) 2820*d289c2baSAndroid Build Coastguard Worker 2821*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = 0 2822*d289c2baSAndroid Build Coastguard Worker if footer: 2823*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = footer.vbmeta_offset 2824*d289c2baSAndroid Build Coastguard Worker 2825*d289c2baSAndroid Build Coastguard Worker image.seek(vbmeta_offset) 2826*d289c2baSAndroid Build Coastguard Worker h = AvbVBMetaHeader(image.read(AvbVBMetaHeader.SIZE)) 2827*d289c2baSAndroid Build Coastguard Worker 2828*d289c2baSAndroid Build Coastguard Worker image.seek(vbmeta_offset) 2829*d289c2baSAndroid Build Coastguard Worker data_size = AvbVBMetaHeader.SIZE 2830*d289c2baSAndroid Build Coastguard Worker data_size += h.authentication_data_block_size 2831*d289c2baSAndroid Build Coastguard Worker data_size += h.auxiliary_data_block_size 2832*d289c2baSAndroid Build Coastguard Worker return image.read(data_size) 2833*d289c2baSAndroid Build Coastguard Worker 2834*d289c2baSAndroid Build Coastguard Worker def _get_cmdline_descriptors_for_hashtree_descriptor(self, ht): 2835*d289c2baSAndroid Build Coastguard Worker """Generate kernel cmdline descriptors for dm-verity. 2836*d289c2baSAndroid Build Coastguard Worker 2837*d289c2baSAndroid Build Coastguard Worker Arguments: 2838*d289c2baSAndroid Build Coastguard Worker ht: A AvbHashtreeDescriptor 2839*d289c2baSAndroid Build Coastguard Worker 2840*d289c2baSAndroid Build Coastguard Worker Returns: 2841*d289c2baSAndroid Build Coastguard Worker A list with two AvbKernelCmdlineDescriptor with dm-verity kernel cmdline 2842*d289c2baSAndroid Build Coastguard Worker instructions. There is one for when hashtree is not disabled and one for 2843*d289c2baSAndroid Build Coastguard Worker when it is. 2844*d289c2baSAndroid Build Coastguard Worker 2845*d289c2baSAndroid Build Coastguard Worker """ 2846*d289c2baSAndroid Build Coastguard Worker c = 'dm="1 vroot none ro 1,' 2847*d289c2baSAndroid Build Coastguard Worker c += '0' # start 2848*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format((ht.image_size // 512)) # size (# sectors) 2849*d289c2baSAndroid Build Coastguard Worker c += ' verity {}'.format(ht.dm_verity_version) # type and version 2850*d289c2baSAndroid Build Coastguard Worker c += ' PARTUUID=$(ANDROID_SYSTEM_PARTUUID)' # data_dev 2851*d289c2baSAndroid Build Coastguard Worker c += ' PARTUUID=$(ANDROID_SYSTEM_PARTUUID)' # hash_dev 2852*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.data_block_size) # data_block 2853*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.hash_block_size) # hash_block 2854*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.image_size // ht.data_block_size) # #blocks 2855*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.image_size // ht.data_block_size) # hash_offset 2856*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.hash_algorithm) # hash_alg 2857*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.root_digest.hex()) # root_digest 2858*d289c2baSAndroid Build Coastguard Worker c += ' {}'.format(ht.salt.hex()) # salt 2859*d289c2baSAndroid Build Coastguard Worker if ht.fec_num_roots > 0: 2860*d289c2baSAndroid Build Coastguard Worker if ht.flags & AvbHashtreeDescriptor.FLAGS_CHECK_AT_MOST_ONCE: 2861*d289c2baSAndroid Build Coastguard Worker c += ' 11' # number of optional args 2862*d289c2baSAndroid Build Coastguard Worker c += ' check_at_most_once' 2863*d289c2baSAndroid Build Coastguard Worker else: 2864*d289c2baSAndroid Build Coastguard Worker c += ' 10' # number of optional args 2865*d289c2baSAndroid Build Coastguard Worker c += ' $(ANDROID_VERITY_MODE)' 2866*d289c2baSAndroid Build Coastguard Worker c += ' ignore_zero_blocks' 2867*d289c2baSAndroid Build Coastguard Worker c += ' use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID)' 2868*d289c2baSAndroid Build Coastguard Worker c += ' fec_roots {}'.format(ht.fec_num_roots) 2869*d289c2baSAndroid Build Coastguard Worker # Note that fec_blocks is the size that FEC covers, *not* the 2870*d289c2baSAndroid Build Coastguard Worker # size of the FEC data. Since we use FEC for everything up until 2871*d289c2baSAndroid Build Coastguard Worker # the FEC data, it's the same as the offset. 2872*d289c2baSAndroid Build Coastguard Worker c += ' fec_blocks {}'.format(ht.fec_offset // ht.data_block_size) 2873*d289c2baSAndroid Build Coastguard Worker c += ' fec_start {}'.format(ht.fec_offset // ht.data_block_size) 2874*d289c2baSAndroid Build Coastguard Worker else: 2875*d289c2baSAndroid Build Coastguard Worker if ht.flags & AvbHashtreeDescriptor.FLAGS_CHECK_AT_MOST_ONCE: 2876*d289c2baSAndroid Build Coastguard Worker c += ' 3' # number of optional args 2877*d289c2baSAndroid Build Coastguard Worker c += ' check_at_most_once' 2878*d289c2baSAndroid Build Coastguard Worker else: 2879*d289c2baSAndroid Build Coastguard Worker c += ' 2' # number of optional args 2880*d289c2baSAndroid Build Coastguard Worker c += ' $(ANDROID_VERITY_MODE)' 2881*d289c2baSAndroid Build Coastguard Worker c += ' ignore_zero_blocks' 2882*d289c2baSAndroid Build Coastguard Worker c += '" root=/dev/dm-0' 2883*d289c2baSAndroid Build Coastguard Worker 2884*d289c2baSAndroid Build Coastguard Worker # Now that we have the command-line, generate the descriptor. 2885*d289c2baSAndroid Build Coastguard Worker desc = AvbKernelCmdlineDescriptor() 2886*d289c2baSAndroid Build Coastguard Worker desc.kernel_cmdline = c 2887*d289c2baSAndroid Build Coastguard Worker desc.flags = ( 2888*d289c2baSAndroid Build Coastguard Worker AvbKernelCmdlineDescriptor.FLAGS_USE_ONLY_IF_HASHTREE_NOT_DISABLED) 2889*d289c2baSAndroid Build Coastguard Worker 2890*d289c2baSAndroid Build Coastguard Worker # The descriptor for when hashtree verification is disabled is a lot 2891*d289c2baSAndroid Build Coastguard Worker # simpler - we just set the root to the partition. 2892*d289c2baSAndroid Build Coastguard Worker desc_no_ht = AvbKernelCmdlineDescriptor() 2893*d289c2baSAndroid Build Coastguard Worker desc_no_ht.kernel_cmdline = 'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)' 2894*d289c2baSAndroid Build Coastguard Worker desc_no_ht.flags = ( 2895*d289c2baSAndroid Build Coastguard Worker AvbKernelCmdlineDescriptor.FLAGS_USE_ONLY_IF_HASHTREE_DISABLED) 2896*d289c2baSAndroid Build Coastguard Worker 2897*d289c2baSAndroid Build Coastguard Worker return [desc, desc_no_ht] 2898*d289c2baSAndroid Build Coastguard Worker 2899*d289c2baSAndroid Build Coastguard Worker def _get_cmdline_descriptors_for_dm_verity(self, image): 2900*d289c2baSAndroid Build Coastguard Worker """Generate kernel cmdline descriptors for dm-verity. 2901*d289c2baSAndroid Build Coastguard Worker 2902*d289c2baSAndroid Build Coastguard Worker Arguments: 2903*d289c2baSAndroid Build Coastguard Worker image: An ImageHandler (vbmeta or footer) with a hashtree descriptor. 2904*d289c2baSAndroid Build Coastguard Worker 2905*d289c2baSAndroid Build Coastguard Worker Returns: 2906*d289c2baSAndroid Build Coastguard Worker A list with two AvbKernelCmdlineDescriptor with dm-verity kernel cmdline 2907*d289c2baSAndroid Build Coastguard Worker instructions. There is one for when hashtree is not disabled and one for 2908*d289c2baSAndroid Build Coastguard Worker when it is. 2909*d289c2baSAndroid Build Coastguard Worker 2910*d289c2baSAndroid Build Coastguard Worker Raises: 2911*d289c2baSAndroid Build Coastguard Worker AvbError: If |image| doesn't have a hashtree descriptor. 2912*d289c2baSAndroid Build Coastguard Worker 2913*d289c2baSAndroid Build Coastguard Worker """ 2914*d289c2baSAndroid Build Coastguard Worker (_, _, descriptors, _) = self._parse_image(image) 2915*d289c2baSAndroid Build Coastguard Worker 2916*d289c2baSAndroid Build Coastguard Worker ht = None 2917*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 2918*d289c2baSAndroid Build Coastguard Worker if isinstance(desc, AvbHashtreeDescriptor): 2919*d289c2baSAndroid Build Coastguard Worker ht = desc 2920*d289c2baSAndroid Build Coastguard Worker break 2921*d289c2baSAndroid Build Coastguard Worker 2922*d289c2baSAndroid Build Coastguard Worker if not ht: 2923*d289c2baSAndroid Build Coastguard Worker raise AvbError('No hashtree descriptor in given image') 2924*d289c2baSAndroid Build Coastguard Worker 2925*d289c2baSAndroid Build Coastguard Worker return self._get_cmdline_descriptors_for_hashtree_descriptor(ht) 2926*d289c2baSAndroid Build Coastguard Worker 2927*d289c2baSAndroid Build Coastguard Worker def make_vbmeta_image(self, output, chain_partitions_use_ab, 2928*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab, algorithm_name, 2929*d289c2baSAndroid Build Coastguard Worker key_path, public_key_metadata_path, rollback_index, 2930*d289c2baSAndroid Build Coastguard Worker flags, rollback_index_location, 2931*d289c2baSAndroid Build Coastguard Worker props, props_from_file, kernel_cmdlines, 2932*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel, 2933*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, 2934*d289c2baSAndroid Build Coastguard Worker signing_helper, 2935*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files, 2936*d289c2baSAndroid Build Coastguard Worker release_string, 2937*d289c2baSAndroid Build Coastguard Worker append_to_release_string, 2938*d289c2baSAndroid Build Coastguard Worker print_required_libavb_version, 2939*d289c2baSAndroid Build Coastguard Worker padding_size): 2940*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_vbmeta_image' command. 2941*d289c2baSAndroid Build Coastguard Worker 2942*d289c2baSAndroid Build Coastguard Worker Arguments: 2943*d289c2baSAndroid Build Coastguard Worker output: File to write the image to. 2944*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab: List of partitions to chain or None. 2945*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab: List of partitions to chain which does not use A/B or None. 2946*d289c2baSAndroid Build Coastguard Worker algorithm_name: Name of algorithm to use. 2947*d289c2baSAndroid Build Coastguard Worker key_path: Path to key to use or None. 2948*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path: Path to public key metadata or None. 2949*d289c2baSAndroid Build Coastguard Worker rollback_index: The rollback index to use. 2950*d289c2baSAndroid Build Coastguard Worker flags: Flags value to use in the image. 2951*d289c2baSAndroid Build Coastguard Worker rollback_index_location: Location of the main vbmeta rollback index. 2952*d289c2baSAndroid Build Coastguard Worker props: Properties to insert (list of strings of the form 'key:value'). 2953*d289c2baSAndroid Build Coastguard Worker props_from_file: Properties to insert (list of strings 'key:<path>'). 2954*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines: Kernel cmdlines to insert (list of strings). 2955*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel: None or file to generate from. 2956*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image: List of file objects with descriptors. 2957*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and return signature. 2958*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 2959*d289c2baSAndroid Build Coastguard Worker release_string: None or avbtool release string to use instead of default. 2960*d289c2baSAndroid Build Coastguard Worker append_to_release_string: None or string to append. 2961*d289c2baSAndroid Build Coastguard Worker print_required_libavb_version: True to only print required libavb version. 2962*d289c2baSAndroid Build Coastguard Worker padding_size: If not 0, pads output so size is a multiple of the number. 2963*d289c2baSAndroid Build Coastguard Worker 2964*d289c2baSAndroid Build Coastguard Worker Raises: 2965*d289c2baSAndroid Build Coastguard Worker AvbError: If a chained partition is malformed. 2966*d289c2baSAndroid Build Coastguard Worker """ 2967*d289c2baSAndroid Build Coastguard Worker # If we're asked to calculate minimum required libavb version, we're done. 2968*d289c2baSAndroid Build Coastguard Worker tmp_header = AvbVBMetaHeader() 2969*d289c2baSAndroid Build Coastguard Worker if rollback_index_location > 0: 2970*d289c2baSAndroid Build Coastguard Worker tmp_header.bump_required_libavb_version_minor(2) 2971*d289c2baSAndroid Build Coastguard Worker if chain_partitions_do_not_use_ab: 2972*d289c2baSAndroid Build Coastguard Worker tmp_header.bump_required_libavb_version_minor(3) 2973*d289c2baSAndroid Build Coastguard Worker if include_descriptors_from_image: 2974*d289c2baSAndroid Build Coastguard Worker # Use the bump logic in AvbVBMetaHeader to calculate the max required 2975*d289c2baSAndroid Build Coastguard Worker # version of all included descriptors. 2976*d289c2baSAndroid Build Coastguard Worker for image in include_descriptors_from_image: 2977*d289c2baSAndroid Build Coastguard Worker (_, image_header, _, _) = self._parse_image(ImageHandler( 2978*d289c2baSAndroid Build Coastguard Worker image.name, read_only=True)) 2979*d289c2baSAndroid Build Coastguard Worker tmp_header.bump_required_libavb_version_minor( 2980*d289c2baSAndroid Build Coastguard Worker image_header.required_libavb_version_minor) 2981*d289c2baSAndroid Build Coastguard Worker 2982*d289c2baSAndroid Build Coastguard Worker if print_required_libavb_version: 2983*d289c2baSAndroid Build Coastguard Worker print('1.{}'.format(tmp_header.required_libavb_version_minor)) 2984*d289c2baSAndroid Build Coastguard Worker return 2985*d289c2baSAndroid Build Coastguard Worker 2986*d289c2baSAndroid Build Coastguard Worker if not output: 2987*d289c2baSAndroid Build Coastguard Worker raise AvbError('No output file given') 2988*d289c2baSAndroid Build Coastguard Worker 2989*d289c2baSAndroid Build Coastguard Worker descriptors = [] 2990*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup = None 2991*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = self._generate_vbmeta_blob( 2992*d289c2baSAndroid Build Coastguard Worker algorithm_name, key_path, public_key_metadata_path, descriptors, 2993*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab, chain_partitions_do_not_use_ab, 2994*d289c2baSAndroid Build Coastguard Worker rollback_index, flags, rollback_index_location, props, props_from_file, 2995*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines, setup_rootfs_from_kernel, ht_desc_to_setup, 2996*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, signing_helper, 2997*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files, release_string, 2998*d289c2baSAndroid Build Coastguard Worker append_to_release_string, tmp_header.required_libavb_version_minor) 2999*d289c2baSAndroid Build Coastguard Worker 3000*d289c2baSAndroid Build Coastguard Worker # Write entire vbmeta blob (header, authentication, auxiliary). 3001*d289c2baSAndroid Build Coastguard Worker output.seek(0) 3002*d289c2baSAndroid Build Coastguard Worker output.write(vbmeta_blob) 3003*d289c2baSAndroid Build Coastguard Worker 3004*d289c2baSAndroid Build Coastguard Worker if padding_size > 0: 3005*d289c2baSAndroid Build Coastguard Worker padded_size = round_to_multiple(len(vbmeta_blob), padding_size) 3006*d289c2baSAndroid Build Coastguard Worker padding_needed = padded_size - len(vbmeta_blob) 3007*d289c2baSAndroid Build Coastguard Worker output.write(b'\0' * padding_needed) 3008*d289c2baSAndroid Build Coastguard Worker 3009*d289c2baSAndroid Build Coastguard Worker def _generate_vbmeta_blob(self, algorithm_name, key_path, 3010*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path, descriptors, 3011*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab, chain_partitions_do_not_use_ab, 3012*d289c2baSAndroid Build Coastguard Worker rollback_index, flags, rollback_index_location, 3013*d289c2baSAndroid Build Coastguard Worker props, props_from_file, 3014*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines, 3015*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel, 3016*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup, 3017*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, signing_helper, 3018*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files, 3019*d289c2baSAndroid Build Coastguard Worker release_string, append_to_release_string, 3020*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor): 3021*d289c2baSAndroid Build Coastguard Worker """Generates a VBMeta blob. 3022*d289c2baSAndroid Build Coastguard Worker 3023*d289c2baSAndroid Build Coastguard Worker This blob contains the header (struct AvbVBMetaHeader), the 3024*d289c2baSAndroid Build Coastguard Worker authentication data block (which contains the hash and signature 3025*d289c2baSAndroid Build Coastguard Worker for the header and auxiliary block), and the auxiliary block 3026*d289c2baSAndroid Build Coastguard Worker (which contains descriptors, the public key used, and other data). 3027*d289c2baSAndroid Build Coastguard Worker 3028*d289c2baSAndroid Build Coastguard Worker The |key| parameter can |None| only if the |algorithm_name| is 3029*d289c2baSAndroid Build Coastguard Worker 'NONE'. 3030*d289c2baSAndroid Build Coastguard Worker 3031*d289c2baSAndroid Build Coastguard Worker Arguments: 3032*d289c2baSAndroid Build Coastguard Worker algorithm_name: The algorithm name as per the ALGORITHMS dict. 3033*d289c2baSAndroid Build Coastguard Worker key_path: The path to the .pem file used to sign the blob. 3034*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path: Path to public key metadata or None. 3035*d289c2baSAndroid Build Coastguard Worker descriptors: A list of descriptors to insert or None. 3036*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab: List of partitions to chain with A/B or None. 3037*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab: List of partitions to chain without A/B or None 3038*d289c2baSAndroid Build Coastguard Worker rollback_index: The rollback index to use. 3039*d289c2baSAndroid Build Coastguard Worker flags: Flags to use in the image. 3040*d289c2baSAndroid Build Coastguard Worker rollback_index_location: Location of the main vbmeta rollback index. 3041*d289c2baSAndroid Build Coastguard Worker props: Properties to insert (List of strings of the form 'key:value'). 3042*d289c2baSAndroid Build Coastguard Worker props_from_file: Properties to insert (List of strings 'key:<path>'). 3043*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines: Kernel cmdlines to insert (list of strings). 3044*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel: None or file to generate 3045*d289c2baSAndroid Build Coastguard Worker dm-verity kernel cmdline from. 3046*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup: If not None, an AvbHashtreeDescriptor to 3047*d289c2baSAndroid Build Coastguard Worker generate dm-verity kernel cmdline descriptors from. 3048*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image: List of file objects for which 3049*d289c2baSAndroid Build Coastguard Worker to insert descriptors from. 3050*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and return signature. 3051*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 3052*d289c2baSAndroid Build Coastguard Worker release_string: None or avbtool release string. 3053*d289c2baSAndroid Build Coastguard Worker append_to_release_string: None or string to append. 3054*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor: Use at least this required minor version. 3055*d289c2baSAndroid Build Coastguard Worker 3056*d289c2baSAndroid Build Coastguard Worker Returns: 3057*d289c2baSAndroid Build Coastguard Worker The VBMeta blob as bytes. 3058*d289c2baSAndroid Build Coastguard Worker 3059*d289c2baSAndroid Build Coastguard Worker Raises: 3060*d289c2baSAndroid Build Coastguard Worker Exception: If the |algorithm_name| is not found, if no key has 3061*d289c2baSAndroid Build Coastguard Worker been given and the given algorithm requires one, or the key is 3062*d289c2baSAndroid Build Coastguard Worker of the wrong size. 3063*d289c2baSAndroid Build Coastguard Worker """ 3064*d289c2baSAndroid Build Coastguard Worker try: 3065*d289c2baSAndroid Build Coastguard Worker alg = ALGORITHMS[algorithm_name] 3066*d289c2baSAndroid Build Coastguard Worker except KeyError as e: 3067*d289c2baSAndroid Build Coastguard Worker raise AvbError('Unknown algorithm with name {}' 3068*d289c2baSAndroid Build Coastguard Worker .format(algorithm_name)) from e 3069*d289c2baSAndroid Build Coastguard Worker 3070*d289c2baSAndroid Build Coastguard Worker if not descriptors: 3071*d289c2baSAndroid Build Coastguard Worker descriptors = [] 3072*d289c2baSAndroid Build Coastguard Worker 3073*d289c2baSAndroid Build Coastguard Worker h = AvbVBMetaHeader() 3074*d289c2baSAndroid Build Coastguard Worker h.bump_required_libavb_version_minor(required_libavb_version_minor) 3075*d289c2baSAndroid Build Coastguard Worker 3076*d289c2baSAndroid Build Coastguard Worker # Insert chained partition descriptors, if any 3077*d289c2baSAndroid Build Coastguard Worker all_chain_partitions = [] 3078*d289c2baSAndroid Build Coastguard Worker if chain_partitions_use_ab: 3079*d289c2baSAndroid Build Coastguard Worker all_chain_partitions.extend(chain_partitions_use_ab) 3080*d289c2baSAndroid Build Coastguard Worker if chain_partitions_do_not_use_ab: 3081*d289c2baSAndroid Build Coastguard Worker all_chain_partitions.extend(chain_partitions_do_not_use_ab) 3082*d289c2baSAndroid Build Coastguard Worker 3083*d289c2baSAndroid Build Coastguard Worker if len(all_chain_partitions) > 0: 3084*d289c2baSAndroid Build Coastguard Worker used_locations = {rollback_index_location: True} 3085*d289c2baSAndroid Build Coastguard Worker for cp in all_chain_partitions: 3086*d289c2baSAndroid Build Coastguard Worker cp_tokens = cp.split(':') 3087*d289c2baSAndroid Build Coastguard Worker if len(cp_tokens) != 3: 3088*d289c2baSAndroid Build Coastguard Worker raise AvbError('Malformed chained partition "{}".'.format(cp)) 3089*d289c2baSAndroid Build Coastguard Worker partition_name = cp_tokens[0] 3090*d289c2baSAndroid Build Coastguard Worker chained_rollback_index_location = int(cp_tokens[1]) 3091*d289c2baSAndroid Build Coastguard Worker file_path = cp_tokens[2] 3092*d289c2baSAndroid Build Coastguard Worker # Check that the same rollback location isn't being used by 3093*d289c2baSAndroid Build Coastguard Worker # multiple chained partitions. 3094*d289c2baSAndroid Build Coastguard Worker if used_locations.get(chained_rollback_index_location): 3095*d289c2baSAndroid Build Coastguard Worker raise AvbError('Rollback Index Location {} is already in use.'.format( 3096*d289c2baSAndroid Build Coastguard Worker chained_rollback_index_location)) 3097*d289c2baSAndroid Build Coastguard Worker used_locations[chained_rollback_index_location] = True 3098*d289c2baSAndroid Build Coastguard Worker desc = AvbChainPartitionDescriptor() 3099*d289c2baSAndroid Build Coastguard Worker desc.partition_name = partition_name 3100*d289c2baSAndroid Build Coastguard Worker desc.rollback_index_location = chained_rollback_index_location 3101*d289c2baSAndroid Build Coastguard Worker if desc.rollback_index_location < 1: 3102*d289c2baSAndroid Build Coastguard Worker raise AvbError('Rollback index location must be 1 or larger.') 3103*d289c2baSAndroid Build Coastguard Worker with open(file_path, 'rb') as f: 3104*d289c2baSAndroid Build Coastguard Worker desc.public_key = f.read() 3105*d289c2baSAndroid Build Coastguard Worker if chain_partitions_do_not_use_ab and (cp in chain_partitions_do_not_use_ab): 3106*d289c2baSAndroid Build Coastguard Worker desc.flags |= 1 3107*d289c2baSAndroid Build Coastguard Worker descriptors.append(desc) 3108*d289c2baSAndroid Build Coastguard Worker 3109*d289c2baSAndroid Build Coastguard Worker # Descriptors. 3110*d289c2baSAndroid Build Coastguard Worker encoded_descriptors = bytearray() 3111*d289c2baSAndroid Build Coastguard Worker for desc in descriptors: 3112*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(desc.encode()) 3113*d289c2baSAndroid Build Coastguard Worker 3114*d289c2baSAndroid Build Coastguard Worker # Add properties. 3115*d289c2baSAndroid Build Coastguard Worker if props: 3116*d289c2baSAndroid Build Coastguard Worker for prop in props: 3117*d289c2baSAndroid Build Coastguard Worker idx = prop.find(':') 3118*d289c2baSAndroid Build Coastguard Worker if idx == -1: 3119*d289c2baSAndroid Build Coastguard Worker raise AvbError('Malformed property "{}".'.format(prop)) 3120*d289c2baSAndroid Build Coastguard Worker # pylint: disable=redefined-variable-type 3121*d289c2baSAndroid Build Coastguard Worker desc = AvbPropertyDescriptor() 3122*d289c2baSAndroid Build Coastguard Worker desc.key = prop[0:idx] 3123*d289c2baSAndroid Build Coastguard Worker desc.value = prop[(idx + 1):].encode('utf-8') 3124*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(desc.encode()) 3125*d289c2baSAndroid Build Coastguard Worker if props_from_file: 3126*d289c2baSAndroid Build Coastguard Worker for prop in props_from_file: 3127*d289c2baSAndroid Build Coastguard Worker idx = prop.find(':') 3128*d289c2baSAndroid Build Coastguard Worker if idx == -1: 3129*d289c2baSAndroid Build Coastguard Worker raise AvbError('Malformed property "{}".'.format(prop)) 3130*d289c2baSAndroid Build Coastguard Worker desc = AvbPropertyDescriptor() 3131*d289c2baSAndroid Build Coastguard Worker desc.key = prop[0:idx] 3132*d289c2baSAndroid Build Coastguard Worker file_path = prop[(idx + 1):] 3133*d289c2baSAndroid Build Coastguard Worker with open(file_path, 'rb') as f: 3134*d289c2baSAndroid Build Coastguard Worker # pylint: disable=attribute-defined-outside-init 3135*d289c2baSAndroid Build Coastguard Worker desc.value = f.read() 3136*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(desc.encode()) 3137*d289c2baSAndroid Build Coastguard Worker 3138*d289c2baSAndroid Build Coastguard Worker # Add AvbKernelCmdline descriptor for dm-verity from an image, if requested. 3139*d289c2baSAndroid Build Coastguard Worker if setup_rootfs_from_kernel: 3140*d289c2baSAndroid Build Coastguard Worker image_handler = ImageHandler( 3141*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel.name) 3142*d289c2baSAndroid Build Coastguard Worker cmdline_desc = self._get_cmdline_descriptors_for_dm_verity(image_handler) 3143*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(cmdline_desc[0].encode()) 3144*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(cmdline_desc[1].encode()) 3145*d289c2baSAndroid Build Coastguard Worker 3146*d289c2baSAndroid Build Coastguard Worker # Add AvbKernelCmdline descriptor for dm-verity from desc, if requested. 3147*d289c2baSAndroid Build Coastguard Worker if ht_desc_to_setup: 3148*d289c2baSAndroid Build Coastguard Worker cmdline_desc = self._get_cmdline_descriptors_for_hashtree_descriptor( 3149*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup) 3150*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(cmdline_desc[0].encode()) 3151*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(cmdline_desc[1].encode()) 3152*d289c2baSAndroid Build Coastguard Worker 3153*d289c2baSAndroid Build Coastguard Worker # Add kernel command-lines. 3154*d289c2baSAndroid Build Coastguard Worker if kernel_cmdlines: 3155*d289c2baSAndroid Build Coastguard Worker for i in kernel_cmdlines: 3156*d289c2baSAndroid Build Coastguard Worker desc = AvbKernelCmdlineDescriptor() 3157*d289c2baSAndroid Build Coastguard Worker desc.kernel_cmdline = i 3158*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(desc.encode()) 3159*d289c2baSAndroid Build Coastguard Worker 3160*d289c2baSAndroid Build Coastguard Worker # Add descriptors from other images. 3161*d289c2baSAndroid Build Coastguard Worker if include_descriptors_from_image: 3162*d289c2baSAndroid Build Coastguard Worker descriptors_dict = dict() 3163*d289c2baSAndroid Build Coastguard Worker for image in include_descriptors_from_image: 3164*d289c2baSAndroid Build Coastguard Worker image_handler = ImageHandler(image.name, read_only=True) 3165*d289c2baSAndroid Build Coastguard Worker (_, image_vbmeta_header, image_descriptors, _) = self._parse_image( 3166*d289c2baSAndroid Build Coastguard Worker image_handler) 3167*d289c2baSAndroid Build Coastguard Worker # Bump the required libavb version to support all included descriptors. 3168*d289c2baSAndroid Build Coastguard Worker h.bump_required_libavb_version_minor( 3169*d289c2baSAndroid Build Coastguard Worker image_vbmeta_header.required_libavb_version_minor) 3170*d289c2baSAndroid Build Coastguard Worker for desc in image_descriptors: 3171*d289c2baSAndroid Build Coastguard Worker # The --include_descriptors_from_image option is used in some setups 3172*d289c2baSAndroid Build Coastguard Worker # with images A and B where both A and B contain a descriptor 3173*d289c2baSAndroid Build Coastguard Worker # for a partition with the same name. Since it's not meaningful 3174*d289c2baSAndroid Build Coastguard Worker # to include both descriptors, only include the last seen descriptor. 3175*d289c2baSAndroid Build Coastguard Worker # See bug 76386656 for details. 3176*d289c2baSAndroid Build Coastguard Worker if hasattr(desc, 'partition_name'): 3177*d289c2baSAndroid Build Coastguard Worker key = type(desc).__name__ + '_' + desc.partition_name 3178*d289c2baSAndroid Build Coastguard Worker descriptors_dict[key] = desc.encode() 3179*d289c2baSAndroid Build Coastguard Worker else: 3180*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(desc.encode()) 3181*d289c2baSAndroid Build Coastguard Worker for key in sorted(descriptors_dict): 3182*d289c2baSAndroid Build Coastguard Worker encoded_descriptors.extend(descriptors_dict[key]) 3183*d289c2baSAndroid Build Coastguard Worker 3184*d289c2baSAndroid Build Coastguard Worker # Load public key metadata blob, if requested. 3185*d289c2baSAndroid Build Coastguard Worker pkmd_blob = b'' 3186*d289c2baSAndroid Build Coastguard Worker if public_key_metadata_path: 3187*d289c2baSAndroid Build Coastguard Worker with open(public_key_metadata_path, 'rb') as f: 3188*d289c2baSAndroid Build Coastguard Worker pkmd_blob = f.read() 3189*d289c2baSAndroid Build Coastguard Worker 3190*d289c2baSAndroid Build Coastguard Worker key = None 3191*d289c2baSAndroid Build Coastguard Worker encoded_key = b'' 3192*d289c2baSAndroid Build Coastguard Worker if alg.public_key_num_bytes > 0: 3193*d289c2baSAndroid Build Coastguard Worker if not key_path: 3194*d289c2baSAndroid Build Coastguard Worker raise AvbError('Key is required for algorithm {}'.format( 3195*d289c2baSAndroid Build Coastguard Worker algorithm_name)) 3196*d289c2baSAndroid Build Coastguard Worker encoded_key = RSAPublicKey(key_path).encode() 3197*d289c2baSAndroid Build Coastguard Worker if len(encoded_key) != alg.public_key_num_bytes: 3198*d289c2baSAndroid Build Coastguard Worker raise AvbError('Key is wrong size for algorithm {}'.format( 3199*d289c2baSAndroid Build Coastguard Worker algorithm_name)) 3200*d289c2baSAndroid Build Coastguard Worker 3201*d289c2baSAndroid Build Coastguard Worker # Override release string, if requested. 3202*d289c2baSAndroid Build Coastguard Worker if isinstance(release_string, str): 3203*d289c2baSAndroid Build Coastguard Worker h.release_string = release_string 3204*d289c2baSAndroid Build Coastguard Worker 3205*d289c2baSAndroid Build Coastguard Worker # Append to release string, if requested. Also insert a space before. 3206*d289c2baSAndroid Build Coastguard Worker if isinstance(append_to_release_string, str): 3207*d289c2baSAndroid Build Coastguard Worker h.release_string += ' ' + append_to_release_string 3208*d289c2baSAndroid Build Coastguard Worker 3209*d289c2baSAndroid Build Coastguard Worker # For the Auxiliary data block, descriptors are stored at offset 0, 3210*d289c2baSAndroid Build Coastguard Worker # followed by the public key, followed by the public key metadata blob. 3211*d289c2baSAndroid Build Coastguard Worker h.auxiliary_data_block_size = round_to_multiple( 3212*d289c2baSAndroid Build Coastguard Worker len(encoded_descriptors) + len(encoded_key) + len(pkmd_blob), 64) 3213*d289c2baSAndroid Build Coastguard Worker h.descriptors_offset = 0 3214*d289c2baSAndroid Build Coastguard Worker h.descriptors_size = len(encoded_descriptors) 3215*d289c2baSAndroid Build Coastguard Worker h.public_key_offset = h.descriptors_size 3216*d289c2baSAndroid Build Coastguard Worker h.public_key_size = len(encoded_key) 3217*d289c2baSAndroid Build Coastguard Worker h.public_key_metadata_offset = h.public_key_offset + h.public_key_size 3218*d289c2baSAndroid Build Coastguard Worker h.public_key_metadata_size = len(pkmd_blob) 3219*d289c2baSAndroid Build Coastguard Worker 3220*d289c2baSAndroid Build Coastguard Worker # For the Authentication data block, the hash is first and then 3221*d289c2baSAndroid Build Coastguard Worker # the signature. 3222*d289c2baSAndroid Build Coastguard Worker h.authentication_data_block_size = round_to_multiple( 3223*d289c2baSAndroid Build Coastguard Worker alg.hash_num_bytes + alg.signature_num_bytes, 64) 3224*d289c2baSAndroid Build Coastguard Worker h.algorithm_type = alg.algorithm_type 3225*d289c2baSAndroid Build Coastguard Worker h.hash_offset = 0 3226*d289c2baSAndroid Build Coastguard Worker h.hash_size = alg.hash_num_bytes 3227*d289c2baSAndroid Build Coastguard Worker # Signature offset and size - it's stored right after the hash 3228*d289c2baSAndroid Build Coastguard Worker # (in Authentication data block). 3229*d289c2baSAndroid Build Coastguard Worker h.signature_offset = alg.hash_num_bytes 3230*d289c2baSAndroid Build Coastguard Worker h.signature_size = alg.signature_num_bytes 3231*d289c2baSAndroid Build Coastguard Worker 3232*d289c2baSAndroid Build Coastguard Worker h.rollback_index = rollback_index 3233*d289c2baSAndroid Build Coastguard Worker h.flags = flags 3234*d289c2baSAndroid Build Coastguard Worker h.rollback_index_location = rollback_index_location 3235*d289c2baSAndroid Build Coastguard Worker 3236*d289c2baSAndroid Build Coastguard Worker # Generate Header data block. 3237*d289c2baSAndroid Build Coastguard Worker header_data_blob = h.encode() 3238*d289c2baSAndroid Build Coastguard Worker 3239*d289c2baSAndroid Build Coastguard Worker # Generate Auxiliary data block. 3240*d289c2baSAndroid Build Coastguard Worker aux_data_blob = bytearray() 3241*d289c2baSAndroid Build Coastguard Worker aux_data_blob.extend(encoded_descriptors) 3242*d289c2baSAndroid Build Coastguard Worker aux_data_blob.extend(encoded_key) 3243*d289c2baSAndroid Build Coastguard Worker aux_data_blob.extend(pkmd_blob) 3244*d289c2baSAndroid Build Coastguard Worker padding_bytes = h.auxiliary_data_block_size - len(aux_data_blob) 3245*d289c2baSAndroid Build Coastguard Worker aux_data_blob.extend(b'\0' * padding_bytes) 3246*d289c2baSAndroid Build Coastguard Worker 3247*d289c2baSAndroid Build Coastguard Worker # Calculate the hash. 3248*d289c2baSAndroid Build Coastguard Worker binary_hash = b'' 3249*d289c2baSAndroid Build Coastguard Worker binary_signature = b'' 3250*d289c2baSAndroid Build Coastguard Worker if algorithm_name != 'NONE': 3251*d289c2baSAndroid Build Coastguard Worker ha = hashlib.new(alg.hash_name) 3252*d289c2baSAndroid Build Coastguard Worker ha.update(header_data_blob) 3253*d289c2baSAndroid Build Coastguard Worker ha.update(aux_data_blob) 3254*d289c2baSAndroid Build Coastguard Worker binary_hash = ha.digest() 3255*d289c2baSAndroid Build Coastguard Worker 3256*d289c2baSAndroid Build Coastguard Worker # Calculate the signature. 3257*d289c2baSAndroid Build Coastguard Worker rsa_key = RSAPublicKey(key_path) 3258*d289c2baSAndroid Build Coastguard Worker data_to_sign = header_data_blob + bytes(aux_data_blob) 3259*d289c2baSAndroid Build Coastguard Worker binary_signature = rsa_key.sign(algorithm_name, data_to_sign, 3260*d289c2baSAndroid Build Coastguard Worker signing_helper, signing_helper_with_files) 3261*d289c2baSAndroid Build Coastguard Worker 3262*d289c2baSAndroid Build Coastguard Worker # Generate Authentication data block. 3263*d289c2baSAndroid Build Coastguard Worker auth_data_blob = bytearray() 3264*d289c2baSAndroid Build Coastguard Worker auth_data_blob.extend(binary_hash) 3265*d289c2baSAndroid Build Coastguard Worker auth_data_blob.extend(binary_signature) 3266*d289c2baSAndroid Build Coastguard Worker padding_bytes = h.authentication_data_block_size - len(auth_data_blob) 3267*d289c2baSAndroid Build Coastguard Worker auth_data_blob.extend(b'\0' * padding_bytes) 3268*d289c2baSAndroid Build Coastguard Worker 3269*d289c2baSAndroid Build Coastguard Worker return header_data_blob + bytes(auth_data_blob) + bytes(aux_data_blob) 3270*d289c2baSAndroid Build Coastguard Worker 3271*d289c2baSAndroid Build Coastguard Worker def extract_public_key(self, key_path, output): 3272*d289c2baSAndroid Build Coastguard Worker """Implements the 'extract_public_key' command. 3273*d289c2baSAndroid Build Coastguard Worker 3274*d289c2baSAndroid Build Coastguard Worker Arguments: 3275*d289c2baSAndroid Build Coastguard Worker key_path: The path to a RSA private key file. 3276*d289c2baSAndroid Build Coastguard Worker output: The file to write to. 3277*d289c2baSAndroid Build Coastguard Worker 3278*d289c2baSAndroid Build Coastguard Worker Raises: 3279*d289c2baSAndroid Build Coastguard Worker AvbError: If the public key could not be extracted. 3280*d289c2baSAndroid Build Coastguard Worker """ 3281*d289c2baSAndroid Build Coastguard Worker output.write(RSAPublicKey(key_path).encode()) 3282*d289c2baSAndroid Build Coastguard Worker 3283*d289c2baSAndroid Build Coastguard Worker def append_vbmeta_image(self, image_filename, vbmeta_image_filename, 3284*d289c2baSAndroid Build Coastguard Worker partition_size): 3285*d289c2baSAndroid Build Coastguard Worker """Implementation of the append_vbmeta_image command. 3286*d289c2baSAndroid Build Coastguard Worker 3287*d289c2baSAndroid Build Coastguard Worker Arguments: 3288*d289c2baSAndroid Build Coastguard Worker image_filename: File to add the footer to. 3289*d289c2baSAndroid Build Coastguard Worker vbmeta_image_filename: File to get vbmeta struct from. 3290*d289c2baSAndroid Build Coastguard Worker partition_size: Size of partition. 3291*d289c2baSAndroid Build Coastguard Worker 3292*d289c2baSAndroid Build Coastguard Worker Raises: 3293*d289c2baSAndroid Build Coastguard Worker AvbError: If an argument is incorrect or if appending VBMeta image fialed. 3294*d289c2baSAndroid Build Coastguard Worker """ 3295*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename) 3296*d289c2baSAndroid Build Coastguard Worker 3297*d289c2baSAndroid Build Coastguard Worker if partition_size % image.block_size != 0: 3298*d289c2baSAndroid Build Coastguard Worker raise AvbError('Partition size of {} is not a multiple of the image ' 3299*d289c2baSAndroid Build Coastguard Worker 'block size {}.'.format(partition_size, 3300*d289c2baSAndroid Build Coastguard Worker image.block_size)) 3301*d289c2baSAndroid Build Coastguard Worker 3302*d289c2baSAndroid Build Coastguard Worker # If there's already a footer, truncate the image to its original 3303*d289c2baSAndroid Build Coastguard Worker # size. This way 'avbtool append_vbmeta_image' is idempotent. 3304*d289c2baSAndroid Build Coastguard Worker if image.image_size >= AvbFooter.SIZE: 3305*d289c2baSAndroid Build Coastguard Worker image.seek(image.image_size - AvbFooter.SIZE) 3306*d289c2baSAndroid Build Coastguard Worker try: 3307*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter(image.read(AvbFooter.SIZE)) 3308*d289c2baSAndroid Build Coastguard Worker # Existing footer found. Just truncate. 3309*d289c2baSAndroid Build Coastguard Worker original_image_size = footer.original_image_size 3310*d289c2baSAndroid Build Coastguard Worker image.truncate(footer.original_image_size) 3311*d289c2baSAndroid Build Coastguard Worker except (LookupError, struct.error): 3312*d289c2baSAndroid Build Coastguard Worker original_image_size = image.image_size 3313*d289c2baSAndroid Build Coastguard Worker else: 3314*d289c2baSAndroid Build Coastguard Worker # Image size is too small to possibly contain a footer. 3315*d289c2baSAndroid Build Coastguard Worker original_image_size = image.image_size 3316*d289c2baSAndroid Build Coastguard Worker 3317*d289c2baSAndroid Build Coastguard Worker # If anything goes wrong from here-on, restore the image back to 3318*d289c2baSAndroid Build Coastguard Worker # its original size. 3319*d289c2baSAndroid Build Coastguard Worker try: 3320*d289c2baSAndroid Build Coastguard Worker vbmeta_image_handler = ImageHandler(vbmeta_image_filename) 3321*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = self._load_vbmeta_blob(vbmeta_image_handler) 3322*d289c2baSAndroid Build Coastguard Worker 3323*d289c2baSAndroid Build Coastguard Worker # If the image isn't sparse, its size might not be a multiple of 3324*d289c2baSAndroid Build Coastguard Worker # the block size. This will screw up padding later so just grow it. 3325*d289c2baSAndroid Build Coastguard Worker if image.image_size % image.block_size != 0: 3326*d289c2baSAndroid Build Coastguard Worker assert not image.is_sparse 3327*d289c2baSAndroid Build Coastguard Worker padding_needed = image.block_size - (image.image_size%image.block_size) 3328*d289c2baSAndroid Build Coastguard Worker image.truncate(image.image_size + padding_needed) 3329*d289c2baSAndroid Build Coastguard Worker 3330*d289c2baSAndroid Build Coastguard Worker # The append_raw() method requires content with size being a 3331*d289c2baSAndroid Build Coastguard Worker # multiple of |block_size| so add padding as needed. Also record 3332*d289c2baSAndroid Build Coastguard Worker # where this is written to since we'll need to put that in the 3333*d289c2baSAndroid Build Coastguard Worker # footer. 3334*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = image.image_size 3335*d289c2baSAndroid Build Coastguard Worker padding_needed = (round_to_multiple(len(vbmeta_blob), image.block_size) - 3336*d289c2baSAndroid Build Coastguard Worker len(vbmeta_blob)) 3337*d289c2baSAndroid Build Coastguard Worker vbmeta_blob_with_padding = vbmeta_blob + b'\0' * padding_needed 3338*d289c2baSAndroid Build Coastguard Worker 3339*d289c2baSAndroid Build Coastguard Worker # Append vbmeta blob and footer 3340*d289c2baSAndroid Build Coastguard Worker image.append_raw(vbmeta_blob_with_padding) 3341*d289c2baSAndroid Build Coastguard Worker vbmeta_end_offset = vbmeta_offset + len(vbmeta_blob_with_padding) 3342*d289c2baSAndroid Build Coastguard Worker 3343*d289c2baSAndroid Build Coastguard Worker # Now insert a DONT_CARE chunk with enough bytes such that the 3344*d289c2baSAndroid Build Coastguard Worker # final Footer block is at the end of partition_size.. 3345*d289c2baSAndroid Build Coastguard Worker image.append_dont_care(partition_size - vbmeta_end_offset - 3346*d289c2baSAndroid Build Coastguard Worker 1 * image.block_size) 3347*d289c2baSAndroid Build Coastguard Worker 3348*d289c2baSAndroid Build Coastguard Worker # Generate the Footer that tells where the VBMeta footer 3349*d289c2baSAndroid Build Coastguard Worker # is. Also put enough padding in the front of the footer since 3350*d289c2baSAndroid Build Coastguard Worker # we'll write out an entire block. 3351*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter() 3352*d289c2baSAndroid Build Coastguard Worker footer.original_image_size = original_image_size 3353*d289c2baSAndroid Build Coastguard Worker footer.vbmeta_offset = vbmeta_offset 3354*d289c2baSAndroid Build Coastguard Worker footer.vbmeta_size = len(vbmeta_blob) 3355*d289c2baSAndroid Build Coastguard Worker footer_blob = footer.encode() 3356*d289c2baSAndroid Build Coastguard Worker footer_blob_with_padding = (b'\0' * (image.block_size - AvbFooter.SIZE) + 3357*d289c2baSAndroid Build Coastguard Worker footer_blob) 3358*d289c2baSAndroid Build Coastguard Worker image.append_raw(footer_blob_with_padding) 3359*d289c2baSAndroid Build Coastguard Worker 3360*d289c2baSAndroid Build Coastguard Worker except Exception as e: 3361*d289c2baSAndroid Build Coastguard Worker # Truncate back to original size, then re-raise. 3362*d289c2baSAndroid Build Coastguard Worker image.truncate(original_image_size) 3363*d289c2baSAndroid Build Coastguard Worker raise AvbError('Appending VBMeta image failed: {}.'.format(e)) from e 3364*d289c2baSAndroid Build Coastguard Worker 3365*d289c2baSAndroid Build Coastguard Worker def add_hash_footer(self, image_filename, partition_size, 3366*d289c2baSAndroid Build Coastguard Worker dynamic_partition_size, partition_name, 3367*d289c2baSAndroid Build Coastguard Worker hash_algorithm, salt, chain_partitions_use_ab, 3368*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab, 3369*d289c2baSAndroid Build Coastguard Worker algorithm_name, key_path, 3370*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path, rollback_index, flags, 3371*d289c2baSAndroid Build Coastguard Worker rollback_index_location, props, 3372*d289c2baSAndroid Build Coastguard Worker props_from_file, kernel_cmdlines, 3373*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel, 3374*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, calc_max_image_size, 3375*d289c2baSAndroid Build Coastguard Worker signing_helper, signing_helper_with_files, 3376*d289c2baSAndroid Build Coastguard Worker release_string, append_to_release_string, 3377*d289c2baSAndroid Build Coastguard Worker output_vbmeta_image, do_not_append_vbmeta_image, 3378*d289c2baSAndroid Build Coastguard Worker print_required_libavb_version, use_persistent_digest, 3379*d289c2baSAndroid Build Coastguard Worker do_not_use_ab): 3380*d289c2baSAndroid Build Coastguard Worker """Implementation of the add_hash_footer on unsparse images. 3381*d289c2baSAndroid Build Coastguard Worker 3382*d289c2baSAndroid Build Coastguard Worker Arguments: 3383*d289c2baSAndroid Build Coastguard Worker image_filename: File to add the footer to. 3384*d289c2baSAndroid Build Coastguard Worker partition_size: Size of partition. 3385*d289c2baSAndroid Build Coastguard Worker dynamic_partition_size: Calculate partition size based on image size. 3386*d289c2baSAndroid Build Coastguard Worker partition_name: Name of partition (without A/B suffix). 3387*d289c2baSAndroid Build Coastguard Worker hash_algorithm: Hash algorithm to use. 3388*d289c2baSAndroid Build Coastguard Worker salt: Salt to use as a hexadecimal string or None to use /dev/urandom. 3389*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab: List of partitions to chain with A/B or None. 3390*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab: List of partitions to chain without A/B or None. 3391*d289c2baSAndroid Build Coastguard Worker algorithm_name: Name of algorithm to use. 3392*d289c2baSAndroid Build Coastguard Worker key_path: Path to key to use or None. 3393*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path: Path to public key metadata or None. 3394*d289c2baSAndroid Build Coastguard Worker rollback_index: Rollback index. 3395*d289c2baSAndroid Build Coastguard Worker flags: Flags value to use in the image. 3396*d289c2baSAndroid Build Coastguard Worker rollback_index_location: Location of the main vbmeta rollback index. 3397*d289c2baSAndroid Build Coastguard Worker props: Properties to insert (List of strings of the form 'key:value'). 3398*d289c2baSAndroid Build Coastguard Worker props_from_file: Properties to insert (List of strings 'key:<path>'). 3399*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines: Kernel cmdlines to insert (list of strings). 3400*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel: None or file to generate 3401*d289c2baSAndroid Build Coastguard Worker dm-verity kernel cmdline from. 3402*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image: List of file objects for which 3403*d289c2baSAndroid Build Coastguard Worker to insert descriptors from. 3404*d289c2baSAndroid Build Coastguard Worker calc_max_image_size: Don't store the footer - instead calculate the 3405*d289c2baSAndroid Build Coastguard Worker maximum image size leaving enough room for metadata with the 3406*d289c2baSAndroid Build Coastguard Worker given |partition_size|. 3407*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and return signature. 3408*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 3409*d289c2baSAndroid Build Coastguard Worker release_string: None or avbtool release string. 3410*d289c2baSAndroid Build Coastguard Worker append_to_release_string: None or string to append. 3411*d289c2baSAndroid Build Coastguard Worker output_vbmeta_image: If not None, also write vbmeta struct to this file. 3412*d289c2baSAndroid Build Coastguard Worker do_not_append_vbmeta_image: If True, don't append vbmeta struct. 3413*d289c2baSAndroid Build Coastguard Worker print_required_libavb_version: True to only print required libavb version. 3414*d289c2baSAndroid Build Coastguard Worker use_persistent_digest: Use a persistent digest on device. 3415*d289c2baSAndroid Build Coastguard Worker do_not_use_ab: This partition does not use A/B. 3416*d289c2baSAndroid Build Coastguard Worker 3417*d289c2baSAndroid Build Coastguard Worker Raises: 3418*d289c2baSAndroid Build Coastguard Worker AvbError: If an argument is incorrect of if adding of hash_footer failed. 3419*d289c2baSAndroid Build Coastguard Worker """ 3420*d289c2baSAndroid Build Coastguard Worker if not partition_size and not dynamic_partition_size: 3421*d289c2baSAndroid Build Coastguard Worker raise AvbError('--dynamic_partition_size required when not specifying a ' 3422*d289c2baSAndroid Build Coastguard Worker 'partition size') 3423*d289c2baSAndroid Build Coastguard Worker 3424*d289c2baSAndroid Build Coastguard Worker if dynamic_partition_size and calc_max_image_size: 3425*d289c2baSAndroid Build Coastguard Worker raise AvbError('--calc_max_image_size not supported with ' 3426*d289c2baSAndroid Build Coastguard Worker '--dynamic_partition_size') 3427*d289c2baSAndroid Build Coastguard Worker 3428*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 0 3429*d289c2baSAndroid Build Coastguard Worker if use_persistent_digest or do_not_use_ab: 3430*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 1 3431*d289c2baSAndroid Build Coastguard Worker if rollback_index_location > 0: 3432*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 2 3433*d289c2baSAndroid Build Coastguard Worker if chain_partitions_do_not_use_ab: 3434*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 3 3435*d289c2baSAndroid Build Coastguard Worker 3436*d289c2baSAndroid Build Coastguard Worker # If we're asked to calculate minimum required libavb version, we're done. 3437*d289c2baSAndroid Build Coastguard Worker if print_required_libavb_version: 3438*d289c2baSAndroid Build Coastguard Worker print('1.{}'.format(required_libavb_version_minor)) 3439*d289c2baSAndroid Build Coastguard Worker return 3440*d289c2baSAndroid Build Coastguard Worker 3441*d289c2baSAndroid Build Coastguard Worker # First, calculate the maximum image size such that an image 3442*d289c2baSAndroid Build Coastguard Worker # this size + metadata (footer + vbmeta struct) fits in 3443*d289c2baSAndroid Build Coastguard Worker # |partition_size|. 3444*d289c2baSAndroid Build Coastguard Worker max_metadata_size = self.MAX_VBMETA_SIZE + self.MAX_FOOTER_SIZE 3445*d289c2baSAndroid Build Coastguard Worker if not dynamic_partition_size and partition_size < max_metadata_size: 3446*d289c2baSAndroid Build Coastguard Worker raise AvbError('Parition size of {} is too small. ' 3447*d289c2baSAndroid Build Coastguard Worker 'Needs to be at least {}'.format( 3448*d289c2baSAndroid Build Coastguard Worker partition_size, max_metadata_size)) 3449*d289c2baSAndroid Build Coastguard Worker 3450*d289c2baSAndroid Build Coastguard Worker # If we're asked to only calculate the maximum image size, we're done. 3451*d289c2baSAndroid Build Coastguard Worker if calc_max_image_size: 3452*d289c2baSAndroid Build Coastguard Worker print('{}'.format(partition_size - max_metadata_size)) 3453*d289c2baSAndroid Build Coastguard Worker return 3454*d289c2baSAndroid Build Coastguard Worker 3455*d289c2baSAndroid Build Coastguard Worker # If we aren't appending the vbmeta footer to the input image we can 3456*d289c2baSAndroid Build Coastguard Worker # open it in read-only mode. 3457*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename, 3458*d289c2baSAndroid Build Coastguard Worker read_only=do_not_append_vbmeta_image) 3459*d289c2baSAndroid Build Coastguard Worker 3460*d289c2baSAndroid Build Coastguard Worker # If there's already a footer, truncate the image to its original 3461*d289c2baSAndroid Build Coastguard Worker # size. This way 'avbtool add_hash_footer' is idempotent (modulo 3462*d289c2baSAndroid Build Coastguard Worker # salts). 3463*d289c2baSAndroid Build Coastguard Worker if image.image_size >= AvbFooter.SIZE: 3464*d289c2baSAndroid Build Coastguard Worker image.seek(image.image_size - AvbFooter.SIZE) 3465*d289c2baSAndroid Build Coastguard Worker try: 3466*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter(image.read(AvbFooter.SIZE)) 3467*d289c2baSAndroid Build Coastguard Worker # Existing footer found. Just truncate. 3468*d289c2baSAndroid Build Coastguard Worker original_image_size = footer.original_image_size 3469*d289c2baSAndroid Build Coastguard Worker image.truncate(footer.original_image_size) 3470*d289c2baSAndroid Build Coastguard Worker except (LookupError, struct.error): 3471*d289c2baSAndroid Build Coastguard Worker original_image_size = image.image_size 3472*d289c2baSAndroid Build Coastguard Worker else: 3473*d289c2baSAndroid Build Coastguard Worker # Image size is too small to possibly contain a footer. 3474*d289c2baSAndroid Build Coastguard Worker original_image_size = image.image_size 3475*d289c2baSAndroid Build Coastguard Worker 3476*d289c2baSAndroid Build Coastguard Worker if dynamic_partition_size: 3477*d289c2baSAndroid Build Coastguard Worker partition_size = round_to_multiple( 3478*d289c2baSAndroid Build Coastguard Worker original_image_size + max_metadata_size, image.block_size) 3479*d289c2baSAndroid Build Coastguard Worker 3480*d289c2baSAndroid Build Coastguard Worker max_image_size = partition_size - max_metadata_size 3481*d289c2baSAndroid Build Coastguard Worker if partition_size % image.block_size != 0: 3482*d289c2baSAndroid Build Coastguard Worker raise AvbError('Partition size of {} is not a multiple of the image ' 3483*d289c2baSAndroid Build Coastguard Worker 'block size {}.'.format(partition_size, 3484*d289c2baSAndroid Build Coastguard Worker image.block_size)) 3485*d289c2baSAndroid Build Coastguard Worker 3486*d289c2baSAndroid Build Coastguard Worker # If anything goes wrong from here-on, restore the image back to 3487*d289c2baSAndroid Build Coastguard Worker # its original size. 3488*d289c2baSAndroid Build Coastguard Worker try: 3489*d289c2baSAndroid Build Coastguard Worker # If image size exceeds the maximum image size, fail. 3490*d289c2baSAndroid Build Coastguard Worker if image.image_size > max_image_size: 3491*d289c2baSAndroid Build Coastguard Worker raise AvbError('Image size of {} exceeds maximum image ' 3492*d289c2baSAndroid Build Coastguard Worker 'size of {} in order to fit in a partition ' 3493*d289c2baSAndroid Build Coastguard Worker 'size of {}.'.format(image.image_size, max_image_size, 3494*d289c2baSAndroid Build Coastguard Worker partition_size)) 3495*d289c2baSAndroid Build Coastguard Worker 3496*d289c2baSAndroid Build Coastguard Worker digest_size = len(hashlib.new(hash_algorithm).digest()) 3497*d289c2baSAndroid Build Coastguard Worker if salt: 3498*d289c2baSAndroid Build Coastguard Worker salt = binascii.unhexlify(salt) 3499*d289c2baSAndroid Build Coastguard Worker elif salt is None and not use_persistent_digest: 3500*d289c2baSAndroid Build Coastguard Worker # If salt is not explicitly specified, choose a hash that's the same 3501*d289c2baSAndroid Build Coastguard Worker # size as the hash size. Don't populate a random salt if this 3502*d289c2baSAndroid Build Coastguard Worker # descriptor is being created to use a persistent digest on device. 3503*d289c2baSAndroid Build Coastguard Worker hash_size = digest_size 3504*d289c2baSAndroid Build Coastguard Worker with open('/dev/urandom', 'rb') as f: 3505*d289c2baSAndroid Build Coastguard Worker salt = f.read(hash_size) 3506*d289c2baSAndroid Build Coastguard Worker else: 3507*d289c2baSAndroid Build Coastguard Worker salt = b'' 3508*d289c2baSAndroid Build Coastguard Worker 3509*d289c2baSAndroid Build Coastguard Worker hasher = hashlib.new(hash_algorithm, salt) 3510*d289c2baSAndroid Build Coastguard Worker # TODO(zeuthen): might want to read this in chunks to avoid 3511*d289c2baSAndroid Build Coastguard Worker # memory pressure, then again, this is only supposed to be used 3512*d289c2baSAndroid Build Coastguard Worker # on kernel/initramfs partitions. Possible optimization. 3513*d289c2baSAndroid Build Coastguard Worker image.seek(0) 3514*d289c2baSAndroid Build Coastguard Worker hasher.update(image.read(image.image_size)) 3515*d289c2baSAndroid Build Coastguard Worker digest = hasher.digest() 3516*d289c2baSAndroid Build Coastguard Worker 3517*d289c2baSAndroid Build Coastguard Worker h_desc = AvbHashDescriptor() 3518*d289c2baSAndroid Build Coastguard Worker h_desc.image_size = image.image_size 3519*d289c2baSAndroid Build Coastguard Worker h_desc.hash_algorithm = hash_algorithm 3520*d289c2baSAndroid Build Coastguard Worker h_desc.partition_name = partition_name 3521*d289c2baSAndroid Build Coastguard Worker h_desc.salt = salt 3522*d289c2baSAndroid Build Coastguard Worker h_desc.flags = 0 3523*d289c2baSAndroid Build Coastguard Worker if do_not_use_ab: 3524*d289c2baSAndroid Build Coastguard Worker h_desc.flags |= 1 # AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB 3525*d289c2baSAndroid Build Coastguard Worker if not use_persistent_digest: 3526*d289c2baSAndroid Build Coastguard Worker h_desc.digest = digest 3527*d289c2baSAndroid Build Coastguard Worker 3528*d289c2baSAndroid Build Coastguard Worker # Generate the VBMeta footer. 3529*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup = None 3530*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = self._generate_vbmeta_blob( 3531*d289c2baSAndroid Build Coastguard Worker algorithm_name, key_path, public_key_metadata_path, [h_desc], 3532*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab, chain_partitions_do_not_use_ab, rollback_index, 3533*d289c2baSAndroid Build Coastguard Worker flags, rollback_index_location, props, props_from_file, 3534*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines, setup_rootfs_from_kernel, ht_desc_to_setup, 3535*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, signing_helper, 3536*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files, release_string, 3537*d289c2baSAndroid Build Coastguard Worker append_to_release_string, required_libavb_version_minor) 3538*d289c2baSAndroid Build Coastguard Worker 3539*d289c2baSAndroid Build Coastguard Worker # Write vbmeta blob, if requested. 3540*d289c2baSAndroid Build Coastguard Worker if output_vbmeta_image: 3541*d289c2baSAndroid Build Coastguard Worker output_vbmeta_image.write(vbmeta_blob) 3542*d289c2baSAndroid Build Coastguard Worker 3543*d289c2baSAndroid Build Coastguard Worker # Append vbmeta blob and footer, unless requested not to. 3544*d289c2baSAndroid Build Coastguard Worker if not do_not_append_vbmeta_image: 3545*d289c2baSAndroid Build Coastguard Worker # If the image isn't sparse, its size might not be a multiple of 3546*d289c2baSAndroid Build Coastguard Worker # the block size. This will screw up padding later so just grow it. 3547*d289c2baSAndroid Build Coastguard Worker if image.image_size % image.block_size != 0: 3548*d289c2baSAndroid Build Coastguard Worker assert not image.is_sparse 3549*d289c2baSAndroid Build Coastguard Worker padding_needed = image.block_size - ( 3550*d289c2baSAndroid Build Coastguard Worker image.image_size % image.block_size) 3551*d289c2baSAndroid Build Coastguard Worker image.truncate(image.image_size + padding_needed) 3552*d289c2baSAndroid Build Coastguard Worker 3553*d289c2baSAndroid Build Coastguard Worker # The append_raw() method requires content with size being a 3554*d289c2baSAndroid Build Coastguard Worker # multiple of |block_size| so add padding as needed. Also record 3555*d289c2baSAndroid Build Coastguard Worker # where this is written to since we'll need to put that in the 3556*d289c2baSAndroid Build Coastguard Worker # footer. 3557*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = image.image_size 3558*d289c2baSAndroid Build Coastguard Worker padding_needed = ( 3559*d289c2baSAndroid Build Coastguard Worker round_to_multiple(len(vbmeta_blob), image.block_size) - 3560*d289c2baSAndroid Build Coastguard Worker len(vbmeta_blob)) 3561*d289c2baSAndroid Build Coastguard Worker vbmeta_blob_with_padding = vbmeta_blob + b'\0' * padding_needed 3562*d289c2baSAndroid Build Coastguard Worker 3563*d289c2baSAndroid Build Coastguard Worker image.append_raw(vbmeta_blob_with_padding) 3564*d289c2baSAndroid Build Coastguard Worker vbmeta_end_offset = vbmeta_offset + len(vbmeta_blob_with_padding) 3565*d289c2baSAndroid Build Coastguard Worker 3566*d289c2baSAndroid Build Coastguard Worker # Now insert a DONT_CARE chunk with enough bytes such that the 3567*d289c2baSAndroid Build Coastguard Worker # final Footer block is at the end of partition_size.. 3568*d289c2baSAndroid Build Coastguard Worker image.append_dont_care(partition_size - vbmeta_end_offset - 3569*d289c2baSAndroid Build Coastguard Worker 1 * image.block_size) 3570*d289c2baSAndroid Build Coastguard Worker 3571*d289c2baSAndroid Build Coastguard Worker # Generate the Footer that tells where the VBMeta footer 3572*d289c2baSAndroid Build Coastguard Worker # is. Also put enough padding in the front of the footer since 3573*d289c2baSAndroid Build Coastguard Worker # we'll write out an entire block. 3574*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter() 3575*d289c2baSAndroid Build Coastguard Worker footer.original_image_size = original_image_size 3576*d289c2baSAndroid Build Coastguard Worker footer.vbmeta_offset = vbmeta_offset 3577*d289c2baSAndroid Build Coastguard Worker footer.vbmeta_size = len(vbmeta_blob) 3578*d289c2baSAndroid Build Coastguard Worker footer_blob = footer.encode() 3579*d289c2baSAndroid Build Coastguard Worker footer_blob_with_padding = ( 3580*d289c2baSAndroid Build Coastguard Worker b'\0' * (image.block_size - AvbFooter.SIZE) + footer_blob) 3581*d289c2baSAndroid Build Coastguard Worker image.append_raw(footer_blob_with_padding) 3582*d289c2baSAndroid Build Coastguard Worker except Exception as e: 3583*d289c2baSAndroid Build Coastguard Worker # Truncate back to original size, then re-raise. 3584*d289c2baSAndroid Build Coastguard Worker image.truncate(original_image_size) 3585*d289c2baSAndroid Build Coastguard Worker raise AvbError('Adding hash_footer failed: {}.'.format(e)) from e 3586*d289c2baSAndroid Build Coastguard Worker 3587*d289c2baSAndroid Build Coastguard Worker def add_hashtree_footer(self, image_filename, partition_size, partition_name, 3588*d289c2baSAndroid Build Coastguard Worker generate_fec, fec_num_roots, hash_algorithm, 3589*d289c2baSAndroid Build Coastguard Worker block_size, salt, chain_partitions_use_ab, 3590*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab, 3591*d289c2baSAndroid Build Coastguard Worker algorithm_name, key_path, 3592*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path, rollback_index, flags, 3593*d289c2baSAndroid Build Coastguard Worker rollback_index_location, 3594*d289c2baSAndroid Build Coastguard Worker props, props_from_file, kernel_cmdlines, 3595*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel, 3596*d289c2baSAndroid Build Coastguard Worker setup_as_rootfs_from_kernel, 3597*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, 3598*d289c2baSAndroid Build Coastguard Worker calc_max_image_size, signing_helper, 3599*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files, 3600*d289c2baSAndroid Build Coastguard Worker release_string, append_to_release_string, 3601*d289c2baSAndroid Build Coastguard Worker output_vbmeta_image, do_not_append_vbmeta_image, 3602*d289c2baSAndroid Build Coastguard Worker print_required_libavb_version, 3603*d289c2baSAndroid Build Coastguard Worker use_persistent_root_digest, do_not_use_ab, 3604*d289c2baSAndroid Build Coastguard Worker no_hashtree, check_at_most_once): 3605*d289c2baSAndroid Build Coastguard Worker """Implements the 'add_hashtree_footer' command. 3606*d289c2baSAndroid Build Coastguard Worker 3607*d289c2baSAndroid Build Coastguard Worker See https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for 3608*d289c2baSAndroid Build Coastguard Worker more information about dm-verity and these hashes. 3609*d289c2baSAndroid Build Coastguard Worker 3610*d289c2baSAndroid Build Coastguard Worker Arguments: 3611*d289c2baSAndroid Build Coastguard Worker image_filename: File to add the footer to. 3612*d289c2baSAndroid Build Coastguard Worker partition_size: Size of partition or 0 to put it right at the end. 3613*d289c2baSAndroid Build Coastguard Worker partition_name: Name of partition (without A/B suffix). 3614*d289c2baSAndroid Build Coastguard Worker generate_fec: If True, generate FEC codes. 3615*d289c2baSAndroid Build Coastguard Worker fec_num_roots: Number of roots for FEC. 3616*d289c2baSAndroid Build Coastguard Worker hash_algorithm: Hash algorithm to use. 3617*d289c2baSAndroid Build Coastguard Worker block_size: Block size to use. 3618*d289c2baSAndroid Build Coastguard Worker salt: Salt to use as a hexadecimal string or None to use /dev/urandom. 3619*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab: List of partitions to chain. 3620*d289c2baSAndroid Build Coastguard Worker chain_partitions_do_not_use_ab: List of partitions to chain without A/B or None. 3621*d289c2baSAndroid Build Coastguard Worker algorithm_name: Name of algorithm to use. 3622*d289c2baSAndroid Build Coastguard Worker key_path: Path to key to use or None. 3623*d289c2baSAndroid Build Coastguard Worker public_key_metadata_path: Path to public key metadata or None. 3624*d289c2baSAndroid Build Coastguard Worker rollback_index: Rollback index. 3625*d289c2baSAndroid Build Coastguard Worker flags: Flags value to use in the image. 3626*d289c2baSAndroid Build Coastguard Worker rollback_index_location: Location of the main vbmeta rollback index. 3627*d289c2baSAndroid Build Coastguard Worker props: Properties to insert (List of strings of the form 'key:value'). 3628*d289c2baSAndroid Build Coastguard Worker props_from_file: Properties to insert (List of strings 'key:<path>'). 3629*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines: Kernel cmdlines to insert (list of strings). 3630*d289c2baSAndroid Build Coastguard Worker setup_rootfs_from_kernel: None or file to generate 3631*d289c2baSAndroid Build Coastguard Worker dm-verity kernel cmdline from. 3632*d289c2baSAndroid Build Coastguard Worker setup_as_rootfs_from_kernel: If True, generate dm-verity kernel 3633*d289c2baSAndroid Build Coastguard Worker cmdline to set up rootfs. 3634*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image: List of file objects for which 3635*d289c2baSAndroid Build Coastguard Worker to insert descriptors from. 3636*d289c2baSAndroid Build Coastguard Worker calc_max_image_size: Don't store the hashtree or footer - instead 3637*d289c2baSAndroid Build Coastguard Worker calculate the maximum image size leaving enough room for hashtree 3638*d289c2baSAndroid Build Coastguard Worker and metadata with the given |partition_size|. 3639*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and return signature. 3640*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 3641*d289c2baSAndroid Build Coastguard Worker release_string: None or avbtool release string. 3642*d289c2baSAndroid Build Coastguard Worker append_to_release_string: None or string to append. 3643*d289c2baSAndroid Build Coastguard Worker output_vbmeta_image: If not None, also write vbmeta struct to this file. 3644*d289c2baSAndroid Build Coastguard Worker do_not_append_vbmeta_image: If True, don't append vbmeta struct. 3645*d289c2baSAndroid Build Coastguard Worker print_required_libavb_version: True to only print required libavb version. 3646*d289c2baSAndroid Build Coastguard Worker use_persistent_root_digest: Use a persistent root digest on device. 3647*d289c2baSAndroid Build Coastguard Worker do_not_use_ab: The partition does not use A/B. 3648*d289c2baSAndroid Build Coastguard Worker no_hashtree: Do not append hashtree. Set size in descriptor as zero. 3649*d289c2baSAndroid Build Coastguard Worker check_at_most_once: Set to verify data blocks only the first time they 3650*d289c2baSAndroid Build Coastguard Worker are read from the data device. 3651*d289c2baSAndroid Build Coastguard Worker 3652*d289c2baSAndroid Build Coastguard Worker Raises: 3653*d289c2baSAndroid Build Coastguard Worker AvbError: If an argument is incorrect or adding the hashtree footer 3654*d289c2baSAndroid Build Coastguard Worker failed. 3655*d289c2baSAndroid Build Coastguard Worker """ 3656*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 0 3657*d289c2baSAndroid Build Coastguard Worker if use_persistent_root_digest or do_not_use_ab or check_at_most_once: 3658*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 1 3659*d289c2baSAndroid Build Coastguard Worker if rollback_index_location > 0: 3660*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 2 3661*d289c2baSAndroid Build Coastguard Worker if chain_partitions_do_not_use_ab: 3662*d289c2baSAndroid Build Coastguard Worker required_libavb_version_minor = 3 3663*d289c2baSAndroid Build Coastguard Worker 3664*d289c2baSAndroid Build Coastguard Worker # If we're asked to calculate minimum required libavb version, we're done. 3665*d289c2baSAndroid Build Coastguard Worker if print_required_libavb_version: 3666*d289c2baSAndroid Build Coastguard Worker print('1.{}'.format(required_libavb_version_minor)) 3667*d289c2baSAndroid Build Coastguard Worker return 3668*d289c2baSAndroid Build Coastguard Worker 3669*d289c2baSAndroid Build Coastguard Worker digest_size = len(create_avb_hashtree_hasher(hash_algorithm, b'') 3670*d289c2baSAndroid Build Coastguard Worker .digest()) 3671*d289c2baSAndroid Build Coastguard Worker digest_padding = round_to_pow2(digest_size) - digest_size 3672*d289c2baSAndroid Build Coastguard Worker 3673*d289c2baSAndroid Build Coastguard Worker # If |partition_size| is given (e.g. not 0), calculate the maximum image 3674*d289c2baSAndroid Build Coastguard Worker # size such that an image this size + the hashtree + metadata (footer + 3675*d289c2baSAndroid Build Coastguard Worker # vbmeta struct) fits in |partition_size|. We use very conservative figures 3676*d289c2baSAndroid Build Coastguard Worker # for metadata. 3677*d289c2baSAndroid Build Coastguard Worker if partition_size > 0: 3678*d289c2baSAndroid Build Coastguard Worker max_tree_size = 0 3679*d289c2baSAndroid Build Coastguard Worker max_fec_size = 0 3680*d289c2baSAndroid Build Coastguard Worker if not no_hashtree: 3681*d289c2baSAndroid Build Coastguard Worker (_, max_tree_size) = calc_hash_level_offsets( 3682*d289c2baSAndroid Build Coastguard Worker partition_size, block_size, digest_size + digest_padding) 3683*d289c2baSAndroid Build Coastguard Worker if generate_fec: 3684*d289c2baSAndroid Build Coastguard Worker max_fec_size = calc_fec_data_size(partition_size, fec_num_roots) 3685*d289c2baSAndroid Build Coastguard Worker max_metadata_size = (max_fec_size + max_tree_size + 3686*d289c2baSAndroid Build Coastguard Worker self.MAX_VBMETA_SIZE + 3687*d289c2baSAndroid Build Coastguard Worker self.MAX_FOOTER_SIZE) 3688*d289c2baSAndroid Build Coastguard Worker max_image_size = partition_size - max_metadata_size 3689*d289c2baSAndroid Build Coastguard Worker else: 3690*d289c2baSAndroid Build Coastguard Worker max_image_size = 0 3691*d289c2baSAndroid Build Coastguard Worker 3692*d289c2baSAndroid Build Coastguard Worker # If we're asked to only calculate the maximum image size, we're done. 3693*d289c2baSAndroid Build Coastguard Worker if calc_max_image_size: 3694*d289c2baSAndroid Build Coastguard Worker print('{}'.format(max_image_size)) 3695*d289c2baSAndroid Build Coastguard Worker return 3696*d289c2baSAndroid Build Coastguard Worker 3697*d289c2baSAndroid Build Coastguard Worker image = ImageHandler(image_filename) 3698*d289c2baSAndroid Build Coastguard Worker 3699*d289c2baSAndroid Build Coastguard Worker if partition_size > 0: 3700*d289c2baSAndroid Build Coastguard Worker if partition_size % image.block_size != 0: 3701*d289c2baSAndroid Build Coastguard Worker raise AvbError('Partition size of {} is not a multiple of the image ' 3702*d289c2baSAndroid Build Coastguard Worker 'block size {}.'.format(partition_size, 3703*d289c2baSAndroid Build Coastguard Worker image.block_size)) 3704*d289c2baSAndroid Build Coastguard Worker elif image.image_size % image.block_size != 0: 3705*d289c2baSAndroid Build Coastguard Worker raise AvbError('File size of {} is not a multiple of the image ' 3706*d289c2baSAndroid Build Coastguard Worker 'block size {}.'.format(image.image_size, 3707*d289c2baSAndroid Build Coastguard Worker image.block_size)) 3708*d289c2baSAndroid Build Coastguard Worker 3709*d289c2baSAndroid Build Coastguard Worker # If there's already a footer, truncate the image to its original 3710*d289c2baSAndroid Build Coastguard Worker # size. This way 'avbtool add_hashtree_footer' is idempotent 3711*d289c2baSAndroid Build Coastguard Worker # (modulo salts). 3712*d289c2baSAndroid Build Coastguard Worker if image.image_size >= AvbFooter.SIZE: 3713*d289c2baSAndroid Build Coastguard Worker image.seek(image.image_size - AvbFooter.SIZE) 3714*d289c2baSAndroid Build Coastguard Worker try: 3715*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter(image.read(AvbFooter.SIZE)) 3716*d289c2baSAndroid Build Coastguard Worker # Existing footer found. Just truncate. 3717*d289c2baSAndroid Build Coastguard Worker original_image_size = footer.original_image_size 3718*d289c2baSAndroid Build Coastguard Worker image.truncate(footer.original_image_size) 3719*d289c2baSAndroid Build Coastguard Worker except (LookupError, struct.error): 3720*d289c2baSAndroid Build Coastguard Worker original_image_size = image.image_size 3721*d289c2baSAndroid Build Coastguard Worker else: 3722*d289c2baSAndroid Build Coastguard Worker # Image size is too small to possibly contain a footer. 3723*d289c2baSAndroid Build Coastguard Worker original_image_size = image.image_size 3724*d289c2baSAndroid Build Coastguard Worker 3725*d289c2baSAndroid Build Coastguard Worker # If anything goes wrong from here-on, restore the image back to 3726*d289c2baSAndroid Build Coastguard Worker # its original size. 3727*d289c2baSAndroid Build Coastguard Worker try: 3728*d289c2baSAndroid Build Coastguard Worker # Ensure image is multiple of block_size. 3729*d289c2baSAndroid Build Coastguard Worker rounded_image_size = round_to_multiple(image.image_size, block_size) 3730*d289c2baSAndroid Build Coastguard Worker if rounded_image_size > image.image_size: 3731*d289c2baSAndroid Build Coastguard Worker # If we need to round up the image size, it means the length of the 3732*d289c2baSAndroid Build Coastguard Worker # data to append is not a multiple of block size. 3733*d289c2baSAndroid Build Coastguard Worker # Setting multiple_block_size to false, so append_raw() will not 3734*d289c2baSAndroid Build Coastguard Worker # require it. 3735*d289c2baSAndroid Build Coastguard Worker image.append_raw(b'\0' * (rounded_image_size - image.image_size), 3736*d289c2baSAndroid Build Coastguard Worker multiple_block_size=False) 3737*d289c2baSAndroid Build Coastguard Worker 3738*d289c2baSAndroid Build Coastguard Worker # If image size exceeds the maximum image size, fail. 3739*d289c2baSAndroid Build Coastguard Worker if partition_size > 0: 3740*d289c2baSAndroid Build Coastguard Worker if image.image_size > max_image_size: 3741*d289c2baSAndroid Build Coastguard Worker raise AvbError('Image size of {} exceeds maximum image ' 3742*d289c2baSAndroid Build Coastguard Worker 'size of {} in order to fit in a partition ' 3743*d289c2baSAndroid Build Coastguard Worker 'size of {}.'.format(image.image_size, max_image_size, 3744*d289c2baSAndroid Build Coastguard Worker partition_size)) 3745*d289c2baSAndroid Build Coastguard Worker 3746*d289c2baSAndroid Build Coastguard Worker if salt: 3747*d289c2baSAndroid Build Coastguard Worker salt = binascii.unhexlify(salt) 3748*d289c2baSAndroid Build Coastguard Worker elif salt is None and not use_persistent_root_digest: 3749*d289c2baSAndroid Build Coastguard Worker # If salt is not explicitly specified, choose a hash that's the same 3750*d289c2baSAndroid Build Coastguard Worker # size as the hash size. Don't populate a random salt if this 3751*d289c2baSAndroid Build Coastguard Worker # descriptor is being created to use a persistent digest on device. 3752*d289c2baSAndroid Build Coastguard Worker hash_size = digest_size 3753*d289c2baSAndroid Build Coastguard Worker with open('/dev/urandom', 'rb') as f: 3754*d289c2baSAndroid Build Coastguard Worker salt = f.read(hash_size) 3755*d289c2baSAndroid Build Coastguard Worker else: 3756*d289c2baSAndroid Build Coastguard Worker salt = b'' 3757*d289c2baSAndroid Build Coastguard Worker 3758*d289c2baSAndroid Build Coastguard Worker # Hashes are stored upside down so we need to calculate hash 3759*d289c2baSAndroid Build Coastguard Worker # offsets in advance. 3760*d289c2baSAndroid Build Coastguard Worker (hash_level_offsets, tree_size) = calc_hash_level_offsets( 3761*d289c2baSAndroid Build Coastguard Worker image.image_size, block_size, digest_size + digest_padding) 3762*d289c2baSAndroid Build Coastguard Worker 3763*d289c2baSAndroid Build Coastguard Worker # If the image isn't sparse, its size might not be a multiple of 3764*d289c2baSAndroid Build Coastguard Worker # the block size. This will screw up padding later so just grow it. 3765*d289c2baSAndroid Build Coastguard Worker if image.image_size % image.block_size != 0: 3766*d289c2baSAndroid Build Coastguard Worker assert not image.is_sparse 3767*d289c2baSAndroid Build Coastguard Worker padding_needed = image.block_size - (image.image_size%image.block_size) 3768*d289c2baSAndroid Build Coastguard Worker image.truncate(image.image_size + padding_needed) 3769*d289c2baSAndroid Build Coastguard Worker 3770*d289c2baSAndroid Build Coastguard Worker # Generate the tree and add padding as needed. 3771*d289c2baSAndroid Build Coastguard Worker tree_offset = image.image_size 3772*d289c2baSAndroid Build Coastguard Worker root_digest, hash_tree = generate_hash_tree(image, image.image_size, 3773*d289c2baSAndroid Build Coastguard Worker block_size, 3774*d289c2baSAndroid Build Coastguard Worker hash_algorithm, salt, 3775*d289c2baSAndroid Build Coastguard Worker digest_padding, 3776*d289c2baSAndroid Build Coastguard Worker hash_level_offsets, 3777*d289c2baSAndroid Build Coastguard Worker tree_size) 3778*d289c2baSAndroid Build Coastguard Worker 3779*d289c2baSAndroid Build Coastguard Worker # Generate HashtreeDescriptor with details about the tree we 3780*d289c2baSAndroid Build Coastguard Worker # just generated. 3781*d289c2baSAndroid Build Coastguard Worker if no_hashtree: 3782*d289c2baSAndroid Build Coastguard Worker tree_size = 0 3783*d289c2baSAndroid Build Coastguard Worker hash_tree = b'' 3784*d289c2baSAndroid Build Coastguard Worker ht_desc = AvbHashtreeDescriptor() 3785*d289c2baSAndroid Build Coastguard Worker ht_desc.dm_verity_version = 1 3786*d289c2baSAndroid Build Coastguard Worker ht_desc.image_size = image.image_size 3787*d289c2baSAndroid Build Coastguard Worker ht_desc.tree_offset = tree_offset 3788*d289c2baSAndroid Build Coastguard Worker ht_desc.tree_size = tree_size 3789*d289c2baSAndroid Build Coastguard Worker ht_desc.data_block_size = block_size 3790*d289c2baSAndroid Build Coastguard Worker ht_desc.hash_block_size = block_size 3791*d289c2baSAndroid Build Coastguard Worker ht_desc.hash_algorithm = hash_algorithm 3792*d289c2baSAndroid Build Coastguard Worker ht_desc.partition_name = partition_name 3793*d289c2baSAndroid Build Coastguard Worker ht_desc.salt = salt 3794*d289c2baSAndroid Build Coastguard Worker if do_not_use_ab: 3795*d289c2baSAndroid Build Coastguard Worker ht_desc.flags |= AvbHashtreeDescriptor.FLAGS_DO_NOT_USE_AB 3796*d289c2baSAndroid Build Coastguard Worker if not use_persistent_root_digest: 3797*d289c2baSAndroid Build Coastguard Worker ht_desc.root_digest = root_digest 3798*d289c2baSAndroid Build Coastguard Worker if check_at_most_once: 3799*d289c2baSAndroid Build Coastguard Worker ht_desc.flags |= AvbHashtreeDescriptor.FLAGS_CHECK_AT_MOST_ONCE 3800*d289c2baSAndroid Build Coastguard Worker 3801*d289c2baSAndroid Build Coastguard Worker # Write the hash tree 3802*d289c2baSAndroid Build Coastguard Worker padding_needed = (round_to_multiple(len(hash_tree), image.block_size) - 3803*d289c2baSAndroid Build Coastguard Worker len(hash_tree)) 3804*d289c2baSAndroid Build Coastguard Worker hash_tree_with_padding = hash_tree + b'\0' * padding_needed 3805*d289c2baSAndroid Build Coastguard Worker if len(hash_tree_with_padding) > 0: 3806*d289c2baSAndroid Build Coastguard Worker image.append_raw(hash_tree_with_padding) 3807*d289c2baSAndroid Build Coastguard Worker len_hashtree_and_fec = len(hash_tree_with_padding) 3808*d289c2baSAndroid Build Coastguard Worker 3809*d289c2baSAndroid Build Coastguard Worker # Generate FEC codes, if requested. 3810*d289c2baSAndroid Build Coastguard Worker if generate_fec: 3811*d289c2baSAndroid Build Coastguard Worker if no_hashtree: 3812*d289c2baSAndroid Build Coastguard Worker fec_data = b'' 3813*d289c2baSAndroid Build Coastguard Worker else: 3814*d289c2baSAndroid Build Coastguard Worker fec_data = generate_fec_data(image_filename, fec_num_roots) 3815*d289c2baSAndroid Build Coastguard Worker padding_needed = (round_to_multiple(len(fec_data), image.block_size) - 3816*d289c2baSAndroid Build Coastguard Worker len(fec_data)) 3817*d289c2baSAndroid Build Coastguard Worker fec_data_with_padding = fec_data + b'\0' * padding_needed 3818*d289c2baSAndroid Build Coastguard Worker fec_offset = image.image_size 3819*d289c2baSAndroid Build Coastguard Worker image.append_raw(fec_data_with_padding) 3820*d289c2baSAndroid Build Coastguard Worker len_hashtree_and_fec += len(fec_data_with_padding) 3821*d289c2baSAndroid Build Coastguard Worker # Update the hashtree descriptor. 3822*d289c2baSAndroid Build Coastguard Worker ht_desc.fec_num_roots = fec_num_roots 3823*d289c2baSAndroid Build Coastguard Worker ht_desc.fec_offset = fec_offset 3824*d289c2baSAndroid Build Coastguard Worker ht_desc.fec_size = len(fec_data) 3825*d289c2baSAndroid Build Coastguard Worker 3826*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup = None 3827*d289c2baSAndroid Build Coastguard Worker if setup_as_rootfs_from_kernel: 3828*d289c2baSAndroid Build Coastguard Worker ht_desc_to_setup = ht_desc 3829*d289c2baSAndroid Build Coastguard Worker 3830*d289c2baSAndroid Build Coastguard Worker # Generate the VBMeta footer and add padding as needed. 3831*d289c2baSAndroid Build Coastguard Worker vbmeta_offset = tree_offset + len_hashtree_and_fec 3832*d289c2baSAndroid Build Coastguard Worker vbmeta_blob = self._generate_vbmeta_blob( 3833*d289c2baSAndroid Build Coastguard Worker algorithm_name, key_path, public_key_metadata_path, [ht_desc], 3834*d289c2baSAndroid Build Coastguard Worker chain_partitions_use_ab, chain_partitions_do_not_use_ab, 3835*d289c2baSAndroid Build Coastguard Worker rollback_index, flags, rollback_index_location, 3836*d289c2baSAndroid Build Coastguard Worker props, props_from_file, 3837*d289c2baSAndroid Build Coastguard Worker kernel_cmdlines, setup_rootfs_from_kernel, ht_desc_to_setup, 3838*d289c2baSAndroid Build Coastguard Worker include_descriptors_from_image, signing_helper, 3839*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files, release_string, 3840*d289c2baSAndroid Build Coastguard Worker append_to_release_string, required_libavb_version_minor) 3841*d289c2baSAndroid Build Coastguard Worker padding_needed = (round_to_multiple(len(vbmeta_blob), image.block_size) - 3842*d289c2baSAndroid Build Coastguard Worker len(vbmeta_blob)) 3843*d289c2baSAndroid Build Coastguard Worker vbmeta_blob_with_padding = vbmeta_blob + b'\0' * padding_needed 3844*d289c2baSAndroid Build Coastguard Worker 3845*d289c2baSAndroid Build Coastguard Worker # Write vbmeta blob, if requested. 3846*d289c2baSAndroid Build Coastguard Worker if output_vbmeta_image: 3847*d289c2baSAndroid Build Coastguard Worker output_vbmeta_image.write(vbmeta_blob) 3848*d289c2baSAndroid Build Coastguard Worker 3849*d289c2baSAndroid Build Coastguard Worker # Append vbmeta blob and footer, unless requested not to. 3850*d289c2baSAndroid Build Coastguard Worker if not do_not_append_vbmeta_image: 3851*d289c2baSAndroid Build Coastguard Worker image.append_raw(vbmeta_blob_with_padding) 3852*d289c2baSAndroid Build Coastguard Worker 3853*d289c2baSAndroid Build Coastguard Worker # Now insert a DONT_CARE chunk with enough bytes such that the 3854*d289c2baSAndroid Build Coastguard Worker # final Footer block is at the end of partition_size.. 3855*d289c2baSAndroid Build Coastguard Worker if partition_size > 0: 3856*d289c2baSAndroid Build Coastguard Worker image.append_dont_care(partition_size - image.image_size - 3857*d289c2baSAndroid Build Coastguard Worker 1 * image.block_size) 3858*d289c2baSAndroid Build Coastguard Worker 3859*d289c2baSAndroid Build Coastguard Worker # Generate the Footer that tells where the VBMeta footer 3860*d289c2baSAndroid Build Coastguard Worker # is. Also put enough padding in the front of the footer since 3861*d289c2baSAndroid Build Coastguard Worker # we'll write out an entire block. 3862*d289c2baSAndroid Build Coastguard Worker footer = AvbFooter() 3863*d289c2baSAndroid Build Coastguard Worker footer.original_image_size = original_image_size 3864*d289c2baSAndroid Build Coastguard Worker footer.vbmeta_offset = vbmeta_offset 3865*d289c2baSAndroid Build Coastguard Worker footer.vbmeta_size = len(vbmeta_blob) 3866*d289c2baSAndroid Build Coastguard Worker footer_blob = footer.encode() 3867*d289c2baSAndroid Build Coastguard Worker footer_blob_with_padding = ( 3868*d289c2baSAndroid Build Coastguard Worker b'\0' * (image.block_size - AvbFooter.SIZE) + footer_blob) 3869*d289c2baSAndroid Build Coastguard Worker image.append_raw(footer_blob_with_padding) 3870*d289c2baSAndroid Build Coastguard Worker 3871*d289c2baSAndroid Build Coastguard Worker except Exception as e: 3872*d289c2baSAndroid Build Coastguard Worker # Truncate back to original size, then re-raise. 3873*d289c2baSAndroid Build Coastguard Worker image.truncate(original_image_size) 3874*d289c2baSAndroid Build Coastguard Worker raise AvbError('Adding hashtree_footer failed: {}.'.format(e)) from e 3875*d289c2baSAndroid Build Coastguard Worker 3876*d289c2baSAndroid Build Coastguard Worker def make_certificate(self, output, authority_key_path, subject_key_path, 3877*d289c2baSAndroid Build Coastguard Worker subject_key_version, subject, usage, 3878*d289c2baSAndroid Build Coastguard Worker signing_helper, signing_helper_with_files): 3879*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_certificate' command. 3880*d289c2baSAndroid Build Coastguard Worker 3881*d289c2baSAndroid Build Coastguard Worker Certificates are required for avb_cert extension public key metadata. They 3882*d289c2baSAndroid Build Coastguard Worker chain the vbmeta signing key for a particular product back to a fused, 3883*d289c2baSAndroid Build Coastguard Worker permanent root key. These certificates are fixed-length and fixed-format 3884*d289c2baSAndroid Build Coastguard Worker with the explicit goal of not parsing ASN.1 in bootloader code. 3885*d289c2baSAndroid Build Coastguard Worker 3886*d289c2baSAndroid Build Coastguard Worker Arguments: 3887*d289c2baSAndroid Build Coastguard Worker output: Certificate will be written to this file on success. 3888*d289c2baSAndroid Build Coastguard Worker authority_key_path: A PEM file path with the authority private key. 3889*d289c2baSAndroid Build Coastguard Worker If None, then a certificate will be created without a 3890*d289c2baSAndroid Build Coastguard Worker signature. The signature can be created out-of-band 3891*d289c2baSAndroid Build Coastguard Worker and appended. 3892*d289c2baSAndroid Build Coastguard Worker subject_key_path: Path to a PEM or DER subject public key. 3893*d289c2baSAndroid Build Coastguard Worker subject_key_version: A 64-bit version value. If this is None, the number 3894*d289c2baSAndroid Build Coastguard Worker of seconds since the epoch is used. 3895*d289c2baSAndroid Build Coastguard Worker subject: A subject identifier. For Product Signing Key certificates this 3896*d289c2baSAndroid Build Coastguard Worker should be the same Product ID found in the permanent attributes. 3897*d289c2baSAndroid Build Coastguard Worker usage: Usage string whose SHA256 hash will be embedded in the certificate. 3898*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and returns the signature. 3899*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 3900*d289c2baSAndroid Build Coastguard Worker 3901*d289c2baSAndroid Build Coastguard Worker Raises: 3902*d289c2baSAndroid Build Coastguard Worker AvbError: If there an error during signing. 3903*d289c2baSAndroid Build Coastguard Worker """ 3904*d289c2baSAndroid Build Coastguard Worker signed_data = bytearray() 3905*d289c2baSAndroid Build Coastguard Worker signed_data.extend(struct.pack('<I', 1)) # Format Version 3906*d289c2baSAndroid Build Coastguard Worker signed_data.extend(RSAPublicKey(subject_key_path).encode()) 3907*d289c2baSAndroid Build Coastguard Worker hasher = hashlib.sha256() 3908*d289c2baSAndroid Build Coastguard Worker hasher.update(subject) 3909*d289c2baSAndroid Build Coastguard Worker signed_data.extend(hasher.digest()) 3910*d289c2baSAndroid Build Coastguard Worker hasher = hashlib.sha256() 3911*d289c2baSAndroid Build Coastguard Worker hasher.update(usage.encode('ascii')) 3912*d289c2baSAndroid Build Coastguard Worker signed_data.extend(hasher.digest()) 3913*d289c2baSAndroid Build Coastguard Worker if subject_key_version is None: 3914*d289c2baSAndroid Build Coastguard Worker subject_key_version = int(time.time()) 3915*d289c2baSAndroid Build Coastguard Worker signed_data.extend(struct.pack('<Q', subject_key_version)) 3916*d289c2baSAndroid Build Coastguard Worker signature = b'' 3917*d289c2baSAndroid Build Coastguard Worker if authority_key_path: 3918*d289c2baSAndroid Build Coastguard Worker rsa_key = RSAPublicKey(authority_key_path) 3919*d289c2baSAndroid Build Coastguard Worker algorithm_name = 'SHA512_RSA4096' 3920*d289c2baSAndroid Build Coastguard Worker signature = rsa_key.sign(algorithm_name, signed_data, signing_helper, 3921*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files) 3922*d289c2baSAndroid Build Coastguard Worker output.write(signed_data) 3923*d289c2baSAndroid Build Coastguard Worker output.write(signature) 3924*d289c2baSAndroid Build Coastguard Worker 3925*d289c2baSAndroid Build Coastguard Worker def make_cert_permanent_attributes(self, output, root_authority_key_path, 3926*d289c2baSAndroid Build Coastguard Worker product_id): 3927*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_cert_permanent_attributes' command. 3928*d289c2baSAndroid Build Coastguard Worker 3929*d289c2baSAndroid Build Coastguard Worker avb_cert permanent attributes are designed to be permanent for a 3930*d289c2baSAndroid Build Coastguard Worker particular product and a hash of these attributes should be fused into 3931*d289c2baSAndroid Build Coastguard Worker hardware to enforce this. 3932*d289c2baSAndroid Build Coastguard Worker 3933*d289c2baSAndroid Build Coastguard Worker Arguments: 3934*d289c2baSAndroid Build Coastguard Worker output: Attributes will be written to this file on success. 3935*d289c2baSAndroid Build Coastguard Worker root_authority_key_path: Path to a PEM or DER public key for 3936*d289c2baSAndroid Build Coastguard Worker the root authority. 3937*d289c2baSAndroid Build Coastguard Worker product_id: A 16-byte Product ID. 3938*d289c2baSAndroid Build Coastguard Worker 3939*d289c2baSAndroid Build Coastguard Worker Raises: 3940*d289c2baSAndroid Build Coastguard Worker AvbError: If an argument is incorrect. 3941*d289c2baSAndroid Build Coastguard Worker """ 3942*d289c2baSAndroid Build Coastguard Worker EXPECTED_PRODUCT_ID_SIZE = 16 # pylint: disable=invalid-name 3943*d289c2baSAndroid Build Coastguard Worker if len(product_id) != EXPECTED_PRODUCT_ID_SIZE: 3944*d289c2baSAndroid Build Coastguard Worker raise AvbError('Invalid Product ID length.') 3945*d289c2baSAndroid Build Coastguard Worker output.write(struct.pack('<I', 1)) # Format Version 3946*d289c2baSAndroid Build Coastguard Worker output.write(RSAPublicKey(root_authority_key_path).encode()) 3947*d289c2baSAndroid Build Coastguard Worker output.write(product_id) 3948*d289c2baSAndroid Build Coastguard Worker 3949*d289c2baSAndroid Build Coastguard Worker def make_cert_metadata(self, output, intermediate_key_certificate, 3950*d289c2baSAndroid Build Coastguard Worker product_key_certificate): 3951*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_cert_metadata' command. 3952*d289c2baSAndroid Build Coastguard Worker 3953*d289c2baSAndroid Build Coastguard Worker avb_cert metadata are included in vbmeta images to facilitate 3954*d289c2baSAndroid Build Coastguard Worker verification. The output of this command can be used as the 3955*d289c2baSAndroid Build Coastguard Worker public_key_metadata argument to other commands. 3956*d289c2baSAndroid Build Coastguard Worker 3957*d289c2baSAndroid Build Coastguard Worker Arguments: 3958*d289c2baSAndroid Build Coastguard Worker output: Metadata will be written to this file on success. 3959*d289c2baSAndroid Build Coastguard Worker intermediate_key_certificate: A certificate file as output by 3960*d289c2baSAndroid Build Coastguard Worker make_certificate with usage set to 3961*d289c2baSAndroid Build Coastguard Worker CERT_USAGE_INTERMEDIATE_AUTHORITY. 3962*d289c2baSAndroid Build Coastguard Worker product_key_certificate: A certificate file as output by 3963*d289c2baSAndroid Build Coastguard Worker make_certificate with usage set to 3964*d289c2baSAndroid Build Coastguard Worker CERT_USAGE_SIGNING. 3965*d289c2baSAndroid Build Coastguard Worker 3966*d289c2baSAndroid Build Coastguard Worker Raises: 3967*d289c2baSAndroid Build Coastguard Worker AvbError: If an argument is incorrect. 3968*d289c2baSAndroid Build Coastguard Worker """ 3969*d289c2baSAndroid Build Coastguard Worker EXPECTED_CERTIFICATE_SIZE = 1620 # pylint: disable=invalid-name 3970*d289c2baSAndroid Build Coastguard Worker if len(intermediate_key_certificate) != EXPECTED_CERTIFICATE_SIZE: 3971*d289c2baSAndroid Build Coastguard Worker raise AvbError('Invalid intermediate key certificate length.') 3972*d289c2baSAndroid Build Coastguard Worker if len(product_key_certificate) != EXPECTED_CERTIFICATE_SIZE: 3973*d289c2baSAndroid Build Coastguard Worker raise AvbError('Invalid product key certificate length.') 3974*d289c2baSAndroid Build Coastguard Worker output.write(struct.pack('<I', 1)) # Format Version 3975*d289c2baSAndroid Build Coastguard Worker output.write(intermediate_key_certificate) 3976*d289c2baSAndroid Build Coastguard Worker output.write(product_key_certificate) 3977*d289c2baSAndroid Build Coastguard Worker 3978*d289c2baSAndroid Build Coastguard Worker def make_cert_unlock_credential(self, output, intermediate_key_certificate, 3979*d289c2baSAndroid Build Coastguard Worker unlock_key_certificate, challenge_path, 3980*d289c2baSAndroid Build Coastguard Worker unlock_key_path, signing_helper, 3981*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files): 3982*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_cert_unlock_credential' command. 3983*d289c2baSAndroid Build Coastguard Worker 3984*d289c2baSAndroid Build Coastguard Worker avb_cert unlock credentials can be used to authorize the unlock of AVB 3985*d289c2baSAndroid Build Coastguard Worker on a device. These credentials are presented to an avb_cert bootloader 3986*d289c2baSAndroid Build Coastguard Worker via the fastboot interface in response to a 16-byte challenge. This method 3987*d289c2baSAndroid Build Coastguard Worker creates all fields of the credential except the challenge signature field 3988*d289c2baSAndroid Build Coastguard Worker (which is the last field) and can optionally create the challenge signature 3989*d289c2baSAndroid Build Coastguard Worker field as well if a challenge and the unlock_key_path is provided. 3990*d289c2baSAndroid Build Coastguard Worker 3991*d289c2baSAndroid Build Coastguard Worker Arguments: 3992*d289c2baSAndroid Build Coastguard Worker output: The credential will be written to this file on success. 3993*d289c2baSAndroid Build Coastguard Worker intermediate_key_certificate: A certificate file as output by 3994*d289c2baSAndroid Build Coastguard Worker make_certificate with usage set to 3995*d289c2baSAndroid Build Coastguard Worker CERT_USAGE_INTERMEDIATE_AUTHORITY. 3996*d289c2baSAndroid Build Coastguard Worker unlock_key_certificate: A certificate file as output by 3997*d289c2baSAndroid Build Coastguard Worker make_certificate with usage set to 3998*d289c2baSAndroid Build Coastguard Worker CERT_USAGE_UNLOCK. 3999*d289c2baSAndroid Build Coastguard Worker challenge_path: [optional] A path to the challenge to sign. 4000*d289c2baSAndroid Build Coastguard Worker unlock_key_path: [optional] A PEM file path with the unlock private key. 4001*d289c2baSAndroid Build Coastguard Worker signing_helper: Program which signs a hash and returns the signature. 4002*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files: Same as signing_helper but uses files instead. 4003*d289c2baSAndroid Build Coastguard Worker 4004*d289c2baSAndroid Build Coastguard Worker Raises: 4005*d289c2baSAndroid Build Coastguard Worker AvbError: If an argument is incorrect or an error occurs during signing. 4006*d289c2baSAndroid Build Coastguard Worker """ 4007*d289c2baSAndroid Build Coastguard Worker EXPECTED_CERTIFICATE_SIZE = 1620 # pylint: disable=invalid-name 4008*d289c2baSAndroid Build Coastguard Worker EXPECTED_CHALLENGE_SIZE = 16 # pylint: disable=invalid-name 4009*d289c2baSAndroid Build Coastguard Worker if len(intermediate_key_certificate) != EXPECTED_CERTIFICATE_SIZE: 4010*d289c2baSAndroid Build Coastguard Worker raise AvbError('Invalid intermediate key certificate length.') 4011*d289c2baSAndroid Build Coastguard Worker if len(unlock_key_certificate) != EXPECTED_CERTIFICATE_SIZE: 4012*d289c2baSAndroid Build Coastguard Worker raise AvbError('Invalid product key certificate length.') 4013*d289c2baSAndroid Build Coastguard Worker challenge = b'' 4014*d289c2baSAndroid Build Coastguard Worker if challenge_path: 4015*d289c2baSAndroid Build Coastguard Worker with open(challenge_path, 'rb') as f: 4016*d289c2baSAndroid Build Coastguard Worker challenge = f.read() 4017*d289c2baSAndroid Build Coastguard Worker if len(challenge) != EXPECTED_CHALLENGE_SIZE: 4018*d289c2baSAndroid Build Coastguard Worker raise AvbError('Invalid unlock challenge length.') 4019*d289c2baSAndroid Build Coastguard Worker output.write(struct.pack('<I', 1)) # Format Version 4020*d289c2baSAndroid Build Coastguard Worker output.write(intermediate_key_certificate) 4021*d289c2baSAndroid Build Coastguard Worker output.write(unlock_key_certificate) 4022*d289c2baSAndroid Build Coastguard Worker if challenge_path and unlock_key_path: 4023*d289c2baSAndroid Build Coastguard Worker rsa_key = RSAPublicKey(unlock_key_path) 4024*d289c2baSAndroid Build Coastguard Worker algorithm_name = 'SHA512_RSA4096' 4025*d289c2baSAndroid Build Coastguard Worker signature = rsa_key.sign(algorithm_name, challenge, signing_helper, 4026*d289c2baSAndroid Build Coastguard Worker signing_helper_with_files) 4027*d289c2baSAndroid Build Coastguard Worker output.write(signature) 4028*d289c2baSAndroid Build Coastguard Worker 4029*d289c2baSAndroid Build Coastguard Worker 4030*d289c2baSAndroid Build Coastguard Workerdef calc_hash_level_offsets(image_size, block_size, digest_size): 4031*d289c2baSAndroid Build Coastguard Worker """Calculate the offsets of all the hash-levels in a Merkle-tree. 4032*d289c2baSAndroid Build Coastguard Worker 4033*d289c2baSAndroid Build Coastguard Worker Arguments: 4034*d289c2baSAndroid Build Coastguard Worker image_size: The size of the image to calculate a Merkle-tree for. 4035*d289c2baSAndroid Build Coastguard Worker block_size: The block size, e.g. 4096. 4036*d289c2baSAndroid Build Coastguard Worker digest_size: The size of each hash, e.g. 32 for SHA-256. 4037*d289c2baSAndroid Build Coastguard Worker 4038*d289c2baSAndroid Build Coastguard Worker Returns: 4039*d289c2baSAndroid Build Coastguard Worker A tuple where the first argument is an array of offsets and the 4040*d289c2baSAndroid Build Coastguard Worker second is size of the tree, in bytes. 4041*d289c2baSAndroid Build Coastguard Worker """ 4042*d289c2baSAndroid Build Coastguard Worker level_offsets = [] 4043*d289c2baSAndroid Build Coastguard Worker level_sizes = [] 4044*d289c2baSAndroid Build Coastguard Worker tree_size = 0 4045*d289c2baSAndroid Build Coastguard Worker 4046*d289c2baSAndroid Build Coastguard Worker num_levels = 0 4047*d289c2baSAndroid Build Coastguard Worker size = image_size 4048*d289c2baSAndroid Build Coastguard Worker while size > block_size: 4049*d289c2baSAndroid Build Coastguard Worker num_blocks = (size + block_size - 1) // block_size 4050*d289c2baSAndroid Build Coastguard Worker level_size = round_to_multiple(num_blocks * digest_size, block_size) 4051*d289c2baSAndroid Build Coastguard Worker 4052*d289c2baSAndroid Build Coastguard Worker level_sizes.append(level_size) 4053*d289c2baSAndroid Build Coastguard Worker tree_size += level_size 4054*d289c2baSAndroid Build Coastguard Worker num_levels += 1 4055*d289c2baSAndroid Build Coastguard Worker 4056*d289c2baSAndroid Build Coastguard Worker size = level_size 4057*d289c2baSAndroid Build Coastguard Worker 4058*d289c2baSAndroid Build Coastguard Worker for n in range(0, num_levels): 4059*d289c2baSAndroid Build Coastguard Worker offset = 0 4060*d289c2baSAndroid Build Coastguard Worker for m in range(n + 1, num_levels): 4061*d289c2baSAndroid Build Coastguard Worker offset += level_sizes[m] 4062*d289c2baSAndroid Build Coastguard Worker level_offsets.append(offset) 4063*d289c2baSAndroid Build Coastguard Worker 4064*d289c2baSAndroid Build Coastguard Worker return level_offsets, tree_size 4065*d289c2baSAndroid Build Coastguard Worker 4066*d289c2baSAndroid Build Coastguard Worker 4067*d289c2baSAndroid Build Coastguard Worker# See system/extras/libfec/include/fec/io.h for these definitions. 4068*d289c2baSAndroid Build Coastguard WorkerFEC_FOOTER_FORMAT = '<LLLLLQ32s' 4069*d289c2baSAndroid Build Coastguard WorkerFEC_MAGIC = 0xfecfecfe 4070*d289c2baSAndroid Build Coastguard Worker 4071*d289c2baSAndroid Build Coastguard Worker 4072*d289c2baSAndroid Build Coastguard Workerdef calc_fec_data_size(image_size, num_roots): 4073*d289c2baSAndroid Build Coastguard Worker """Calculates how much space FEC data will take. 4074*d289c2baSAndroid Build Coastguard Worker 4075*d289c2baSAndroid Build Coastguard Worker Arguments: 4076*d289c2baSAndroid Build Coastguard Worker image_size: The size of the image. 4077*d289c2baSAndroid Build Coastguard Worker num_roots: Number of roots. 4078*d289c2baSAndroid Build Coastguard Worker 4079*d289c2baSAndroid Build Coastguard Worker Returns: 4080*d289c2baSAndroid Build Coastguard Worker The number of bytes needed for FEC for an image of the given size 4081*d289c2baSAndroid Build Coastguard Worker and with the requested number of FEC roots. 4082*d289c2baSAndroid Build Coastguard Worker 4083*d289c2baSAndroid Build Coastguard Worker Raises: 4084*d289c2baSAndroid Build Coastguard Worker ValueError: If output from the 'fec' tool is invalid. 4085*d289c2baSAndroid Build Coastguard Worker """ 4086*d289c2baSAndroid Build Coastguard Worker p = subprocess.Popen( 4087*d289c2baSAndroid Build Coastguard Worker ['fec', '--print-fec-size', str(image_size), '--roots', str(num_roots)], 4088*d289c2baSAndroid Build Coastguard Worker stdout=subprocess.PIPE, 4089*d289c2baSAndroid Build Coastguard Worker stderr=subprocess.PIPE) 4090*d289c2baSAndroid Build Coastguard Worker (pout, perr) = p.communicate() 4091*d289c2baSAndroid Build Coastguard Worker retcode = p.wait() 4092*d289c2baSAndroid Build Coastguard Worker if retcode != 0: 4093*d289c2baSAndroid Build Coastguard Worker raise ValueError('Error invoking fec: {}'.format(perr)) 4094*d289c2baSAndroid Build Coastguard Worker return int(pout) 4095*d289c2baSAndroid Build Coastguard Worker 4096*d289c2baSAndroid Build Coastguard Worker 4097*d289c2baSAndroid Build Coastguard Workerdef generate_fec_data(image_filename, num_roots): 4098*d289c2baSAndroid Build Coastguard Worker """Generate FEC codes for an image. 4099*d289c2baSAndroid Build Coastguard Worker 4100*d289c2baSAndroid Build Coastguard Worker Arguments: 4101*d289c2baSAndroid Build Coastguard Worker image_filename: The filename of the image. 4102*d289c2baSAndroid Build Coastguard Worker num_roots: Number of roots. 4103*d289c2baSAndroid Build Coastguard Worker 4104*d289c2baSAndroid Build Coastguard Worker Returns: 4105*d289c2baSAndroid Build Coastguard Worker The FEC data blob as bytes. 4106*d289c2baSAndroid Build Coastguard Worker 4107*d289c2baSAndroid Build Coastguard Worker Raises: 4108*d289c2baSAndroid Build Coastguard Worker ValueError: If calling the 'fec' tool failed or the output is invalid. 4109*d289c2baSAndroid Build Coastguard Worker """ 4110*d289c2baSAndroid Build Coastguard Worker with tempfile.NamedTemporaryFile() as fec_tmpfile: 4111*d289c2baSAndroid Build Coastguard Worker try: 4112*d289c2baSAndroid Build Coastguard Worker subprocess.check_call( 4113*d289c2baSAndroid Build Coastguard Worker ['fec', '--encode', '--roots', str(num_roots), image_filename, 4114*d289c2baSAndroid Build Coastguard Worker fec_tmpfile.name], 4115*d289c2baSAndroid Build Coastguard Worker stderr=open(os.devnull, 'wb')) 4116*d289c2baSAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 4117*d289c2baSAndroid Build Coastguard Worker raise ValueError('Execution of \'fec\' tool failed: {}.' 4118*d289c2baSAndroid Build Coastguard Worker .format(e)) from e 4119*d289c2baSAndroid Build Coastguard Worker fec_data = fec_tmpfile.read() 4120*d289c2baSAndroid Build Coastguard Worker 4121*d289c2baSAndroid Build Coastguard Worker footer_size = struct.calcsize(FEC_FOOTER_FORMAT) 4122*d289c2baSAndroid Build Coastguard Worker footer_data = fec_data[-footer_size:] 4123*d289c2baSAndroid Build Coastguard Worker (magic, _, _, num_roots, fec_size, _, _) = struct.unpack(FEC_FOOTER_FORMAT, 4124*d289c2baSAndroid Build Coastguard Worker footer_data) 4125*d289c2baSAndroid Build Coastguard Worker if magic != FEC_MAGIC: 4126*d289c2baSAndroid Build Coastguard Worker raise ValueError('Unexpected magic in FEC footer') 4127*d289c2baSAndroid Build Coastguard Worker return fec_data[0:fec_size] 4128*d289c2baSAndroid Build Coastguard Worker 4129*d289c2baSAndroid Build Coastguard Worker 4130*d289c2baSAndroid Build Coastguard Workerdef generate_hash_tree(image, image_size, block_size, hash_alg_name, salt, 4131*d289c2baSAndroid Build Coastguard Worker digest_padding, hash_level_offsets, tree_size): 4132*d289c2baSAndroid Build Coastguard Worker """Generates a Merkle-tree for a file. 4133*d289c2baSAndroid Build Coastguard Worker 4134*d289c2baSAndroid Build Coastguard Worker Arguments: 4135*d289c2baSAndroid Build Coastguard Worker image: The image, as a file. 4136*d289c2baSAndroid Build Coastguard Worker image_size: The size of the image. 4137*d289c2baSAndroid Build Coastguard Worker block_size: The block size, e.g. 4096. 4138*d289c2baSAndroid Build Coastguard Worker hash_alg_name: The hash algorithm, e.g. 'sha256' or 'sha1'. 4139*d289c2baSAndroid Build Coastguard Worker salt: The salt to use. 4140*d289c2baSAndroid Build Coastguard Worker digest_padding: The padding for each digest. 4141*d289c2baSAndroid Build Coastguard Worker hash_level_offsets: The offsets from calc_hash_level_offsets(). 4142*d289c2baSAndroid Build Coastguard Worker tree_size: The size of the tree, in number of bytes. 4143*d289c2baSAndroid Build Coastguard Worker 4144*d289c2baSAndroid Build Coastguard Worker Returns: 4145*d289c2baSAndroid Build Coastguard Worker A tuple where the first element is the top-level hash as bytes and the 4146*d289c2baSAndroid Build Coastguard Worker second element is the hash-tree as bytes. 4147*d289c2baSAndroid Build Coastguard Worker """ 4148*d289c2baSAndroid Build Coastguard Worker hash_ret = bytearray(tree_size) 4149*d289c2baSAndroid Build Coastguard Worker hash_src_offset = 0 4150*d289c2baSAndroid Build Coastguard Worker hash_src_size = image_size 4151*d289c2baSAndroid Build Coastguard Worker level_num = 0 4152*d289c2baSAndroid Build Coastguard Worker 4153*d289c2baSAndroid Build Coastguard Worker # If there is only one block, returns the top-level hash directly. 4154*d289c2baSAndroid Build Coastguard Worker if hash_src_size == block_size: 4155*d289c2baSAndroid Build Coastguard Worker hasher = create_avb_hashtree_hasher(hash_alg_name, salt) 4156*d289c2baSAndroid Build Coastguard Worker image.seek(0) 4157*d289c2baSAndroid Build Coastguard Worker hasher.update(image.read(block_size)) 4158*d289c2baSAndroid Build Coastguard Worker return hasher.digest(), bytes(hash_ret) 4159*d289c2baSAndroid Build Coastguard Worker 4160*d289c2baSAndroid Build Coastguard Worker while hash_src_size > block_size: 4161*d289c2baSAndroid Build Coastguard Worker level_output_list = [] 4162*d289c2baSAndroid Build Coastguard Worker remaining = hash_src_size 4163*d289c2baSAndroid Build Coastguard Worker while remaining > 0: 4164*d289c2baSAndroid Build Coastguard Worker hasher = create_avb_hashtree_hasher(hash_alg_name, salt) 4165*d289c2baSAndroid Build Coastguard Worker # Only read from the file for the first level - for subsequent 4166*d289c2baSAndroid Build Coastguard Worker # levels, access the array we're building. 4167*d289c2baSAndroid Build Coastguard Worker if level_num == 0: 4168*d289c2baSAndroid Build Coastguard Worker image.seek(hash_src_offset + hash_src_size - remaining) 4169*d289c2baSAndroid Build Coastguard Worker data = image.read(min(remaining, block_size)) 4170*d289c2baSAndroid Build Coastguard Worker else: 4171*d289c2baSAndroid Build Coastguard Worker offset = hash_level_offsets[level_num - 1] + hash_src_size - remaining 4172*d289c2baSAndroid Build Coastguard Worker data = hash_ret[offset:offset + block_size] 4173*d289c2baSAndroid Build Coastguard Worker hasher.update(data) 4174*d289c2baSAndroid Build Coastguard Worker 4175*d289c2baSAndroid Build Coastguard Worker remaining -= len(data) 4176*d289c2baSAndroid Build Coastguard Worker if len(data) < block_size: 4177*d289c2baSAndroid Build Coastguard Worker hasher.update(b'\0' * (block_size - len(data))) 4178*d289c2baSAndroid Build Coastguard Worker level_output_list.append(hasher.digest()) 4179*d289c2baSAndroid Build Coastguard Worker if digest_padding > 0: 4180*d289c2baSAndroid Build Coastguard Worker level_output_list.append(b'\0' * digest_padding) 4181*d289c2baSAndroid Build Coastguard Worker 4182*d289c2baSAndroid Build Coastguard Worker level_output = b''.join(level_output_list) 4183*d289c2baSAndroid Build Coastguard Worker 4184*d289c2baSAndroid Build Coastguard Worker padding_needed = (round_to_multiple( 4185*d289c2baSAndroid Build Coastguard Worker len(level_output), block_size) - len(level_output)) 4186*d289c2baSAndroid Build Coastguard Worker level_output += b'\0' * padding_needed 4187*d289c2baSAndroid Build Coastguard Worker 4188*d289c2baSAndroid Build Coastguard Worker # Copy level-output into resulting tree. 4189*d289c2baSAndroid Build Coastguard Worker offset = hash_level_offsets[level_num] 4190*d289c2baSAndroid Build Coastguard Worker hash_ret[offset:offset + len(level_output)] = level_output 4191*d289c2baSAndroid Build Coastguard Worker 4192*d289c2baSAndroid Build Coastguard Worker # Continue on to the next level. 4193*d289c2baSAndroid Build Coastguard Worker hash_src_size = len(level_output) 4194*d289c2baSAndroid Build Coastguard Worker level_num += 1 4195*d289c2baSAndroid Build Coastguard Worker 4196*d289c2baSAndroid Build Coastguard Worker hasher = create_avb_hashtree_hasher(hash_alg_name, salt) 4197*d289c2baSAndroid Build Coastguard Worker hasher.update(level_output) 4198*d289c2baSAndroid Build Coastguard Worker return hasher.digest(), bytes(hash_ret) 4199*d289c2baSAndroid Build Coastguard Worker 4200*d289c2baSAndroid Build Coastguard Worker 4201*d289c2baSAndroid Build Coastguard Workerclass AvbTool(object): 4202*d289c2baSAndroid Build Coastguard Worker """Object for avbtool command-line tool.""" 4203*d289c2baSAndroid Build Coastguard Worker 4204*d289c2baSAndroid Build Coastguard Worker def __init__(self): 4205*d289c2baSAndroid Build Coastguard Worker """Initializer method.""" 4206*d289c2baSAndroid Build Coastguard Worker self.avb = Avb() 4207*d289c2baSAndroid Build Coastguard Worker 4208*d289c2baSAndroid Build Coastguard Worker def _add_common_args(self, sub_parser): 4209*d289c2baSAndroid Build Coastguard Worker """Adds arguments used by several sub-commands. 4210*d289c2baSAndroid Build Coastguard Worker 4211*d289c2baSAndroid Build Coastguard Worker Arguments: 4212*d289c2baSAndroid Build Coastguard Worker sub_parser: The parser to add arguments to. 4213*d289c2baSAndroid Build Coastguard Worker """ 4214*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--algorithm', 4215*d289c2baSAndroid Build Coastguard Worker help='Algorithm to use (default: NONE)', 4216*d289c2baSAndroid Build Coastguard Worker metavar='ALGORITHM', 4217*d289c2baSAndroid Build Coastguard Worker default='NONE') 4218*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--key', 4219*d289c2baSAndroid Build Coastguard Worker help='Path to RSA private key file', 4220*d289c2baSAndroid Build Coastguard Worker metavar='KEY', 4221*d289c2baSAndroid Build Coastguard Worker required=False) 4222*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--signing_helper', 4223*d289c2baSAndroid Build Coastguard Worker help='Path to helper used for signing', 4224*d289c2baSAndroid Build Coastguard Worker metavar='APP', 4225*d289c2baSAndroid Build Coastguard Worker default=None, 4226*d289c2baSAndroid Build Coastguard Worker required=False) 4227*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--signing_helper_with_files', 4228*d289c2baSAndroid Build Coastguard Worker help='Path to helper used for signing using files', 4229*d289c2baSAndroid Build Coastguard Worker metavar='APP', 4230*d289c2baSAndroid Build Coastguard Worker default=None, 4231*d289c2baSAndroid Build Coastguard Worker required=False) 4232*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--public_key_metadata', 4233*d289c2baSAndroid Build Coastguard Worker help='Path to public key metadata file', 4234*d289c2baSAndroid Build Coastguard Worker metavar='KEY_METADATA', 4235*d289c2baSAndroid Build Coastguard Worker required=False) 4236*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--rollback_index', 4237*d289c2baSAndroid Build Coastguard Worker help='Rollback Index', 4238*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4239*d289c2baSAndroid Build Coastguard Worker default=0) 4240*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--rollback_index_location', 4241*d289c2baSAndroid Build Coastguard Worker help='Location of main vbmeta Rollback Index', 4242*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4243*d289c2baSAndroid Build Coastguard Worker default=0) 4244*d289c2baSAndroid Build Coastguard Worker # This is used internally for unit tests. Do not include in --help output. 4245*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--internal_release_string', 4246*d289c2baSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 4247*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--append_to_release_string', 4248*d289c2baSAndroid Build Coastguard Worker help='Text to append to release string', 4249*d289c2baSAndroid Build Coastguard Worker metavar='STR') 4250*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--prop', 4251*d289c2baSAndroid Build Coastguard Worker help='Add property', 4252*d289c2baSAndroid Build Coastguard Worker metavar='KEY:VALUE', 4253*d289c2baSAndroid Build Coastguard Worker action='append') 4254*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--prop_from_file', 4255*d289c2baSAndroid Build Coastguard Worker help='Add property from file', 4256*d289c2baSAndroid Build Coastguard Worker metavar='KEY:PATH', 4257*d289c2baSAndroid Build Coastguard Worker action='append') 4258*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--kernel_cmdline', 4259*d289c2baSAndroid Build Coastguard Worker help='Add kernel cmdline', 4260*d289c2baSAndroid Build Coastguard Worker metavar='CMDLINE', 4261*d289c2baSAndroid Build Coastguard Worker action='append') 4262*d289c2baSAndroid Build Coastguard Worker # TODO(zeuthen): the --setup_rootfs_from_kernel option used to be called 4263*d289c2baSAndroid Build Coastguard Worker # --generate_dm_verity_cmdline_from_hashtree. Remove support for the latter 4264*d289c2baSAndroid Build Coastguard Worker # at some future point. 4265*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--setup_rootfs_from_kernel', 4266*d289c2baSAndroid Build Coastguard Worker '--generate_dm_verity_cmdline_from_hashtree', 4267*d289c2baSAndroid Build Coastguard Worker metavar='IMAGE', 4268*d289c2baSAndroid Build Coastguard Worker help='Adds kernel cmdline to set up IMAGE', 4269*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb')) 4270*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--include_descriptors_from_image', 4271*d289c2baSAndroid Build Coastguard Worker help='Include descriptors from image', 4272*d289c2baSAndroid Build Coastguard Worker metavar='IMAGE', 4273*d289c2baSAndroid Build Coastguard Worker action='append', 4274*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb')) 4275*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--print_required_libavb_version', 4276*d289c2baSAndroid Build Coastguard Worker help=('Don\'t store the footer - ' 4277*d289c2baSAndroid Build Coastguard Worker 'instead calculate the required libavb ' 4278*d289c2baSAndroid Build Coastguard Worker 'version for the given options.'), 4279*d289c2baSAndroid Build Coastguard Worker action='store_true') 4280*d289c2baSAndroid Build Coastguard Worker # These are only allowed from top-level vbmeta and boot-in-lieu-of-vbmeta. 4281*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--chain_partition', 4282*d289c2baSAndroid Build Coastguard Worker help='Allow signed integrity-data for partition', 4283*d289c2baSAndroid Build Coastguard Worker metavar='PART_NAME:ROLLBACK_SLOT:KEY_PATH', 4284*d289c2baSAndroid Build Coastguard Worker action='append') 4285*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--chain_partition_do_not_use_ab', 4286*d289c2baSAndroid Build Coastguard Worker help='Allow signed integrity-data for partition does not use A/B', 4287*d289c2baSAndroid Build Coastguard Worker metavar='PART_NAME:ROLLBACK_SLOT:KEY_PATH', 4288*d289c2baSAndroid Build Coastguard Worker action='append', 4289*d289c2baSAndroid Build Coastguard Worker required=False) 4290*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--flags', 4291*d289c2baSAndroid Build Coastguard Worker help='VBMeta flags', 4292*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4293*d289c2baSAndroid Build Coastguard Worker default=0) 4294*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--set_hashtree_disabled_flag', 4295*d289c2baSAndroid Build Coastguard Worker help='Set the HASHTREE_DISABLED flag', 4296*d289c2baSAndroid Build Coastguard Worker action='store_true') 4297*d289c2baSAndroid Build Coastguard Worker 4298*d289c2baSAndroid Build Coastguard Worker def _add_common_footer_args(self, sub_parser): 4299*d289c2baSAndroid Build Coastguard Worker """Adds arguments used by add_*_footer sub-commands. 4300*d289c2baSAndroid Build Coastguard Worker 4301*d289c2baSAndroid Build Coastguard Worker Arguments: 4302*d289c2baSAndroid Build Coastguard Worker sub_parser: The parser to add arguments to. 4303*d289c2baSAndroid Build Coastguard Worker """ 4304*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--use_persistent_digest', 4305*d289c2baSAndroid Build Coastguard Worker help='Use a persistent digest on device instead of ' 4306*d289c2baSAndroid Build Coastguard Worker 'storing the digest in the descriptor. This ' 4307*d289c2baSAndroid Build Coastguard Worker 'cannot be used with A/B so must be combined ' 4308*d289c2baSAndroid Build Coastguard Worker 'with --do_not_use_ab when an A/B suffix is ' 4309*d289c2baSAndroid Build Coastguard Worker 'expected at runtime.', 4310*d289c2baSAndroid Build Coastguard Worker action='store_true') 4311*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--do_not_use_ab', 4312*d289c2baSAndroid Build Coastguard Worker help='The partition does not use A/B even when an ' 4313*d289c2baSAndroid Build Coastguard Worker 'A/B suffix is present. This must not be used ' 4314*d289c2baSAndroid Build Coastguard Worker 'for vbmeta or chained partitions.', 4315*d289c2baSAndroid Build Coastguard Worker action='store_true') 4316*d289c2baSAndroid Build Coastguard Worker 4317*d289c2baSAndroid Build Coastguard Worker def _fixup_common_args(self, args): 4318*d289c2baSAndroid Build Coastguard Worker """Common fixups needed by subcommands. 4319*d289c2baSAndroid Build Coastguard Worker 4320*d289c2baSAndroid Build Coastguard Worker Arguments: 4321*d289c2baSAndroid Build Coastguard Worker args: Arguments to modify. 4322*d289c2baSAndroid Build Coastguard Worker 4323*d289c2baSAndroid Build Coastguard Worker Returns: 4324*d289c2baSAndroid Build Coastguard Worker The modified arguments. 4325*d289c2baSAndroid Build Coastguard Worker """ 4326*d289c2baSAndroid Build Coastguard Worker if args.set_hashtree_disabled_flag: 4327*d289c2baSAndroid Build Coastguard Worker args.flags |= AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED 4328*d289c2baSAndroid Build Coastguard Worker return args 4329*d289c2baSAndroid Build Coastguard Worker 4330*d289c2baSAndroid Build Coastguard Worker def run(self, argv): 4331*d289c2baSAndroid Build Coastguard Worker """Command-line processor. 4332*d289c2baSAndroid Build Coastguard Worker 4333*d289c2baSAndroid Build Coastguard Worker Arguments: 4334*d289c2baSAndroid Build Coastguard Worker argv: Pass sys.argv from main. 4335*d289c2baSAndroid Build Coastguard Worker """ 4336*d289c2baSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 4337*d289c2baSAndroid Build Coastguard Worker subparsers = parser.add_subparsers(title='subcommands') 4338*d289c2baSAndroid Build Coastguard Worker 4339*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4340*d289c2baSAndroid Build Coastguard Worker 'generate_test_image', 4341*d289c2baSAndroid Build Coastguard Worker help=('Generates a test image with a known pattern for testing: ' 4342*d289c2baSAndroid Build Coastguard Worker '0x00 0x01 0x02 ... 0xff 0x00 0x01 ...')) 4343*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image_size', 4344*d289c2baSAndroid Build Coastguard Worker help='Size of image to generate.', 4345*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4346*d289c2baSAndroid Build Coastguard Worker required=True) 4347*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--start_byte', 4348*d289c2baSAndroid Build Coastguard Worker help='Integer for the start byte of the pattern.', 4349*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4350*d289c2baSAndroid Build Coastguard Worker default=0) 4351*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4352*d289c2baSAndroid Build Coastguard Worker help='Output file name.', 4353*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb'), 4354*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4355*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.generate_test_image) 4356*d289c2baSAndroid Build Coastguard Worker 4357*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('version', 4358*d289c2baSAndroid Build Coastguard Worker help='Prints version of avbtool.') 4359*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.version) 4360*d289c2baSAndroid Build Coastguard Worker 4361*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('extract_public_key', 4362*d289c2baSAndroid Build Coastguard Worker help='Extract public key.') 4363*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--key', 4364*d289c2baSAndroid Build Coastguard Worker help='Path to RSA private key file', 4365*d289c2baSAndroid Build Coastguard Worker required=True) 4366*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4367*d289c2baSAndroid Build Coastguard Worker help='Output file name', 4368*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb'), 4369*d289c2baSAndroid Build Coastguard Worker required=True) 4370*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.extract_public_key) 4371*d289c2baSAndroid Build Coastguard Worker 4372*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('make_vbmeta_image', 4373*d289c2baSAndroid Build Coastguard Worker help='Makes a vbmeta image.') 4374*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4375*d289c2baSAndroid Build Coastguard Worker help='Output file name', 4376*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb')) 4377*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--padding_size', 4378*d289c2baSAndroid Build Coastguard Worker metavar='NUMBER', 4379*d289c2baSAndroid Build Coastguard Worker help='If non-zero, pads output with NUL bytes so ' 4380*d289c2baSAndroid Build Coastguard Worker 'its size is a multiple of NUMBER ' 4381*d289c2baSAndroid Build Coastguard Worker '(default: 0)', 4382*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4383*d289c2baSAndroid Build Coastguard Worker default=0) 4384*d289c2baSAndroid Build Coastguard Worker self._add_common_args(sub_parser) 4385*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.make_vbmeta_image) 4386*d289c2baSAndroid Build Coastguard Worker 4387*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('add_hash_footer', 4388*d289c2baSAndroid Build Coastguard Worker help='Add hashes and footer to image.') 4389*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4390*d289c2baSAndroid Build Coastguard Worker help='Image to add hashes to') 4391*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--partition_size', 4392*d289c2baSAndroid Build Coastguard Worker help='Partition size', 4393*d289c2baSAndroid Build Coastguard Worker type=parse_number) 4394*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--dynamic_partition_size', 4395*d289c2baSAndroid Build Coastguard Worker help='Calculate partition size based on image size', 4396*d289c2baSAndroid Build Coastguard Worker action='store_true') 4397*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--partition_name', 4398*d289c2baSAndroid Build Coastguard Worker help='Partition name', 4399*d289c2baSAndroid Build Coastguard Worker default=None) 4400*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--hash_algorithm', 4401*d289c2baSAndroid Build Coastguard Worker help='Hash algorithm to use (default: sha256)', 4402*d289c2baSAndroid Build Coastguard Worker default='sha256') 4403*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--salt', 4404*d289c2baSAndroid Build Coastguard Worker help='Salt in hex (default: /dev/urandom)') 4405*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--calc_max_image_size', 4406*d289c2baSAndroid Build Coastguard Worker help=('Don\'t store the footer - ' 4407*d289c2baSAndroid Build Coastguard Worker 'instead calculate the maximum image size ' 4408*d289c2baSAndroid Build Coastguard Worker 'leaving enough room for metadata with ' 4409*d289c2baSAndroid Build Coastguard Worker 'the given partition size.'), 4410*d289c2baSAndroid Build Coastguard Worker action='store_true') 4411*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output_vbmeta_image', 4412*d289c2baSAndroid Build Coastguard Worker help='Also write vbmeta struct to file', 4413*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb')) 4414*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--do_not_append_vbmeta_image', 4415*d289c2baSAndroid Build Coastguard Worker help=('Do not append vbmeta struct or footer ' 4416*d289c2baSAndroid Build Coastguard Worker 'to the image'), 4417*d289c2baSAndroid Build Coastguard Worker action='store_true') 4418*d289c2baSAndroid Build Coastguard Worker self._add_common_args(sub_parser) 4419*d289c2baSAndroid Build Coastguard Worker self._add_common_footer_args(sub_parser) 4420*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.add_hash_footer) 4421*d289c2baSAndroid Build Coastguard Worker 4422*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('append_vbmeta_image', 4423*d289c2baSAndroid Build Coastguard Worker help='Append vbmeta image to image.') 4424*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4425*d289c2baSAndroid Build Coastguard Worker help='Image to append vbmeta blob to', 4426*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb+')) 4427*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--partition_size', 4428*d289c2baSAndroid Build Coastguard Worker help='Partition size', 4429*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4430*d289c2baSAndroid Build Coastguard Worker required=True) 4431*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--vbmeta_image', 4432*d289c2baSAndroid Build Coastguard Worker help='Image with vbmeta blob to append', 4433*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb')) 4434*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.append_vbmeta_image) 4435*d289c2baSAndroid Build Coastguard Worker 4436*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4437*d289c2baSAndroid Build Coastguard Worker 'add_hashtree_footer', 4438*d289c2baSAndroid Build Coastguard Worker help='Add hashtree and footer to image.') 4439*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4440*d289c2baSAndroid Build Coastguard Worker help='Image to add hashtree to', 4441*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb+')) 4442*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--partition_size', 4443*d289c2baSAndroid Build Coastguard Worker help='Partition size', 4444*d289c2baSAndroid Build Coastguard Worker default=0, 4445*d289c2baSAndroid Build Coastguard Worker type=parse_number) 4446*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--partition_name', 4447*d289c2baSAndroid Build Coastguard Worker help='Partition name', 4448*d289c2baSAndroid Build Coastguard Worker default='') 4449*d289c2baSAndroid Build Coastguard Worker # For backwards compatibility, add_hashtree_footer defaults to sha1, even 4450*d289c2baSAndroid Build Coastguard Worker # though sha1 is not actually allowed to be used in Android. At the earliest 4451*d289c2baSAndroid Build Coastguard Worker # opportunity, the default should be fixed to be sha256. For now we just 4452*d289c2baSAndroid Build Coastguard Worker # print a warning when the algorithm defaults to sha1. Below uses default='' 4453*d289c2baSAndroid Build Coastguard Worker # so that defaulted sha1 can be distinguished from explicit sha1. 4454*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--hash_algorithm', 4455*d289c2baSAndroid Build Coastguard Worker help='Hash algorithm to use (default: sha1)', 4456*d289c2baSAndroid Build Coastguard Worker default='') 4457*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--salt', 4458*d289c2baSAndroid Build Coastguard Worker help='Salt in hex (default: /dev/urandom)') 4459*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--block_size', 4460*d289c2baSAndroid Build Coastguard Worker help='Block size (default: 4096)', 4461*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4462*d289c2baSAndroid Build Coastguard Worker default=4096) 4463*d289c2baSAndroid Build Coastguard Worker # TODO(zeuthen): The --generate_fec option was removed when we 4464*d289c2baSAndroid Build Coastguard Worker # moved to generating FEC by default. To avoid breaking existing 4465*d289c2baSAndroid Build Coastguard Worker # users needing to transition we simply just print a warning below 4466*d289c2baSAndroid Build Coastguard Worker # in add_hashtree_footer(). Remove this option and the warning at 4467*d289c2baSAndroid Build Coastguard Worker # some point in the future. 4468*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--generate_fec', 4469*d289c2baSAndroid Build Coastguard Worker help=argparse.SUPPRESS, 4470*d289c2baSAndroid Build Coastguard Worker action='store_true') 4471*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument( 4472*d289c2baSAndroid Build Coastguard Worker '--do_not_generate_fec', 4473*d289c2baSAndroid Build Coastguard Worker help='Do not generate forward-error-correction codes', 4474*d289c2baSAndroid Build Coastguard Worker action='store_true') 4475*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--fec_num_roots', 4476*d289c2baSAndroid Build Coastguard Worker help='Number of roots for FEC (default: 2)', 4477*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4478*d289c2baSAndroid Build Coastguard Worker default=2) 4479*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--calc_max_image_size', 4480*d289c2baSAndroid Build Coastguard Worker help=('Don\'t store the hashtree or footer - ' 4481*d289c2baSAndroid Build Coastguard Worker 'instead calculate the maximum image size ' 4482*d289c2baSAndroid Build Coastguard Worker 'leaving enough room for hashtree ' 4483*d289c2baSAndroid Build Coastguard Worker 'and metadata with the given partition ' 4484*d289c2baSAndroid Build Coastguard Worker 'size.'), 4485*d289c2baSAndroid Build Coastguard Worker action='store_true') 4486*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output_vbmeta_image', 4487*d289c2baSAndroid Build Coastguard Worker help='Also write vbmeta struct to file', 4488*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb')) 4489*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--do_not_append_vbmeta_image', 4490*d289c2baSAndroid Build Coastguard Worker help=('Do not append vbmeta struct or footer ' 4491*d289c2baSAndroid Build Coastguard Worker 'to the image'), 4492*d289c2baSAndroid Build Coastguard Worker action='store_true') 4493*d289c2baSAndroid Build Coastguard Worker # This is different from --setup_rootfs_from_kernel insofar that 4494*d289c2baSAndroid Build Coastguard Worker # it doesn't take an IMAGE, the generated cmdline will be for the 4495*d289c2baSAndroid Build Coastguard Worker # hashtree we're adding. 4496*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--setup_as_rootfs_from_kernel', 4497*d289c2baSAndroid Build Coastguard Worker action='store_true', 4498*d289c2baSAndroid Build Coastguard Worker help='Adds kernel cmdline for setting up rootfs') 4499*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--no_hashtree', 4500*d289c2baSAndroid Build Coastguard Worker action='store_true', 4501*d289c2baSAndroid Build Coastguard Worker help='Do not append hashtree') 4502*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--check_at_most_once', 4503*d289c2baSAndroid Build Coastguard Worker action='store_true', 4504*d289c2baSAndroid Build Coastguard Worker help='Set to verify data block only once') 4505*d289c2baSAndroid Build Coastguard Worker self._add_common_args(sub_parser) 4506*d289c2baSAndroid Build Coastguard Worker self._add_common_footer_args(sub_parser) 4507*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.add_hashtree_footer) 4508*d289c2baSAndroid Build Coastguard Worker 4509*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('erase_footer', 4510*d289c2baSAndroid Build Coastguard Worker help='Erase footer from an image.') 4511*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4512*d289c2baSAndroid Build Coastguard Worker help='Image with a footer', 4513*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb+'), 4514*d289c2baSAndroid Build Coastguard Worker required=True) 4515*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--keep_hashtree', 4516*d289c2baSAndroid Build Coastguard Worker help='Keep the hashtree and FEC in the image', 4517*d289c2baSAndroid Build Coastguard Worker action='store_true') 4518*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.erase_footer) 4519*d289c2baSAndroid Build Coastguard Worker 4520*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('zero_hashtree', 4521*d289c2baSAndroid Build Coastguard Worker help='Zero out hashtree and FEC data.') 4522*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4523*d289c2baSAndroid Build Coastguard Worker help='Image with a footer', 4524*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb+'), 4525*d289c2baSAndroid Build Coastguard Worker required=True) 4526*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.zero_hashtree) 4527*d289c2baSAndroid Build Coastguard Worker 4528*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4529*d289c2baSAndroid Build Coastguard Worker 'extract_vbmeta_image', 4530*d289c2baSAndroid Build Coastguard Worker help='Extracts vbmeta from an image with a footer.') 4531*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4532*d289c2baSAndroid Build Coastguard Worker help='Image with footer', 4533*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4534*d289c2baSAndroid Build Coastguard Worker required=True) 4535*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4536*d289c2baSAndroid Build Coastguard Worker help='Output file name', 4537*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb')) 4538*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--padding_size', 4539*d289c2baSAndroid Build Coastguard Worker metavar='NUMBER', 4540*d289c2baSAndroid Build Coastguard Worker help='If non-zero, pads output with NUL bytes so ' 4541*d289c2baSAndroid Build Coastguard Worker 'its size is a multiple of NUMBER ' 4542*d289c2baSAndroid Build Coastguard Worker '(default: 0)', 4543*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4544*d289c2baSAndroid Build Coastguard Worker default=0) 4545*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.extract_vbmeta_image) 4546*d289c2baSAndroid Build Coastguard Worker 4547*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('resize_image', 4548*d289c2baSAndroid Build Coastguard Worker help='Resize image with a footer.') 4549*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4550*d289c2baSAndroid Build Coastguard Worker help='Image with a footer', 4551*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb+'), 4552*d289c2baSAndroid Build Coastguard Worker required=True) 4553*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--partition_size', 4554*d289c2baSAndroid Build Coastguard Worker help='New partition size', 4555*d289c2baSAndroid Build Coastguard Worker type=parse_number) 4556*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.resize_image) 4557*d289c2baSAndroid Build Coastguard Worker 4558*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4559*d289c2baSAndroid Build Coastguard Worker 'info_image', 4560*d289c2baSAndroid Build Coastguard Worker help='Show information about vbmeta or footer.') 4561*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4562*d289c2baSAndroid Build Coastguard Worker help='Image to show information about', 4563*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4564*d289c2baSAndroid Build Coastguard Worker required=True) 4565*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4566*d289c2baSAndroid Build Coastguard Worker help='Write info to file', 4567*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wt'), 4568*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4569*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--cert', '--atx', 4570*d289c2baSAndroid Build Coastguard Worker help=('Show information about the avb_cert ' 4571*d289c2baSAndroid Build Coastguard Worker 'extension certificate.'), 4572*d289c2baSAndroid Build Coastguard Worker action='store_true') 4573*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.info_image) 4574*d289c2baSAndroid Build Coastguard Worker 4575*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4576*d289c2baSAndroid Build Coastguard Worker 'verify_image', 4577*d289c2baSAndroid Build Coastguard Worker help='Verify an image.') 4578*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4579*d289c2baSAndroid Build Coastguard Worker help='Image to verify', 4580*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4581*d289c2baSAndroid Build Coastguard Worker required=True) 4582*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--key', 4583*d289c2baSAndroid Build Coastguard Worker help='Check embedded public key matches KEY', 4584*d289c2baSAndroid Build Coastguard Worker metavar='KEY', 4585*d289c2baSAndroid Build Coastguard Worker required=False) 4586*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--expected_chain_partition', 4587*d289c2baSAndroid Build Coastguard Worker help='Expected chain partition', 4588*d289c2baSAndroid Build Coastguard Worker metavar='PART_NAME:ROLLBACK_SLOT:KEY_PATH', 4589*d289c2baSAndroid Build Coastguard Worker action='append') 4590*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument( 4591*d289c2baSAndroid Build Coastguard Worker '--follow_chain_partitions', 4592*d289c2baSAndroid Build Coastguard Worker help=('Follows chain partitions even when not ' 4593*d289c2baSAndroid Build Coastguard Worker 'specified with the --expected_chain_partition option'), 4594*d289c2baSAndroid Build Coastguard Worker action='store_true') 4595*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument( 4596*d289c2baSAndroid Build Coastguard Worker '--accept_zeroed_hashtree', 4597*d289c2baSAndroid Build Coastguard Worker help=('Accept images where the hashtree or FEC data is zeroed out'), 4598*d289c2baSAndroid Build Coastguard Worker action='store_true') 4599*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.verify_image) 4600*d289c2baSAndroid Build Coastguard Worker 4601*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4602*d289c2baSAndroid Build Coastguard Worker 'print_partition_digests', 4603*d289c2baSAndroid Build Coastguard Worker help='Prints partition digests.') 4604*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4605*d289c2baSAndroid Build Coastguard Worker help='Image to print partition digests from', 4606*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4607*d289c2baSAndroid Build Coastguard Worker required=True) 4608*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4609*d289c2baSAndroid Build Coastguard Worker help='Write info to file', 4610*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wt'), 4611*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4612*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--json', 4613*d289c2baSAndroid Build Coastguard Worker help=('Print output as JSON'), 4614*d289c2baSAndroid Build Coastguard Worker action='store_true') 4615*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.print_partition_digests) 4616*d289c2baSAndroid Build Coastguard Worker 4617*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4618*d289c2baSAndroid Build Coastguard Worker 'calculate_vbmeta_digest', 4619*d289c2baSAndroid Build Coastguard Worker help='Calculate vbmeta digest.') 4620*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4621*d289c2baSAndroid Build Coastguard Worker help='Image to calculate digest for', 4622*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4623*d289c2baSAndroid Build Coastguard Worker required=True) 4624*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--hash_algorithm', 4625*d289c2baSAndroid Build Coastguard Worker help='Hash algorithm to use (default: sha256)', 4626*d289c2baSAndroid Build Coastguard Worker default='sha256') 4627*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4628*d289c2baSAndroid Build Coastguard Worker help='Write hex digest to file (default: stdout)', 4629*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wt'), 4630*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4631*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.calculate_vbmeta_digest) 4632*d289c2baSAndroid Build Coastguard Worker 4633*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4634*d289c2baSAndroid Build Coastguard Worker 'calculate_kernel_cmdline', 4635*d289c2baSAndroid Build Coastguard Worker help='Calculate kernel cmdline.') 4636*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--image', 4637*d289c2baSAndroid Build Coastguard Worker help='Image to calculate kernel cmdline for', 4638*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4639*d289c2baSAndroid Build Coastguard Worker required=True) 4640*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--hashtree_disabled', 4641*d289c2baSAndroid Build Coastguard Worker help='Return the cmdline for hashtree disabled', 4642*d289c2baSAndroid Build Coastguard Worker action='store_true') 4643*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4644*d289c2baSAndroid Build Coastguard Worker help='Write cmdline to file (default: stdout)', 4645*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wt'), 4646*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4647*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.calculate_kernel_cmdline) 4648*d289c2baSAndroid Build Coastguard Worker 4649*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser('set_ab_metadata', 4650*d289c2baSAndroid Build Coastguard Worker help='Set A/B metadata.') 4651*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--misc_image', 4652*d289c2baSAndroid Build Coastguard Worker help=('The misc image to modify. If the image does ' 4653*d289c2baSAndroid Build Coastguard Worker 'not exist, it will be created.'), 4654*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('r+b'), 4655*d289c2baSAndroid Build Coastguard Worker required=True) 4656*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--slot_data', 4657*d289c2baSAndroid Build Coastguard Worker help=('Slot data of the form "priority", ' 4658*d289c2baSAndroid Build Coastguard Worker '"tries_remaining", "sucessful_boot" for ' 4659*d289c2baSAndroid Build Coastguard Worker 'slot A followed by the same for slot B, ' 4660*d289c2baSAndroid Build Coastguard Worker 'separated by colons. The default value ' 4661*d289c2baSAndroid Build Coastguard Worker 'is 15:7:0:14:7:0.'), 4662*d289c2baSAndroid Build Coastguard Worker default='15:7:0:14:7:0') 4663*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.set_ab_metadata) 4664*d289c2baSAndroid Build Coastguard Worker 4665*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4666*d289c2baSAndroid Build Coastguard Worker 'make_certificate', 4667*d289c2baSAndroid Build Coastguard Worker aliases=['make_atx_certificate'], 4668*d289c2baSAndroid Build Coastguard Worker help='Create an avb_cert extension certificate.') 4669*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4670*d289c2baSAndroid Build Coastguard Worker help='Write certificate to file', 4671*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb'), 4672*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4673*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--subject', 4674*d289c2baSAndroid Build Coastguard Worker help=('Path to subject file'), 4675*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4676*d289c2baSAndroid Build Coastguard Worker required=True) 4677*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--subject_key', 4678*d289c2baSAndroid Build Coastguard Worker help=('Path to subject RSA public key file'), 4679*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4680*d289c2baSAndroid Build Coastguard Worker required=True) 4681*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--subject_key_version', 4682*d289c2baSAndroid Build Coastguard Worker help=('Version of the subject key'), 4683*d289c2baSAndroid Build Coastguard Worker type=parse_number, 4684*d289c2baSAndroid Build Coastguard Worker required=False) 4685*d289c2baSAndroid Build Coastguard Worker # We have 3 different usage modifying args for convenience, at most one of 4686*d289c2baSAndroid Build Coastguard Worker # which can be provided since they all set the same usage field. 4687*d289c2baSAndroid Build Coastguard Worker usage_group = sub_parser.add_mutually_exclusive_group(required=False) 4688*d289c2baSAndroid Build Coastguard Worker usage_group.add_argument('--subject_is_intermediate_authority', 4689*d289c2baSAndroid Build Coastguard Worker help=('Override usage with the value used for ' 4690*d289c2baSAndroid Build Coastguard Worker 'an intermediate authority'), 4691*d289c2baSAndroid Build Coastguard Worker action='store_const', 4692*d289c2baSAndroid Build Coastguard Worker const=CERT_USAGE_INTERMEDIATE_AUTHORITY, 4693*d289c2baSAndroid Build Coastguard Worker required=False) 4694*d289c2baSAndroid Build Coastguard Worker usage_group.add_argument('--usage', 4695*d289c2baSAndroid Build Coastguard Worker help=('Override usage with a hash of the provided ' 4696*d289c2baSAndroid Build Coastguard Worker 'string'), 4697*d289c2baSAndroid Build Coastguard Worker required=False), 4698*d289c2baSAndroid Build Coastguard Worker usage_group.add_argument('--usage_for_unlock', 4699*d289c2baSAndroid Build Coastguard Worker help=('Override usage with the value used for ' 4700*d289c2baSAndroid Build Coastguard Worker 'authenticated unlock'), 4701*d289c2baSAndroid Build Coastguard Worker action='store_const', 4702*d289c2baSAndroid Build Coastguard Worker const=CERT_USAGE_UNLOCK, 4703*d289c2baSAndroid Build Coastguard Worker required=False), 4704*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--authority_key', 4705*d289c2baSAndroid Build Coastguard Worker help='Path to authority RSA private key file', 4706*d289c2baSAndroid Build Coastguard Worker required=False) 4707*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--signing_helper', 4708*d289c2baSAndroid Build Coastguard Worker help='Path to helper used for signing', 4709*d289c2baSAndroid Build Coastguard Worker metavar='APP', 4710*d289c2baSAndroid Build Coastguard Worker default=None, 4711*d289c2baSAndroid Build Coastguard Worker required=False) 4712*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--signing_helper_with_files', 4713*d289c2baSAndroid Build Coastguard Worker help='Path to helper used for signing using files', 4714*d289c2baSAndroid Build Coastguard Worker metavar='APP', 4715*d289c2baSAndroid Build Coastguard Worker default=None, 4716*d289c2baSAndroid Build Coastguard Worker required=False) 4717*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.make_certificate) 4718*d289c2baSAndroid Build Coastguard Worker 4719*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4720*d289c2baSAndroid Build Coastguard Worker 'make_cert_permanent_attributes', 4721*d289c2baSAndroid Build Coastguard Worker aliases=['make_atx_permanent_attributes'], 4722*d289c2baSAndroid Build Coastguard Worker help='Create avb_cert extension permanent attributes.') 4723*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4724*d289c2baSAndroid Build Coastguard Worker help='Write attributes to file', 4725*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb'), 4726*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4727*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--root_authority_key', 4728*d289c2baSAndroid Build Coastguard Worker help='Path to authority RSA public key file', 4729*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4730*d289c2baSAndroid Build Coastguard Worker required=True) 4731*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--product_id', 4732*d289c2baSAndroid Build Coastguard Worker help=('Path to Product ID file'), 4733*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4734*d289c2baSAndroid Build Coastguard Worker required=True) 4735*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.make_cert_permanent_attributes) 4736*d289c2baSAndroid Build Coastguard Worker 4737*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4738*d289c2baSAndroid Build Coastguard Worker 'make_cert_metadata', 4739*d289c2baSAndroid Build Coastguard Worker aliases=['make_atx_metadata'], 4740*d289c2baSAndroid Build Coastguard Worker help='Create avb_cert extension metadata.') 4741*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4742*d289c2baSAndroid Build Coastguard Worker help='Write metadata to file', 4743*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb'), 4744*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4745*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--intermediate_key_certificate', 4746*d289c2baSAndroid Build Coastguard Worker help='Path to intermediate key certificate file', 4747*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4748*d289c2baSAndroid Build Coastguard Worker required=True) 4749*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--product_key_certificate', 4750*d289c2baSAndroid Build Coastguard Worker help='Path to product key certificate file', 4751*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4752*d289c2baSAndroid Build Coastguard Worker required=True) 4753*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.make_cert_metadata) 4754*d289c2baSAndroid Build Coastguard Worker 4755*d289c2baSAndroid Build Coastguard Worker sub_parser = subparsers.add_parser( 4756*d289c2baSAndroid Build Coastguard Worker 'make_cert_unlock_credential', 4757*d289c2baSAndroid Build Coastguard Worker aliases=['make_atx_unlock_credential'], 4758*d289c2baSAndroid Build Coastguard Worker help='Create an avb_cert extension unlock credential.') 4759*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--output', 4760*d289c2baSAndroid Build Coastguard Worker help='Write credential to file', 4761*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('wb'), 4762*d289c2baSAndroid Build Coastguard Worker default=sys.stdout) 4763*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--intermediate_key_certificate', 4764*d289c2baSAndroid Build Coastguard Worker help='Path to intermediate key certificate file', 4765*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4766*d289c2baSAndroid Build Coastguard Worker required=True) 4767*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--unlock_key_certificate', 4768*d289c2baSAndroid Build Coastguard Worker help='Path to unlock key certificate file', 4769*d289c2baSAndroid Build Coastguard Worker type=argparse.FileType('rb'), 4770*d289c2baSAndroid Build Coastguard Worker required=True) 4771*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--challenge', 4772*d289c2baSAndroid Build Coastguard Worker help='Path to the challenge to sign (optional). If ' 4773*d289c2baSAndroid Build Coastguard Worker 'this is not provided the challenge signature ' 4774*d289c2baSAndroid Build Coastguard Worker 'field is omitted and can be concatenated ' 4775*d289c2baSAndroid Build Coastguard Worker 'later.', 4776*d289c2baSAndroid Build Coastguard Worker required=False) 4777*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--unlock_key', 4778*d289c2baSAndroid Build Coastguard Worker help='Path to unlock key (optional). Must be ' 4779*d289c2baSAndroid Build Coastguard Worker 'provided if using --challenge.', 4780*d289c2baSAndroid Build Coastguard Worker required=False) 4781*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--signing_helper', 4782*d289c2baSAndroid Build Coastguard Worker help='Path to helper used for signing', 4783*d289c2baSAndroid Build Coastguard Worker metavar='APP', 4784*d289c2baSAndroid Build Coastguard Worker default=None, 4785*d289c2baSAndroid Build Coastguard Worker required=False) 4786*d289c2baSAndroid Build Coastguard Worker sub_parser.add_argument('--signing_helper_with_files', 4787*d289c2baSAndroid Build Coastguard Worker help='Path to helper used for signing using files', 4788*d289c2baSAndroid Build Coastguard Worker metavar='APP', 4789*d289c2baSAndroid Build Coastguard Worker default=None, 4790*d289c2baSAndroid Build Coastguard Worker required=False) 4791*d289c2baSAndroid Build Coastguard Worker sub_parser.set_defaults(func=self.make_cert_unlock_credential) 4792*d289c2baSAndroid Build Coastguard Worker 4793*d289c2baSAndroid Build Coastguard Worker args = parser.parse_args(argv[1:]) 4794*d289c2baSAndroid Build Coastguard Worker try: 4795*d289c2baSAndroid Build Coastguard Worker args.func(args) 4796*d289c2baSAndroid Build Coastguard Worker except AttributeError: 4797*d289c2baSAndroid Build Coastguard Worker # This error gets raised when the command line tool is called without any 4798*d289c2baSAndroid Build Coastguard Worker # arguments. It mimics the original Python 2 behavior. 4799*d289c2baSAndroid Build Coastguard Worker parser.print_usage() 4800*d289c2baSAndroid Build Coastguard Worker print('avbtool: error: too few arguments') 4801*d289c2baSAndroid Build Coastguard Worker sys.exit(2) 4802*d289c2baSAndroid Build Coastguard Worker except AvbError as e: 4803*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('{}: {}\n'.format(argv[0], str(e))) 4804*d289c2baSAndroid Build Coastguard Worker sys.exit(1) 4805*d289c2baSAndroid Build Coastguard Worker 4806*d289c2baSAndroid Build Coastguard Worker def version(self, _): 4807*d289c2baSAndroid Build Coastguard Worker """Implements the 'version' sub-command.""" 4808*d289c2baSAndroid Build Coastguard Worker print(get_release_string()) 4809*d289c2baSAndroid Build Coastguard Worker 4810*d289c2baSAndroid Build Coastguard Worker def generate_test_image(self, args): 4811*d289c2baSAndroid Build Coastguard Worker """Implements the 'generate_test_image' sub-command.""" 4812*d289c2baSAndroid Build Coastguard Worker self.avb.generate_test_image(args.output, args.image_size, args.start_byte) 4813*d289c2baSAndroid Build Coastguard Worker 4814*d289c2baSAndroid Build Coastguard Worker def extract_public_key(self, args): 4815*d289c2baSAndroid Build Coastguard Worker """Implements the 'extract_public_key' sub-command.""" 4816*d289c2baSAndroid Build Coastguard Worker self.avb.extract_public_key(args.key, args.output) 4817*d289c2baSAndroid Build Coastguard Worker 4818*d289c2baSAndroid Build Coastguard Worker def make_vbmeta_image(self, args): 4819*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_vbmeta_image' sub-command.""" 4820*d289c2baSAndroid Build Coastguard Worker args = self._fixup_common_args(args) 4821*d289c2baSAndroid Build Coastguard Worker self.avb.make_vbmeta_image(args.output, args.chain_partition, 4822*d289c2baSAndroid Build Coastguard Worker args.chain_partition_do_not_use_ab, 4823*d289c2baSAndroid Build Coastguard Worker args.algorithm, args.key, 4824*d289c2baSAndroid Build Coastguard Worker args.public_key_metadata, args.rollback_index, 4825*d289c2baSAndroid Build Coastguard Worker args.flags, args.rollback_index_location, 4826*d289c2baSAndroid Build Coastguard Worker args.prop, args.prop_from_file, 4827*d289c2baSAndroid Build Coastguard Worker args.kernel_cmdline, 4828*d289c2baSAndroid Build Coastguard Worker args.setup_rootfs_from_kernel, 4829*d289c2baSAndroid Build Coastguard Worker args.include_descriptors_from_image, 4830*d289c2baSAndroid Build Coastguard Worker args.signing_helper, 4831*d289c2baSAndroid Build Coastguard Worker args.signing_helper_with_files, 4832*d289c2baSAndroid Build Coastguard Worker args.internal_release_string, 4833*d289c2baSAndroid Build Coastguard Worker args.append_to_release_string, 4834*d289c2baSAndroid Build Coastguard Worker args.print_required_libavb_version, 4835*d289c2baSAndroid Build Coastguard Worker args.padding_size) 4836*d289c2baSAndroid Build Coastguard Worker 4837*d289c2baSAndroid Build Coastguard Worker def append_vbmeta_image(self, args): 4838*d289c2baSAndroid Build Coastguard Worker """Implements the 'append_vbmeta_image' sub-command.""" 4839*d289c2baSAndroid Build Coastguard Worker self.avb.append_vbmeta_image(args.image.name, args.vbmeta_image.name, 4840*d289c2baSAndroid Build Coastguard Worker args.partition_size) 4841*d289c2baSAndroid Build Coastguard Worker 4842*d289c2baSAndroid Build Coastguard Worker def add_hash_footer(self, args): 4843*d289c2baSAndroid Build Coastguard Worker """Implements the 'add_hash_footer' sub-command.""" 4844*d289c2baSAndroid Build Coastguard Worker args = self._fixup_common_args(args) 4845*d289c2baSAndroid Build Coastguard Worker self.avb.add_hash_footer(args.image, 4846*d289c2baSAndroid Build Coastguard Worker args.partition_size, args.dynamic_partition_size, 4847*d289c2baSAndroid Build Coastguard Worker args.partition_name, args.hash_algorithm, 4848*d289c2baSAndroid Build Coastguard Worker args.salt, args.chain_partition, 4849*d289c2baSAndroid Build Coastguard Worker args.chain_partition_do_not_use_ab, 4850*d289c2baSAndroid Build Coastguard Worker args.algorithm, args.key, 4851*d289c2baSAndroid Build Coastguard Worker args.public_key_metadata, args.rollback_index, 4852*d289c2baSAndroid Build Coastguard Worker args.flags, args.rollback_index_location, 4853*d289c2baSAndroid Build Coastguard Worker args.prop, args.prop_from_file, 4854*d289c2baSAndroid Build Coastguard Worker args.kernel_cmdline, 4855*d289c2baSAndroid Build Coastguard Worker args.setup_rootfs_from_kernel, 4856*d289c2baSAndroid Build Coastguard Worker args.include_descriptors_from_image, 4857*d289c2baSAndroid Build Coastguard Worker args.calc_max_image_size, 4858*d289c2baSAndroid Build Coastguard Worker args.signing_helper, 4859*d289c2baSAndroid Build Coastguard Worker args.signing_helper_with_files, 4860*d289c2baSAndroid Build Coastguard Worker args.internal_release_string, 4861*d289c2baSAndroid Build Coastguard Worker args.append_to_release_string, 4862*d289c2baSAndroid Build Coastguard Worker args.output_vbmeta_image, 4863*d289c2baSAndroid Build Coastguard Worker args.do_not_append_vbmeta_image, 4864*d289c2baSAndroid Build Coastguard Worker args.print_required_libavb_version, 4865*d289c2baSAndroid Build Coastguard Worker args.use_persistent_digest, 4866*d289c2baSAndroid Build Coastguard Worker args.do_not_use_ab) 4867*d289c2baSAndroid Build Coastguard Worker 4868*d289c2baSAndroid Build Coastguard Worker def add_hashtree_footer(self, args): 4869*d289c2baSAndroid Build Coastguard Worker """Implements the 'add_hashtree_footer' sub-command.""" 4870*d289c2baSAndroid Build Coastguard Worker args = self._fixup_common_args(args) 4871*d289c2baSAndroid Build Coastguard Worker # TODO(zeuthen): Remove when removing support for the 4872*d289c2baSAndroid Build Coastguard Worker # '--generate_fec' option above. 4873*d289c2baSAndroid Build Coastguard Worker if args.generate_fec: 4874*d289c2baSAndroid Build Coastguard Worker sys.stderr.write('The --generate_fec option is deprecated since FEC ' 4875*d289c2baSAndroid Build Coastguard Worker 'is now generated by default. Use the option ' 4876*d289c2baSAndroid Build Coastguard Worker '--do_not_generate_fec to not generate FEC.\n') 4877*d289c2baSAndroid Build Coastguard Worker if args.hash_algorithm == '': 4878*d289c2baSAndroid Build Coastguard Worker args.hash_algorithm = 'sha1' 4879*d289c2baSAndroid Build Coastguard Worker # In --calc_max_image_size mode don't show the sha1 warning, since sha1 4880*d289c2baSAndroid Build Coastguard Worker # digests get padded to the same size as sha256 anyway. 4881*d289c2baSAndroid Build Coastguard Worker if not args.calc_max_image_size: 4882*d289c2baSAndroid Build Coastguard Worker sys.stderr.write( 4883*d289c2baSAndroid Build Coastguard Worker"""Warning: 'avbtool add_hashtree_footer' executed without an explicit 4884*d289c2baSAndroid Build Coastguard Worker--hash_algorithm option. Defaulting to sha1 for backwards compatibility. 4885*d289c2baSAndroid Build Coastguard WorkerPlease use '--hash_algorithm sha256'. 4886*d289c2baSAndroid Build Coastguard Worker""") 4887*d289c2baSAndroid Build Coastguard Worker self.avb.add_hashtree_footer( 4888*d289c2baSAndroid Build Coastguard Worker args.image.name if args.image else None, 4889*d289c2baSAndroid Build Coastguard Worker args.partition_size, 4890*d289c2baSAndroid Build Coastguard Worker args.partition_name, 4891*d289c2baSAndroid Build Coastguard Worker not args.do_not_generate_fec, args.fec_num_roots, 4892*d289c2baSAndroid Build Coastguard Worker args.hash_algorithm, args.block_size, 4893*d289c2baSAndroid Build Coastguard Worker args.salt, args.chain_partition, 4894*d289c2baSAndroid Build Coastguard Worker args.chain_partition_do_not_use_ab, 4895*d289c2baSAndroid Build Coastguard Worker args.algorithm, 4896*d289c2baSAndroid Build Coastguard Worker args.key, args.public_key_metadata, 4897*d289c2baSAndroid Build Coastguard Worker args.rollback_index, args.flags, 4898*d289c2baSAndroid Build Coastguard Worker args.rollback_index_location, args.prop, 4899*d289c2baSAndroid Build Coastguard Worker args.prop_from_file, 4900*d289c2baSAndroid Build Coastguard Worker args.kernel_cmdline, 4901*d289c2baSAndroid Build Coastguard Worker args.setup_rootfs_from_kernel, 4902*d289c2baSAndroid Build Coastguard Worker args.setup_as_rootfs_from_kernel, 4903*d289c2baSAndroid Build Coastguard Worker args.include_descriptors_from_image, 4904*d289c2baSAndroid Build Coastguard Worker args.calc_max_image_size, 4905*d289c2baSAndroid Build Coastguard Worker args.signing_helper, 4906*d289c2baSAndroid Build Coastguard Worker args.signing_helper_with_files, 4907*d289c2baSAndroid Build Coastguard Worker args.internal_release_string, 4908*d289c2baSAndroid Build Coastguard Worker args.append_to_release_string, 4909*d289c2baSAndroid Build Coastguard Worker args.output_vbmeta_image, 4910*d289c2baSAndroid Build Coastguard Worker args.do_not_append_vbmeta_image, 4911*d289c2baSAndroid Build Coastguard Worker args.print_required_libavb_version, 4912*d289c2baSAndroid Build Coastguard Worker args.use_persistent_digest, 4913*d289c2baSAndroid Build Coastguard Worker args.do_not_use_ab, 4914*d289c2baSAndroid Build Coastguard Worker args.no_hashtree, 4915*d289c2baSAndroid Build Coastguard Worker args.check_at_most_once) 4916*d289c2baSAndroid Build Coastguard Worker 4917*d289c2baSAndroid Build Coastguard Worker def erase_footer(self, args): 4918*d289c2baSAndroid Build Coastguard Worker """Implements the 'erase_footer' sub-command.""" 4919*d289c2baSAndroid Build Coastguard Worker self.avb.erase_footer(args.image.name, args.keep_hashtree) 4920*d289c2baSAndroid Build Coastguard Worker 4921*d289c2baSAndroid Build Coastguard Worker def zero_hashtree(self, args): 4922*d289c2baSAndroid Build Coastguard Worker """Implements the 'zero_hashtree' sub-command.""" 4923*d289c2baSAndroid Build Coastguard Worker self.avb.zero_hashtree(args.image.name) 4924*d289c2baSAndroid Build Coastguard Worker 4925*d289c2baSAndroid Build Coastguard Worker def extract_vbmeta_image(self, args): 4926*d289c2baSAndroid Build Coastguard Worker """Implements the 'extract_vbmeta_image' sub-command.""" 4927*d289c2baSAndroid Build Coastguard Worker self.avb.extract_vbmeta_image(args.output, args.image.name, 4928*d289c2baSAndroid Build Coastguard Worker args.padding_size) 4929*d289c2baSAndroid Build Coastguard Worker 4930*d289c2baSAndroid Build Coastguard Worker def resize_image(self, args): 4931*d289c2baSAndroid Build Coastguard Worker """Implements the 'resize_image' sub-command.""" 4932*d289c2baSAndroid Build Coastguard Worker self.avb.resize_image(args.image.name, args.partition_size) 4933*d289c2baSAndroid Build Coastguard Worker 4934*d289c2baSAndroid Build Coastguard Worker def set_ab_metadata(self, args): 4935*d289c2baSAndroid Build Coastguard Worker """Implements the 'set_ab_metadata' sub-command.""" 4936*d289c2baSAndroid Build Coastguard Worker self.avb.set_ab_metadata(args.misc_image, args.slot_data) 4937*d289c2baSAndroid Build Coastguard Worker 4938*d289c2baSAndroid Build Coastguard Worker def info_image(self, args): 4939*d289c2baSAndroid Build Coastguard Worker """Implements the 'info_image' sub-command.""" 4940*d289c2baSAndroid Build Coastguard Worker self.avb.info_image(args.image.name, args.output, args.cert) 4941*d289c2baSAndroid Build Coastguard Worker 4942*d289c2baSAndroid Build Coastguard Worker def verify_image(self, args): 4943*d289c2baSAndroid Build Coastguard Worker """Implements the 'verify_image' sub-command.""" 4944*d289c2baSAndroid Build Coastguard Worker self.avb.verify_image(args.image.name, args.key, 4945*d289c2baSAndroid Build Coastguard Worker args.expected_chain_partition, 4946*d289c2baSAndroid Build Coastguard Worker args.follow_chain_partitions, 4947*d289c2baSAndroid Build Coastguard Worker args.accept_zeroed_hashtree) 4948*d289c2baSAndroid Build Coastguard Worker 4949*d289c2baSAndroid Build Coastguard Worker def print_partition_digests(self, args): 4950*d289c2baSAndroid Build Coastguard Worker """Implements the 'print_partition_digests' sub-command.""" 4951*d289c2baSAndroid Build Coastguard Worker self.avb.print_partition_digests(args.image.name, args.output, args.json) 4952*d289c2baSAndroid Build Coastguard Worker 4953*d289c2baSAndroid Build Coastguard Worker def calculate_vbmeta_digest(self, args): 4954*d289c2baSAndroid Build Coastguard Worker """Implements the 'calculate_vbmeta_digest' sub-command.""" 4955*d289c2baSAndroid Build Coastguard Worker self.avb.calculate_vbmeta_digest(args.image.name, args.hash_algorithm, 4956*d289c2baSAndroid Build Coastguard Worker args.output) 4957*d289c2baSAndroid Build Coastguard Worker 4958*d289c2baSAndroid Build Coastguard Worker def calculate_kernel_cmdline(self, args): 4959*d289c2baSAndroid Build Coastguard Worker """Implements the 'calculate_kernel_cmdline' sub-command.""" 4960*d289c2baSAndroid Build Coastguard Worker self.avb.calculate_kernel_cmdline(args.image.name, args.hashtree_disabled, 4961*d289c2baSAndroid Build Coastguard Worker args.output) 4962*d289c2baSAndroid Build Coastguard Worker 4963*d289c2baSAndroid Build Coastguard Worker def make_certificate(self, args): 4964*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_certificate' sub-command.""" 4965*d289c2baSAndroid Build Coastguard Worker # argparse mutually exclusive group ensures that at most one of the usage 4966*d289c2baSAndroid Build Coastguard Worker # args will exist. If none exist, default to signing usage. 4967*d289c2baSAndroid Build Coastguard Worker usage = (args.subject_is_intermediate_authority or args.usage or 4968*d289c2baSAndroid Build Coastguard Worker args.usage_for_unlock or CERT_USAGE_SIGNING) 4969*d289c2baSAndroid Build Coastguard Worker self.avb.make_certificate(args.output, args.authority_key, 4970*d289c2baSAndroid Build Coastguard Worker args.subject_key.name, 4971*d289c2baSAndroid Build Coastguard Worker args.subject_key_version, 4972*d289c2baSAndroid Build Coastguard Worker args.subject.read(), 4973*d289c2baSAndroid Build Coastguard Worker usage, 4974*d289c2baSAndroid Build Coastguard Worker args.signing_helper, 4975*d289c2baSAndroid Build Coastguard Worker args.signing_helper_with_files) 4976*d289c2baSAndroid Build Coastguard Worker 4977*d289c2baSAndroid Build Coastguard Worker def make_cert_permanent_attributes(self, args): 4978*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_cert_permanent_attributes' sub-command.""" 4979*d289c2baSAndroid Build Coastguard Worker self.avb.make_cert_permanent_attributes(args.output, 4980*d289c2baSAndroid Build Coastguard Worker args.root_authority_key.name, 4981*d289c2baSAndroid Build Coastguard Worker args.product_id.read()) 4982*d289c2baSAndroid Build Coastguard Worker 4983*d289c2baSAndroid Build Coastguard Worker def make_cert_metadata(self, args): 4984*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_cert_metadata' sub-command.""" 4985*d289c2baSAndroid Build Coastguard Worker self.avb.make_cert_metadata(args.output, 4986*d289c2baSAndroid Build Coastguard Worker args.intermediate_key_certificate.read(), 4987*d289c2baSAndroid Build Coastguard Worker args.product_key_certificate.read()) 4988*d289c2baSAndroid Build Coastguard Worker 4989*d289c2baSAndroid Build Coastguard Worker def make_cert_unlock_credential(self, args): 4990*d289c2baSAndroid Build Coastguard Worker """Implements the 'make_cert_unlock_credential' sub-command.""" 4991*d289c2baSAndroid Build Coastguard Worker self.avb.make_cert_unlock_credential( 4992*d289c2baSAndroid Build Coastguard Worker args.output, 4993*d289c2baSAndroid Build Coastguard Worker args.intermediate_key_certificate.read(), 4994*d289c2baSAndroid Build Coastguard Worker args.unlock_key_certificate.read(), 4995*d289c2baSAndroid Build Coastguard Worker args.challenge, 4996*d289c2baSAndroid Build Coastguard Worker args.unlock_key, 4997*d289c2baSAndroid Build Coastguard Worker args.signing_helper, 4998*d289c2baSAndroid Build Coastguard Worker args.signing_helper_with_files) 4999*d289c2baSAndroid Build Coastguard Worker 5000*d289c2baSAndroid Build Coastguard Worker 5001*d289c2baSAndroid Build Coastguard Workerif __name__ == '__main__': 5002*d289c2baSAndroid Build Coastguard Worker if AVB_INVOCATION_LOGFILE: 5003*d289c2baSAndroid Build Coastguard Worker with open(AVB_INVOCATION_LOGFILE, 'a') as log: 5004*d289c2baSAndroid Build Coastguard Worker log.write(' '.join(sys.argv)) 5005*d289c2baSAndroid Build Coastguard Worker log.write('\n') 5006*d289c2baSAndroid Build Coastguard Worker 5007*d289c2baSAndroid Build Coastguard Worker tool = AvbTool() 5008*d289c2baSAndroid Build Coastguard Worker tool.run(sys.argv) 5009