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