mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-09-21 07:01:57 +00:00
binman: Support hashing entries
Sometimesi it us useful to be able to verify the content of entries with a hash. Add an easy way to do this in binman. The hash information can be retrieved from the device tree at run time. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
9c888cca5e
commit
e0e5df9310
9 changed files with 143 additions and 0 deletions
|
@ -466,6 +466,28 @@ see README.entries. This is generated from the source code using:
|
|||
binman -E >tools/binman/README.entries
|
||||
|
||||
|
||||
Hashing Entries
|
||||
---------------
|
||||
|
||||
It is possible to ask binman to hash the contents of an entry and write that
|
||||
value back to the device-tree node. For example:
|
||||
|
||||
binman {
|
||||
u-boot {
|
||||
hash {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Here, a new 'value' property will be written to the 'hash' node containing
|
||||
the hash of the 'u-boot' entry. Only SHA256 is supported at present. Whole
|
||||
sections can be hased if desired, by adding the 'hash' node to the section.
|
||||
|
||||
The has value can be chcked at runtime by hashing the data actually read and
|
||||
comparing this has to the value in the device tree.
|
||||
|
||||
|
||||
Order of image creation
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ class Section(object):
|
|||
|
||||
def _ReadEntries(self):
|
||||
for node in self._node.subnodes:
|
||||
if node.name == 'hash':
|
||||
continue
|
||||
entry = Entry.Create(self, node)
|
||||
entry.SetPrefix(self._name_prefix)
|
||||
self._entries[node.name] = entry
|
||||
|
@ -112,6 +114,7 @@ class Section(object):
|
|||
for prop in ['offset', 'size', 'image-pos']:
|
||||
if not prop in self._node.props:
|
||||
state.AddZeroProp(self._node, prop)
|
||||
state.CheckAddHashProp(self._node)
|
||||
for entry in self._entries.values():
|
||||
entry.AddMissingProperties()
|
||||
|
||||
|
|
|
@ -189,12 +189,16 @@ class Entry(object):
|
|||
for prop in ['offset', 'size', 'image-pos']:
|
||||
if not prop in self._node.props:
|
||||
state.AddZeroProp(self._node, prop)
|
||||
err = state.CheckAddHashProp(self._node)
|
||||
if err:
|
||||
self.Raise(err)
|
||||
|
||||
def SetCalculatedProperties(self):
|
||||
"""Set the value of device-tree properties calculated by binman"""
|
||||
state.SetInt(self._node, 'offset', self.offset)
|
||||
state.SetInt(self._node, 'size', self.size)
|
||||
state.SetInt(self._node, 'image-pos', self.image_pos)
|
||||
state.CheckSetHashValue(self._node, self.GetData)
|
||||
|
||||
def ProcessFdt(self, fdt):
|
||||
"""Allow entries to adjust the device tree
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#
|
||||
# python -m unittest func_test.TestFunctional.testHelp
|
||||
|
||||
import hashlib
|
||||
from optparse import OptionParser
|
||||
import os
|
||||
import shutil
|
||||
|
@ -1608,6 +1609,41 @@ class TestFunctional(unittest.TestCase):
|
|||
self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
|
||||
'expanding entry', str(e.exception))
|
||||
|
||||
def testHash(self):
|
||||
"""Test hashing of the contents of an entry"""
|
||||
_, _, _, out_dtb_fname = self._DoReadFileDtb('90_hash.dts',
|
||||
use_real_dtb=True, update_dtb=True)
|
||||
dtb = fdt.Fdt(out_dtb_fname)
|
||||
dtb.Scan()
|
||||
hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
|
||||
m = hashlib.sha256()
|
||||
m.update(U_BOOT_DATA)
|
||||
self.assertEqual(m.digest(), ''.join(hash_node.value))
|
||||
|
||||
def testHashNoAlgo(self):
|
||||
with self.assertRaises(ValueError) as e:
|
||||
self._DoReadFileDtb('91_hash_no_algo.dts', update_dtb=True)
|
||||
self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
|
||||
'hash node', str(e.exception))
|
||||
|
||||
def testHashBadAlgo(self):
|
||||
with self.assertRaises(ValueError) as e:
|
||||
self._DoReadFileDtb('92_hash_bad_algo.dts', update_dtb=True)
|
||||
self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
|
||||
str(e.exception))
|
||||
|
||||
def testHashSection(self):
|
||||
"""Test hashing of the contents of an entry"""
|
||||
_, _, _, out_dtb_fname = self._DoReadFileDtb('99_hash_section.dts',
|
||||
use_real_dtb=True, update_dtb=True)
|
||||
dtb = fdt.Fdt(out_dtb_fname)
|
||||
dtb.Scan()
|
||||
hash_node = dtb.GetNode('/binman/section/hash').props['value']
|
||||
m = hashlib.sha256()
|
||||
m.update(U_BOOT_DATA)
|
||||
m.update(16 * 'a')
|
||||
self.assertEqual(m.digest(), ''.join(hash_node.value))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
# Holds and modifies the state information held by binman
|
||||
#
|
||||
|
||||
import hashlib
|
||||
import re
|
||||
from sets import Set
|
||||
|
||||
|
@ -226,3 +227,27 @@ def SetInt(node, prop, value):
|
|||
"""
|
||||
for n in GetUpdateNodes(node):
|
||||
n.SetInt(prop, value)
|
||||
|
||||
def CheckAddHashProp(node):
|
||||
hash_node = node.FindNode('hash')
|
||||
if hash_node:
|
||||
algo = hash_node.props.get('algo')
|
||||
if not algo:
|
||||
return "Missing 'algo' property for hash node"
|
||||
if algo.value == 'sha256':
|
||||
size = 32
|
||||
else:
|
||||
return "Unknown hash algorithm '%s'" % algo
|
||||
for n in GetUpdateNodes(hash_node):
|
||||
n.AddEmptyProp('value', size)
|
||||
|
||||
def CheckSetHashValue(node, get_data_func):
|
||||
hash_node = node.FindNode('hash')
|
||||
if hash_node:
|
||||
algo = hash_node.props.get('algo').value
|
||||
if algo == 'sha256':
|
||||
m = hashlib.sha256()
|
||||
m.update(get_data_func())
|
||||
data = m.digest()
|
||||
for n in GetUpdateNodes(hash_node):
|
||||
n.SetData('value', data)
|
||||
|
|
12
tools/binman/test/90_hash.dts
Normal file
12
tools/binman/test/90_hash.dts
Normal file
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
binman {
|
||||
u-boot {
|
||||
hash {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
11
tools/binman/test/91_hash_no_algo.dts
Normal file
11
tools/binman/test/91_hash_no_algo.dts
Normal file
|
@ -0,0 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
binman {
|
||||
u-boot {
|
||||
hash {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
12
tools/binman/test/92_hash_bad_algo.dts
Normal file
12
tools/binman/test/92_hash_bad_algo.dts
Normal file
|
@ -0,0 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
binman {
|
||||
u-boot {
|
||||
hash {
|
||||
algo = "invalid";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
18
tools/binman/test/99_hash_section.dts
Normal file
18
tools/binman/test/99_hash_section.dts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
binman {
|
||||
section {
|
||||
u-boot {
|
||||
};
|
||||
fill {
|
||||
size = <0x10>;
|
||||
fill-byte = [61];
|
||||
};
|
||||
hash {
|
||||
algo = "sha256";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue