1 #! /usr/bin/env python 2 3 import os 4 import sys 5 import struct 6 import tempfile 7 import commands 8 9 VERSION = 0 10 MAGIC_NUMBER = 0xb001b001 11 BLOCK_SIZE = 4096 12 METADATA_SIZE = BLOCK_SIZE * 8 13 14 def run(cmd): 15 status, output = commands.getstatusoutput(cmd) 16 print output 17 if status: 18 exit(-1) 19 20 def get_verity_metadata_size(data_size): 21 return METADATA_SIZE 22 23 def build_metadata_block(verity_table, signature): 24 table_len = len(verity_table) 25 block = struct.pack("II256sI", MAGIC_NUMBER, VERSION, signature, table_len) 26 block += verity_table 27 block = block.ljust(METADATA_SIZE, '\x00') 28 return block 29 30 def sign_verity_table(table, signer_path, key_path): 31 with tempfile.NamedTemporaryFile(suffix='.table') as table_file: 32 with tempfile.NamedTemporaryFile(suffix='.sig') as signature_file: 33 table_file.write(table) 34 table_file.flush() 35 cmd = " ".join((signer_path, table_file.name, key_path, signature_file.name)) 36 print cmd 37 run(cmd) 38 return signature_file.read() 39 40 def build_verity_table(block_device, data_blocks, root_hash, salt): 41 table = "1 %s %s %s %s %s %s sha256 %s %s" 42 table %= ( block_device, 43 block_device, 44 BLOCK_SIZE, 45 BLOCK_SIZE, 46 data_blocks, 47 data_blocks, 48 root_hash, 49 salt) 50 return table 51 52 def build_verity_metadata(data_blocks, metadata_image, root_hash, 53 salt, block_device, signer_path, signing_key): 54 # build the verity table 55 verity_table = build_verity_table(block_device, data_blocks, root_hash, salt) 56 # build the verity table signature 57 signature = sign_verity_table(verity_table, signer_path, signing_key) 58 # build the metadata block 59 metadata_block = build_metadata_block(verity_table, signature) 60 # write it to the outfile 61 with open(metadata_image, "wb") as f: 62 f.write(metadata_block) 63 64 if __name__ == "__main__": 65 if len(sys.argv) == 3 and sys.argv[1] == "-s": 66 print get_verity_metadata_size(int(sys.argv[2])) 67 elif len(sys.argv) == 8: 68 data_image_blocks = int(sys.argv[1]) / 4096 69 metadata_image = sys.argv[2] 70 root_hash = sys.argv[3] 71 salt = sys.argv[4] 72 block_device = sys.argv[5] 73 signer_path = sys.argv[6] 74 signing_key = sys.argv[7] 75 build_verity_metadata(data_image_blocks, metadata_image, root_hash, 76 salt, block_device, signer_path, signing_key) 77 else: 78 exit(-1) 79