xref: /openbmc/u-boot/tools/binman/etype/vblock.py (revision d24c1d0f4da3b081a4fedf7ae2a08790871f08d0)
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 
9 from collections import OrderedDict
10 import os
11 
12 from entry import Entry, EntryArg
13 
14 import fdt_util
15 import tools
16 
17 class 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