xref: /openbmc/u-boot/tools/binman/etype/vblock.py (revision 23e8bd7e)
1# SPDX-License-Identifier: GPL-2.0+
2# Copyright (c) 2018 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
5
6# Support for a Chromium OS verified boot block, used to sign a read-write
7# section of the image.
8
9from collections import OrderedDict
10import os
11
12from entry import Entry, EntryArg
13
14import fdt_util
15import tools
16
17class Entry_vblock(Entry):
18    """An entry which contains a Chromium OS verified boot block
19
20    Properties / Entry arguments:
21        - keydir: Directory containing the public keys to use
22        - keyblock: Name of the key file to use (inside keydir)
23        - signprivate: Name of provide key file to use (inside keydir)
24        - version: Version number of the vblock (typically 1)
25        - kernelkey: Name of the kernel key to use (inside keydir)
26        - preamble-flags: Value of the vboot preamble flags (typically 0)
27
28    Output files:
29        - input.<unique_name> - input file passed to futility
30        - vblock.<unique_name> - output file generated by futility (which is
31            used as the entry contents)
32
33    Chromium OS signs the read-write firmware and kernel, writing the signature
34    in this block. This allows U-Boot to verify that the next firmware stage
35    and kernel are genuine.
36    """
37    def __init__(self, section, etype, node):
38        Entry.__init__(self, section, etype, node)
39        self.content = fdt_util.GetPhandleList(self._node, 'content')
40        if not self.content:
41            self.Raise("Vblock must have a 'content' property")
42        (self.keydir, self.keyblock, self.signprivate, self.version,
43         self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
44            EntryArg('keydir', str),
45            EntryArg('keyblock', str),
46            EntryArg('signprivate', str),
47            EntryArg('version', int),
48            EntryArg('kernelkey', str),
49            EntryArg('preamble-flags', int)])
50
51    def ObtainContents(self):
52        # Join up the data files to be signed
53        input_data = ''
54        for entry_phandle in self.content:
55            data = self.section.GetContentsByPhandle(entry_phandle, self)
56            if data is None:
57                # Data not available yet
58                return False
59            input_data += data
60
61        uniq = self.GetUniqueName()
62        output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
63        input_fname = tools.GetOutputFilename('input.%s' % uniq)
64        tools.WriteFile(input_fname, input_data)
65        prefix = self.keydir + '/'
66        args = [
67            'vbutil_firmware',
68            '--vblock', output_fname,
69            '--keyblock', prefix + self.keyblock,
70            '--signprivate', prefix + self.signprivate,
71            '--version', '%d' % self.version,
72            '--fv', input_fname,
73            '--kernelkey', prefix + self.kernelkey,
74            '--flags', '%d' % self.preamble_flags,
75        ]
76        #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
77        stdout = tools.Run('futility', *args)
78        self.SetContents(tools.ReadFile(output_fname))
79        return True
80