vblock.py 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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 binman.entry import EntryArg
  10. from binman.etype.collection import Entry_collection
  11. from dtoc import fdt_util
  12. from patman import tools
  13. class Entry_vblock(Entry_collection):
  14. """An entry which contains a Chromium OS verified boot block
  15. Properties / Entry arguments:
  16. - content: List of phandles to entries to sign
  17. - keydir: Directory containing the public keys to use
  18. - keyblock: Name of the key file to use (inside keydir)
  19. - signprivate: Name of provide key file to use (inside keydir)
  20. - version: Version number of the vblock (typically 1)
  21. - kernelkey: Name of the kernel key to use (inside keydir)
  22. - preamble-flags: Value of the vboot preamble flags (typically 0)
  23. Output files:
  24. - input.<unique_name> - input file passed to futility
  25. - vblock.<unique_name> - output file generated by futility (which is
  26. used as the entry contents)
  27. Chromium OS signs the read-write firmware and kernel, writing the signature
  28. in this block. This allows U-Boot to verify that the next firmware stage
  29. and kernel are genuine.
  30. """
  31. def __init__(self, section, etype, node):
  32. super().__init__(section, etype, node)
  33. (self.keydir, self.keyblock, self.signprivate, self.version,
  34. self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([
  35. EntryArg('keydir', str),
  36. EntryArg('keyblock', str),
  37. EntryArg('signprivate', str),
  38. EntryArg('version', int),
  39. EntryArg('kernelkey', str),
  40. EntryArg('preamble-flags', int)])
  41. def GetVblock(self, required):
  42. """Get the contents of this entry
  43. Args:
  44. required: True if the data must be present, False if it is OK to
  45. return None
  46. Returns:
  47. bytes content of the entry, which is the signed vblock for the
  48. provided data
  49. """
  50. # Join up the data files to be signed
  51. input_data = self.GetContents(required)
  52. if input_data is None:
  53. return None
  54. uniq = self.GetUniqueName()
  55. output_fname = tools.GetOutputFilename('vblock.%s' % uniq)
  56. input_fname = tools.GetOutputFilename('input.%s' % uniq)
  57. tools.WriteFile(input_fname, input_data)
  58. prefix = self.keydir + '/'
  59. args = [
  60. 'vbutil_firmware',
  61. '--vblock', output_fname,
  62. '--keyblock', prefix + self.keyblock,
  63. '--signprivate', prefix + self.signprivate,
  64. '--version', '%d' % self.version,
  65. '--fv', input_fname,
  66. '--kernelkey', prefix + self.kernelkey,
  67. '--flags', '%d' % self.preamble_flags,
  68. ]
  69. #out.Notice("Sign '%s' into %s" % (', '.join(self.value), self.label))
  70. stdout = tools.Run('futility', *args)
  71. return tools.ReadFile(output_fname)
  72. def ObtainContents(self):
  73. data = self.GetVblock(False)
  74. if data is None:
  75. return False
  76. self.SetContents(data)
  77. return True
  78. def ProcessContents(self):
  79. # The blob may have changed due to WriteSymbols()
  80. data = self.GetVblock(True)
  81. return self.ProcessContentsUpdate(data)