blob: 33ee62ffc832fe7cea8233ac1f212a3650d4d6dc [file] [log] [blame]
Cheng-Han Yang8d2fd502020-08-09 03:43:16 +08001#!/usr/bin/env python3
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Chrome OS GBB parser.
7
8This module helps parsing GBB so that we can retrieve the HWID and other
9information from a blob.
10
11ref: src/platform/vboot_reference/firmware/2lib/include/2struct.h
12"""
13
14import collections
15import struct
16import sys
17
18
19GBBContent = collections.namedtuple(
20 'GBBContent', ['hwid', 'hwid_digest', 'rootkey', 'recovery_key'])
21GBBField = collections.namedtuple('GBBField', ['value', 'offset', 'size'])
22
23
24# constant definition
25GBB_SIGNATURE = b'$GBB'
26GBB_SIGNATURE_SIZE = 4
27GBB_HWID_DIGEST_OFFSET = 48 # bytes before HWID digest section in the header
28GBB_HWID_DIGEST_SIZE = 32
29
30
31# blob structure
32# struct vb2_gbb_header {
33# uint8_t signature[VB2_GBB_SIGNATURE_SIZE];
34# uint16_t major_version;
35# uint16_t minor_version;
36# uint32_t header_size;
37# vb2_gbb_flags_t flags;
38# uint32_t hwid_offset;
39# uint32_t hwid_size;
40# uint32_t rootkey_offset;
41# uint32_t rootkey_size;
42# uint32_t bmpfv_offset;
43# uint32_t bmpfv_size;
44# uint32_t recovery_key_offset;
45# uint32_t recovery_key_size;
46# uint8_t hwid_digest[VB2_GBB_HWID_DIGEST_SIZE];
47# uint8_t pad[48];
48# };
49
50
51GBBHeader = collections.namedtuple('GBBHeader', [
52 'signature',
53 'major_version',
54 'minor_version',
55 'header_size',
56 'flags',
57 'hwid_offset',
58 'hwid_size',
59 'rootkey_offset',
60 'rootkey_size',
61 'bmpfw_offset',
62 'bmpfw_size',
63 'recovery_key_offset',
64 'recovery_key_size',
65 'hwid_digest'])
66FORMAT_GBB_HEADER = '<4sHHIIIIIIIIII32s48x'
67
68
69def UnpackGBBHeader(blob, offset=0):
70 """Unpacks a GBB header from a blob, starting from offset."""
71 header = GBBHeader(*struct.unpack_from(FORMAT_GBB_HEADER, blob, offset))
72 # Check signature.
73 if header.signature != GBB_SIGNATURE:
74 raise ValueError('unknown GBB signature: %s' % header.signature)
75 return header
76
77
78def UnpackHWID(blob, base, header):
79 """Unpacks HWID section."""
80 offset = base + header.hwid_offset
81 size = header.hwid_size
82 return GBBField(
83 blob[offset:offset + size].strip(b'\x00').decode('UTF-8'),
84 offset,
85 size)
86
87
88def UnpackHWIDDigest(base, header):
89 """Unpacks HWID digest section."""
90 offset = base + GBB_HWID_DIGEST_OFFSET
91 size = GBB_HWID_DIGEST_SIZE
92 return GBBField(header.hwid_digest.hex(), offset, size)
93
94
95def UnpackRootKey(blob, base, header):
96 """Unpacks root key section."""
97 offset = base + header.rootkey_offset
98 size = header.rootkey_size
99 return GBBField(blob[offset:offset + size], offset, size)
100
101
102def UnpackRecoveryKey(blob, base, header):
103 """Unpacks recovery key section."""
104 offset = base + header.recovery_key_offset
105 size = header.recovery_key_size
106 return GBBField(blob[offset:offset + size], offset, size)
107
108
109def UnpackGBB(blob, offset=0):
110 """Unpacks a Chrome OS GBB.
111
112 Returns a GBBContent instance containing the unpacked data.
113 """
114 header = UnpackGBBHeader(blob, offset)
115 content = GBBContent(
116 hwid=UnpackHWID(blob, offset, header),
117 hwid_digest=UnpackHWIDDigest(offset, header),
118 rootkey=UnpackRootKey(blob, offset, header),
119 recovery_key=UnpackRecoveryKey(blob, offset, header))
120
121 return content
122
123
124def main():
125 # Only load pprint if we are in console (debug / test) mode.
126 import pprint
127 for filename in sys.argv[1:]:
128 gbb = UnpackGBB(open(filename, 'rb').read(), 0)
129 print(pprint.pformat(gbb))
130
131
132# When running in command line, try to report blob in the parameters.
133if __name__ == '__main__':
134 main()