vblock.py 3.0 KB

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