blob: d421523995a664b58a3cd64bda9eb35c043bef8d [file] [log] [blame]
Yilin Yang19da6932019-12-10 13:39:28 +08001#!/usr/bin/env python3
Hung-Te Lin1990b742017-08-09 17:34:57 +08002# Copyright 2011 The Chromium OS Authors. All rights reserved.
Hung-Te Linc83105f2011-03-16 18:38:04 +08003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6# THIS FILE IS COPIED FROM AUTOTEST LIBRARY AND FOLLOWING PEP8 CODING STYLE RULE
7# FOR BACKWARD COMPATIBLE, WE'RE NOT CHANGING ITS INDENTATION AND FUNCTION NAMES
8
9"""
10 Chrome OS firmware verification block parser.
11
12 This module helps parsing firmware verification blocks so that we can
13 retrieve the version and other information from a blob.
14
15 See help(unpack_verification_block) for more information.
16
17 ref: src/platform/vboot_reference/firmware/lib/include/vboot_struct.h
18"""
19
20import struct
21import sys
22
23# Constant Definition
Hung-Te Lin56b18402015-01-16 14:52:30 +080024KEY_BLOCK_MAGIC = 'CHROMEOS'
Hung-Te Linc83105f2011-03-16 18:38:04 +080025KEY_BLOCK_MAGIC_SIZE = 8
26KEY_BLOCK_HEADER_VERSION_MAJOR = 2
27KEY_BLOCK_HEADER_VERSION_MINOR = 1
28FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR = 2
29FIRMWARE_PREAMBLE_HEADER_VERSION_MINOR = 0
30
31
32def unpack_VbKeyBlockHeader(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +080033 """Unpacks a VbKeyBlockHeader from a blob, starting from offset.
Hung-Te Linc83105f2011-03-16 18:38:04 +080034
Hung-Te Lin56b18402015-01-16 14:52:30 +080035 The blob is supposed to be a VBLOCK_A or VBLOCK_A in firmware image.
36 Blob structure:
37 typedef struct VbKeyBlockHeader {
38 uint8_t magic[KEY_BLOCK_MAGIC_SIZE];
39 uint32_t header_version_major;
40 uint32_t header_version_minor;
41 uint64_t key_block_size;
42 ...
43 };
44 """
45 fields = struct.unpack_from('<8sIIQ', blob, offset)
46 names = ('magic', 'header_version_major', 'header_version_minor',
47 'key_block_size')
48 header = dict(zip(names, fields))
49 # check values
50 if header['magic'] != KEY_BLOCK_MAGIC:
Hung-Te Lineec4e332017-06-01 23:16:40 +080051 raise ValueError('unknown key block magic: %s' % header['magic'])
Hung-Te Lin56b18402015-01-16 14:52:30 +080052 major = header['header_version_major']
53 minor = header['header_version_minor']
Hung-Te Lineec4e332017-06-01 23:16:40 +080054 if major != KEY_BLOCK_HEADER_VERSION_MAJOR:
55 raise ValueError('unknown key block version (%d.%d)' % (major, minor))
Hung-Te Lin56b18402015-01-16 14:52:30 +080056 return header
Hung-Te Linc83105f2011-03-16 18:38:04 +080057
58
59def unpack_VbFirmwarePreambleHeader(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +080060 """Unpacks a VbFirmwarePreambleHeader from a blob, starting from offset.
Hung-Te Linc83105f2011-03-16 18:38:04 +080061
Hung-Te Lin56b18402015-01-16 14:52:30 +080062 The blob is supposed to be located immediately after a VbKeyBlockHeader.
63 (i.e., offset = VbKeyBlockHeader[key_block_size])
64 Blob structure:
65 typedef struct VbFirmwarePreambleHeader {
66 uint64_t preamble_size;
67 struct VbSignature preamble_signature {
68 uint64_t sig_offset;
69 uint64_t sig_size;
70 uint64_t data_size;
71 };
72 uint32_t header_version_major;
73 uint32_t header_version_minor;
74 uint64_t firmware_version;
75 ...
76 };
77 """
78 fields = struct.unpack_from('<QQQQIIQ', blob, offset)
79 names = ('preamble_size',
80 'sig_offset', 'sig_size', 'data_size',
81 'header_version_major', 'header_version_minor',
82 'firmware_version')
83 header = dict(zip(names, fields))
84 # check values
85 major = header['header_version_major']
86 minor = header['header_version_minor']
87 if major != FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR:
Hung-Te Lineec4e332017-06-01 23:16:40 +080088 raise ValueError('unknown preamble version: (%d.%d)' % (major, minor))
Hung-Te Lin56b18402015-01-16 14:52:30 +080089 return header
Hung-Te Linc83105f2011-03-16 18:38:04 +080090
91
92def unpack_verification_block(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +080093 """Unpacks a Chrome OS verification block.
Hung-Te Linc83105f2011-03-16 18:38:04 +080094
Hung-Te Lin56b18402015-01-16 14:52:30 +080095 Returns a dictionary of VbKeyBlockHeader and VbFirmwarePreambleHeader.
Hung-Te Linc83105f2011-03-16 18:38:04 +080096
Hung-Te Lin56b18402015-01-16 14:52:30 +080097 Use help(unpack_VbKeyBlockHeader) and help(unpack_VbFirmwarePreambleHeader)
98 for more detail information.
99 """
100 result = {}
101 result['VbKeyBlockHeader'] = unpack_VbKeyBlockHeader(blob, offset)
102 result['VbFirmwarePreambleHeader'] = unpack_VbFirmwarePreambleHeader(
103 blob, result['VbKeyBlockHeader']['key_block_size'])
104 return result
Hung-Te Linc83105f2011-03-16 18:38:04 +0800105
106
107# -----------------------------------------------------------------------------
108
109
110def test_report_vblock_info(blob, offset=0):
Hung-Te Lin56b18402015-01-16 14:52:30 +0800111 """ Reports the information of a vblock blob. """
112 kb_header = unpack_VbKeyBlockHeader(blob, offset)
Yilin Yang71e39412019-09-24 09:26:46 +0800113 print('-- VbKeyBlockHeader --')
Hung-Te Lin56b18402015-01-16 14:52:30 +0800114 for name, value in kb_header.items():
Yilin Yang71e39412019-09-24 09:26:46 +0800115 print(name, ':', value)
Hung-Te Lin56b18402015-01-16 14:52:30 +0800116 preamble = unpack_VbFirmwarePreambleHeader(blob,
117 kb_header['key_block_size'])
Yilin Yang71e39412019-09-24 09:26:46 +0800118 print('-- VbFirmwarePreambleHeader --')
Hung-Te Lin56b18402015-01-16 14:52:30 +0800119 for name, value in preamble.items():
Yilin Yang71e39412019-09-24 09:26:46 +0800120 print(name, ':', value)
121 print('-- END --')
Hung-Te Linc83105f2011-03-16 18:38:04 +0800122
123
124# main stub
Hung-Te Lin56b18402015-01-16 14:52:30 +0800125if __name__ == '__main__':
126 # when running in command line, try to report blob in the parameters
127 for filename in sys.argv[1:]:
128 test_report_vblock_info(open(filename, 'rb').read())