1#!/usr/bin/env python3
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2021, Huawei Technologies Co., Ltd
5#
6
7from cryptography.hazmat.backends import default_backend
8from cryptography.hazmat.primitives import hashes
9from elftools.elf.elffile import ELFFile
10from elftools.elf.sections import SymbolTableSection
11import codecs
12import sys
13
14verbose = False
15
16
17def dump(buf):
18    print(codecs.encode(buf, 'hex').decode('utf-8'))
19
20
21def resolve_symbol(elf, name):
22    for section in elf.iter_sections():
23        if isinstance(section, SymbolTableSection):
24            for symbol in section.iter_symbols():
25                if symbol.name == name:
26                    return symbol.entry['st_value']
27    raise RuntimeError(f'Symbol {name} not found')
28
29
30def hash_range(h, elf, start, end):
31    global verbose
32    start_addr = resolve_symbol(elf, start)
33    end_addr = resolve_symbol(elf, end)
34    size = end_addr - start_addr
35    if verbose:
36        print(f'[{start}(0x{start_addr:x}), {end}(0x{end_addr:x})]: '
37              f'{size} bytes')
38    for segment in elf.iter_segments():
39        if (segment['p_type'] == 'PT_LOAD' and
40                segment['p_vaddr'] <= start_addr and
41                end_addr <= segment['p_vaddr'] + segment['p_filesz']):
42            begin_offs = start_addr - segment['p_vaddr']
43            h.update(segment.data()[begin_offs:begin_offs + size])
44
45
46def hash_section(h, elf, name):
47    global verbose
48    s = elf.get_section_by_name(name)
49    if s is None:
50        return
51    d = s.data()
52    if verbose:
53        print(f'{name}: {len(d)} bytes')
54    h.update(d)
55
56
57def main():
58    global verbose
59    argc = len(sys.argv)
60    if argc != 2 and argc != 3:
61        print('Usage:', sys.argv[0], '<tee.elf>')
62        return 1
63
64    if argc == 3 and sys.argv[1] == '-v':
65        verbose = True
66
67    with open(sys.argv[argc - 1], 'rb') as f:
68        elf = ELFFile(f)
69        h = hashes.Hash(hashes.SHA256(), default_backend())
70        hash_range(h, elf, '__text_start', '__text_data_start')
71        hash_range(h, elf, '__text_data_end', '__text_end')
72        hash_section(h, elf, '.text_init')
73        hash_section(h, elf, '.text_pageable')
74        hash_section(h, elf, '.rodata')
75        hash_section(h, elf, '.rodata_init')
76        hash_section(h, elf, '.rodata_pageable')
77        dump(h.finalize())
78
79
80if __name__ == "__main__":
81    main()
82