Geremy Condra | 649fd55 | 2013-10-21 20:34:13 +0000 | [diff] [blame^] | 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 + (METADATA_SIZE / BLOCK_SIZE), |
| 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) |