summaryrefslogtreecommitdiffstats
path: root/IntelFsp2Pkg/Tools/ConfigEditor/CommonUtility.py
diff options
context:
space:
mode:
Diffstat (limited to 'IntelFsp2Pkg/Tools/ConfigEditor/CommonUtility.py')
-rw-r--r--IntelFsp2Pkg/Tools/ConfigEditor/CommonUtility.py504
1 files changed, 504 insertions, 0 deletions
diff --git a/IntelFsp2Pkg/Tools/ConfigEditor/CommonUtility.py b/IntelFsp2Pkg/Tools/ConfigEditor/CommonUtility.py
new file mode 100644
index 0000000000..1229279116
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/ConfigEditor/CommonUtility.py
@@ -0,0 +1,504 @@
+#!/usr/bin/env python
+# @ CommonUtility.py
+# Common utility script
+#
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import sys
+import shutil
+import subprocess
+import string
+from ctypes import ARRAY, c_char, c_uint16, c_uint32, \
+ c_uint8, Structure, sizeof
+from importlib.machinery import SourceFileLoader
+from SingleSign import single_sign_gen_pub_key
+
+
+# Key types defined should match with cryptolib.h
+PUB_KEY_TYPE = {
+ "RSA": 1,
+ "ECC": 2,
+ "DSA": 3,
+ }
+
+# Signing type schemes defined should match with cryptolib.h
+SIGN_TYPE_SCHEME = {
+ "RSA_PKCS1": 1,
+ "RSA_PSS": 2,
+ "ECC": 3,
+ "DSA": 4,
+ }
+
+# Hash values defined should match with cryptolib.h
+HASH_TYPE_VALUE = {
+ "SHA2_256": 1,
+ "SHA2_384": 2,
+ "SHA2_512": 3,
+ "SM3_256": 4,
+ }
+
+# Hash values defined should match with cryptolib.h
+HASH_VAL_STRING = dict(map(reversed, HASH_TYPE_VALUE.items()))
+
+AUTH_TYPE_HASH_VALUE = {
+ "SHA2_256": 1,
+ "SHA2_384": 2,
+ "SHA2_512": 3,
+ "SM3_256": 4,
+ "RSA2048SHA256": 1,
+ "RSA3072SHA384": 2,
+ }
+
+HASH_DIGEST_SIZE = {
+ "SHA2_256": 32,
+ "SHA2_384": 48,
+ "SHA2_512": 64,
+ "SM3_256": 32,
+ }
+
+
+class PUB_KEY_HDR (Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('Identifier', ARRAY(c_char, 4)), # signature ('P', 'U', 'B', 'K')
+ ('KeySize', c_uint16), # Length of Public Key
+ ('KeyType', c_uint8), # RSA or ECC
+ ('Reserved', ARRAY(c_uint8, 1)),
+ ('KeyData', ARRAY(c_uint8, 0)),
+ ]
+
+ def __init__(self):
+ self.Identifier = b'PUBK'
+
+
+class SIGNATURE_HDR (Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('Identifier', ARRAY(c_char, 4)),
+ ('SigSize', c_uint16),
+ ('SigType', c_uint8),
+ ('HashAlg', c_uint8),
+ ('Signature', ARRAY(c_uint8, 0)),
+ ]
+
+ def __init__(self):
+ self.Identifier = b'SIGN'
+
+
+class LZ_HEADER(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ('signature', ARRAY(c_char, 4)),
+ ('compressed_len', c_uint32),
+ ('length', c_uint32),
+ ('version', c_uint16),
+ ('svn', c_uint8),
+ ('attribute', c_uint8)
+ ]
+ _compress_alg = {
+ b'LZDM': 'Dummy',
+ b'LZ4 ': 'Lz4',
+ b'LZMA': 'Lzma',
+ }
+
+
+def print_bytes(data, indent=0, offset=0, show_ascii=False):
+ bytes_per_line = 16
+ printable = ' ' + string.ascii_letters + string.digits + string.punctuation
+ str_fmt = '{:s}{:04x}: {:%ds} {:s}' % (bytes_per_line * 3)
+ bytes_per_line
+ data_array = bytearray(data)
+ for idx in range(0, len(data_array), bytes_per_line):
+ hex_str = ' '.join(
+ '%02X' % val for val in data_array[idx:idx + bytes_per_line])
+ asc_str = ''.join('%c' % (val if (chr(val) in printable) else '.')
+ for val in data_array[idx:idx + bytes_per_line])
+ print(str_fmt.format(
+ indent * ' ',
+ offset + idx, hex_str,
+ ' ' + asc_str if show_ascii else ''))
+
+
+def get_bits_from_bytes(bytes, start, length):
+ if length == 0:
+ return 0
+ byte_start = (start) // 8
+ byte_end = (start + length - 1) // 8
+ bit_start = start & 7
+ mask = (1 << length) - 1
+ val = bytes_to_value(bytes[byte_start:byte_end + 1])
+ val = (val >> bit_start) & mask
+ return val
+
+
+def set_bits_to_bytes(bytes, start, length, bvalue):
+ if length == 0:
+ return
+ byte_start = (start) // 8
+ byte_end = (start + length - 1) // 8
+ bit_start = start & 7
+ mask = (1 << length) - 1
+ val = bytes_to_value(bytes[byte_start:byte_end + 1])
+ val &= ~(mask << bit_start)
+ val |= ((bvalue & mask) << bit_start)
+ bytes[byte_start:byte_end+1] = value_to_bytearray(
+ val,
+ byte_end + 1 - byte_start)
+
+
+def value_to_bytes(value, length):
+ return value.to_bytes(length, 'little')
+
+
+def bytes_to_value(bytes):
+ return int.from_bytes(bytes, 'little')
+
+
+def value_to_bytearray(value, length):
+ return bytearray(value_to_bytes(value, length))
+
+# def value_to_bytearray (value, length):
+ return bytearray(value_to_bytes(value, length))
+
+
+def get_aligned_value(value, alignment=4):
+ if alignment != (1 << (alignment.bit_length() - 1)):
+ raise Exception(
+ 'Alignment (0x%x) should to be power of 2 !' % alignment)
+ value = (value + (alignment - 1)) & ~(alignment - 1)
+ return value
+
+
+def get_padding_length(data_len, alignment=4):
+ new_data_len = get_aligned_value(data_len, alignment)
+ return new_data_len - data_len
+
+
+def get_file_data(file, mode='rb'):
+ return open(file, mode).read()
+
+
+def gen_file_from_object(file, object):
+ open(file, 'wb').write(object)
+
+
+def gen_file_with_size(file, size):
+ open(file, 'wb').write(b'\xFF' * size)
+
+
+def check_files_exist(base_name_list, dir='', ext=''):
+ for each in base_name_list:
+ if not os.path.exists(os.path.join(dir, each + ext)):
+ return False
+ return True
+
+
+def load_source(name, filepath):
+ mod = SourceFileLoader(name, filepath).load_module()
+ return mod
+
+
+def get_openssl_path():
+ if os.name == 'nt':
+ if 'OPENSSL_PATH' not in os.environ:
+ openssl_dir = "C:\\Openssl\\bin\\"
+ if os.path.exists(openssl_dir):
+ os.environ['OPENSSL_PATH'] = openssl_dir
+ else:
+ os.environ['OPENSSL_PATH'] = "C:\\Openssl\\"
+ if 'OPENSSL_CONF' not in os.environ:
+ openssl_cfg = "C:\\Openssl\\openssl.cfg"
+ if os.path.exists(openssl_cfg):
+ os.environ['OPENSSL_CONF'] = openssl_cfg
+ openssl = os.path.join(
+ os.environ.get('OPENSSL_PATH', ''),
+ 'openssl.exe')
+ else:
+ # Get openssl path for Linux cases
+ openssl = shutil.which('openssl')
+
+ return openssl
+
+
+def run_process(arg_list, print_cmd=False, capture_out=False):
+ sys.stdout.flush()
+ if os.name == 'nt' and os.path.splitext(arg_list[0])[1] == '' and \
+ os.path.exists(arg_list[0] + '.exe'):
+ arg_list[0] += '.exe'
+ if print_cmd:
+ print(' '.join(arg_list))
+
+ exc = None
+ result = 0
+ output = ''
+ try:
+ if capture_out:
+ output = subprocess.check_output(arg_list).decode()
+ else:
+ result = subprocess.call(arg_list)
+ except Exception as ex:
+ result = 1
+ exc = ex
+
+ if result:
+ if not print_cmd:
+ print('Error in running process:\n %s' % ' '.join(arg_list))
+ if exc is None:
+ sys.exit(1)
+ else:
+ raise exc
+
+ return output
+
+
+# Adjust hash type algorithm based on Public key file
+def adjust_hash_type(pub_key_file):
+ key_type = get_key_type(pub_key_file)
+ if key_type == 'RSA2048':
+ hash_type = 'SHA2_256'
+ elif key_type == 'RSA3072':
+ hash_type = 'SHA2_384'
+ else:
+ hash_type = None
+
+ return hash_type
+
+
+def rsa_sign_file(
+ priv_key, pub_key, hash_type, sign_scheme,
+ in_file, out_file, inc_dat=False, inc_key=False):
+
+ bins = bytearray()
+ if inc_dat:
+ bins.extend(get_file_data(in_file))
+
+
+# def single_sign_file(priv_key, hash_type, sign_scheme, in_file, out_file):
+
+ out_data = get_file_data(out_file)
+
+ sign = SIGNATURE_HDR()
+ sign.SigSize = len(out_data)
+ sign.SigType = SIGN_TYPE_SCHEME[sign_scheme]
+ sign.HashAlg = HASH_TYPE_VALUE[hash_type]
+
+ bins.extend(bytearray(sign) + out_data)
+ if inc_key:
+ key = gen_pub_key(priv_key, pub_key)
+ bins.extend(key)
+
+ if len(bins) != len(out_data):
+ gen_file_from_object(out_file, bins)
+
+
+def get_key_type(in_key):
+
+ # Check in_key is file or key Id
+ if not os.path.exists(in_key):
+ key = bytearray(gen_pub_key(in_key))
+ else:
+ # Check for public key in binary format.
+ key = bytearray(get_file_data(in_key))
+
+ pub_key_hdr = PUB_KEY_HDR.from_buffer(key)
+ if pub_key_hdr.Identifier != b'PUBK':
+ pub_key = gen_pub_key(in_key)
+ pub_key_hdr = PUB_KEY_HDR.from_buffer(pub_key)
+
+ key_type = next(
+ (key for key,
+ value in PUB_KEY_TYPE.items() if value == pub_key_hdr.KeyType))
+ return '%s%d' % (key_type, (pub_key_hdr.KeySize - 4) * 8)
+
+
+def get_auth_hash_type(key_type, sign_scheme):
+ if key_type == "RSA2048" and sign_scheme == "RSA_PKCS1":
+ hash_type = 'SHA2_256'
+ auth_type = 'RSA2048_PKCS1_SHA2_256'
+ elif key_type == "RSA3072" and sign_scheme == "RSA_PKCS1":
+ hash_type = 'SHA2_384'
+ auth_type = 'RSA3072_PKCS1_SHA2_384'
+ elif key_type == "RSA2048" and sign_scheme == "RSA_PSS":
+ hash_type = 'SHA2_256'
+ auth_type = 'RSA2048_PSS_SHA2_256'
+ elif key_type == "RSA3072" and sign_scheme == "RSA_PSS":
+ hash_type = 'SHA2_384'
+ auth_type = 'RSA3072_PSS_SHA2_384'
+ else:
+ hash_type = ''
+ auth_type = ''
+ return auth_type, hash_type
+
+
+# def single_sign_gen_pub_key(in_key, pub_key_file=None):
+
+
+def gen_pub_key(in_key, pub_key=None):
+
+ keydata = single_sign_gen_pub_key(in_key, pub_key)
+
+ publickey = PUB_KEY_HDR()
+ publickey.KeySize = len(keydata)
+ publickey.KeyType = PUB_KEY_TYPE['RSA']
+
+ key = bytearray(publickey) + keydata
+
+ if pub_key:
+ gen_file_from_object(pub_key, key)
+
+ return key
+
+
+def decompress(in_file, out_file, tool_dir=''):
+ if not os.path.isfile(in_file):
+ raise Exception("Invalid input file '%s' !" % in_file)
+
+ # Remove the Lz Header
+ fi = open(in_file, 'rb')
+ di = bytearray(fi.read())
+ fi.close()
+
+ lz_hdr = LZ_HEADER.from_buffer(di)
+ offset = sizeof(lz_hdr)
+ if lz_hdr.signature == b"LZDM" or lz_hdr.compressed_len == 0:
+ fo = open(out_file, 'wb')
+ fo.write(di[offset:offset + lz_hdr.compressed_len])
+ fo.close()
+ return
+
+ temp = os.path.splitext(out_file)[0] + '.tmp'
+ if lz_hdr.signature == b"LZMA":
+ alg = "Lzma"
+ elif lz_hdr.signature == b"LZ4 ":
+ alg = "Lz4"
+ else:
+ raise Exception("Unsupported compression '%s' !" % lz_hdr.signature)
+
+ fo = open(temp, 'wb')
+ fo.write(di[offset:offset + lz_hdr.compressed_len])
+ fo.close()
+
+ compress_tool = "%sCompress" % alg
+ if alg == "Lz4":
+ try:
+ cmdline = [
+ os.path.join(tool_dir, compress_tool),
+ "-d",
+ "-o", out_file,
+ temp]
+ run_process(cmdline, False, True)
+ except Exception:
+ msg_string = "Could not find/use CompressLz4 tool, " \
+ "trying with python lz4..."
+ print(msg_string)
+ try:
+ import lz4.block
+ if lz4.VERSION != '3.1.1':
+ msg_string = "Recommended lz4 module version " \
+ "is '3.1.1'," + lz4.VERSION \
+ + " is currently installed."
+ print(msg_string)
+ except ImportError:
+ msg_string = "Could not import lz4, use " \
+ "'python -m pip install lz4==3.1.1' " \
+ "to install it."
+ print(msg_string)
+ exit(1)
+ decompress_data = lz4.block.decompress(get_file_data(temp))
+ with open(out_file, "wb") as lz4bin:
+ lz4bin.write(decompress_data)
+ else:
+ cmdline = [
+ os.path.join(tool_dir, compress_tool),
+ "-d",
+ "-o", out_file,
+ temp]
+ run_process(cmdline, False, True)
+ os.remove(temp)
+
+
+def compress(in_file, alg, svn=0, out_path='', tool_dir=''):
+ if not os.path.isfile(in_file):
+ raise Exception("Invalid input file '%s' !" % in_file)
+
+ basename, ext = os.path.splitext(os.path.basename(in_file))
+ if out_path:
+ if os.path.isdir(out_path):
+ out_file = os.path.join(out_path, basename + '.lz')
+ else:
+ out_file = os.path.join(out_path)
+ else:
+ out_file = os.path.splitext(in_file)[0] + '.lz'
+
+ if alg == "Lzma":
+ sig = "LZMA"
+ elif alg == "Tiano":
+ sig = "LZUF"
+ elif alg == "Lz4":
+ sig = "LZ4 "
+ elif alg == "Dummy":
+ sig = "LZDM"
+ else:
+ raise Exception("Unsupported compression '%s' !" % alg)
+
+ in_len = os.path.getsize(in_file)
+ if in_len > 0:
+ compress_tool = "%sCompress" % alg
+ if sig == "LZDM":
+ shutil.copy(in_file, out_file)
+ compress_data = get_file_data(out_file)
+ elif sig == "LZ4 ":
+ try:
+ cmdline = [
+ os.path.join(tool_dir, compress_tool),
+ "-e",
+ "-o", out_file,
+ in_file]
+ run_process(cmdline, False, True)
+ compress_data = get_file_data(out_file)
+ except Exception:
+ msg_string = "Could not find/use CompressLz4 tool, " \
+ "trying with python lz4..."
+ print(msg_string)
+ try:
+ import lz4.block
+ if lz4.VERSION != '3.1.1':
+ msg_string = "Recommended lz4 module version " \
+ "is '3.1.1', " + lz4.VERSION \
+ + " is currently installed."
+ print(msg_string)
+ except ImportError:
+ msg_string = "Could not import lz4, use " \
+ "'python -m pip install lz4==3.1.1' " \
+ "to install it."
+ print(msg_string)
+ exit(1)
+ compress_data = lz4.block.compress(
+ get_file_data(in_file),
+ mode='high_compression')
+ elif sig == "LZMA":
+ cmdline = [
+ os.path.join(tool_dir, compress_tool),
+ "-e",
+ "-o", out_file,
+ in_file]
+ run_process(cmdline, False, True)
+ compress_data = get_file_data(out_file)
+ else:
+ compress_data = bytearray()
+
+ lz_hdr = LZ_HEADER()
+ lz_hdr.signature = sig.encode()
+ lz_hdr.svn = svn
+ lz_hdr.compressed_len = len(compress_data)
+ lz_hdr.length = os.path.getsize(in_file)
+ data = bytearray()
+ data.extend(lz_hdr)
+ data.extend(compress_data)
+ gen_file_from_object(out_file, data)
+
+ return out_file