diff --git a/util/me_cleaner/README.md b/util/me_cleaner/README.md new file mode 100644 index 0000000000..9a09b550eb --- /dev/null +++ b/util/me_cleaner/README.md @@ -0,0 +1,25 @@ +# ME cleaner + +A cleaner for Intel ME/TXE images. + +This tools removes any unnecessary partition from an Intel ME/TXE firmware, reducing +its size and its ability to interact with the system. +It should work both with coreboot and with the factory firmware. + +Currently this tool: + * Scans the FPT (partition table) and checks that everything is correct + * Removes any partition entry (except for FTPR) from FPT + * Removes any partition except for the fundamental one (FTPR) + * Removes the EFFS presence flag + * Corrects the FPT checksum + * Removes any non-essential LZMA or Huffman compressed module (pre-Skylake only) + * Checks the validity of the RSA signature of the FTPR partition + +Don't forget to power cycle your PC after flashing the modified ME/TXE image +(power off and power on, not just reboot). + +See the [current status](https://github.com/corna/me_cleaner/wiki/me_cleaner-status) +or [a more detailed description](https://github.com/corna/me_cleaner/wiki/How-does-it-work%3F) +of me_cleaner. + +Special thanks to Federico Amedeo Izzo for his help during the study of Intel ME. diff --git a/util/me_cleaner/me_cleaner.py b/util/me_cleaner/me_cleaner.py new file mode 100755 index 0000000000..2ad5898213 --- /dev/null +++ b/util/me_cleaner/me_cleaner.py @@ -0,0 +1,313 @@ +#!/usr/bin/python + +# me_cleaner - Tool for partial deblobbing of Intel ME/TXE firmware images +# Copyright (C) 2016, 2017 Nicola Corna +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +import sys +import itertools +import binascii +import hashlib +from struct import pack, unpack + + +unremovable_modules = ("BUP", "ROMP") + + +def get_chunks_offsets(llut, me_start): + chunk_count = unpack("> 4) & 7 + + sys.stdout.write(" {:<16} ({:<7}, ".format(name, comp_str[comp_type])) + + if comp_type == 0x00 or comp_type == 0x02: + sys.stdout.write("0x{:06x} - 0x{:06x}): " + .format(offset, offset + size)) + + if name in unremovable_modules: + print("NOT removed, essential") + else: + fill_range(f, offset, offset + size, b"\xff") + print("removed") + + elif comp_type == 0x01: + sys.stdout.write("fragmented data ): ") + if not chunks_offsets: + f.seek(offset) + llut = f.read(4) + if llut == b"LLUT": + llut += f.read(0x3c) + + chunk_count = unpack(" removable_chunk[0]: + fill_range(f, removable_chunk[0], removable_chunk[1], b"\xff") + + +def check_partition_signature(f, offset): + f.seek(offset) + header = f.read(0x80) + modulus = int(binascii.hexlify(f.read(0x100)[::-1]), 16) + public_exponent = int(binascii.hexlify(f.read(0x4)[::-1]), 16) + signature = int(binascii.hexlify(f.read(0x100)[::-1]), 16) + + header_len = unpack("> 24 & 0x7 + frba = flmap0 >> 12 & 0xff0 + if nr >= 2: + f.seek(frba + 0x8) + flreg2 = unpack("> 4 & 0x1fff000 | 0xfff + + if me_start >= me_end: + sys.exit("The ME/TXE region in this image has been " + "disabled") + + f.seek(me_start + 0x10) + if f.read(4) != b"$FPT": + sys.exit("The ME/TXE region is corrupted or missing") + + print("The ME/TXE region goes from {:#x} to {:#x}" + .format(me_start, me_end)) + else: + sys.exit("This image does not contains a ME/TXE firmware " + "(NR = {})".format(nr)) + else: + sys.exit("Unknown image") + + print("Found FPT header at {:#x}".format(me_start + 0x10)) + + f.seek(me_start + 0x14) + entries = unpack("