mirror of https://github.com/acidanthera/audk.git
CryptoPkg/openssl: add openssl3 configure scripts
Rewrite the script to configure openssl 3.0 from scratch. It's two scripts now: * Tiny helper script, dumping the perl configdata as json. * Actual configure.py script, written in python, which copies over the generated files to openssl-gen and updates the OpensslLib*.inf file lists and build flags. The configuration workflow has changed a bit: * All generated files are stored in the OpensslGen directory tree. * For ec/no-ec builds two different header files are used. Default is the ec variant, and the new EDK2_OPENSSL_NOEC define is used to select the no-ec build. A five line wrapper include is used to pick the one or the other. * For non-accel builds -DOPENSSL_NO_ASM on the command line is used (same as before). * For configration defines the OPENSSL_FLAGS_$(variant) variable is used, where variant is the architecture for the accelerated builds and 'NOASM' for the non-accelerated builds. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Yi Li <yi1.li@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Acked-by: Ard Biesheuvel <ardb@kernel.org> Tested-by: Ard Biesheuvel <ardb@kernel.org> Tested-by: Brian J. Johnson <brian.johnson@hpe.com> Tested-by: Kenneth Lautner <klautner@microsoft.com>
This commit is contained in:
parent
7cede6d5f4
commit
81f5aa0700
|
@ -28,9 +28,9 @@ on the cryptography.
|
|||
refer to edk2/Readme.md for how to clone the code.
|
||||
|
||||
=============================================================================
|
||||
About process_files.pl
|
||||
About configure.py
|
||||
=============================================================================
|
||||
"process_files.pl" is one Perl script which runs the OpenSSL Configure,
|
||||
"configure.py" is one python script which runs the OpenSSL Configure,
|
||||
then processes the resulting file list into our local OpensslLib.inf and
|
||||
OpensslLibCrypto.inf.
|
||||
This only needs to be done once by the maintainer / developer when
|
||||
|
|
|
@ -0,0 +1,395 @@
|
|||
#!/usr/bin/python3
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import pprint
|
||||
import argparse
|
||||
import subprocess
|
||||
|
||||
def openssl_configure(openssldir, target, ec = True):
|
||||
""" Run openssl Configure script. """
|
||||
cmdline = [
|
||||
'perl',
|
||||
'Configure',
|
||||
'--config=../UefiAsm.conf',
|
||||
'--api=1.1.1',
|
||||
'--with-rand-seed=none',
|
||||
target,
|
||||
'no-afalgeng',
|
||||
'no-aria',
|
||||
'no-async',
|
||||
'no-autoerrinit',
|
||||
'no-autoload-config',
|
||||
'no-bf',
|
||||
'no-blake2',
|
||||
'no-camellia',
|
||||
'no-capieng',
|
||||
'no-cast',
|
||||
'no-chacha',
|
||||
'no-cmac',
|
||||
'no-cmp',
|
||||
'no-cms',
|
||||
'no-ct',
|
||||
'no-deprecated',
|
||||
'no-des',
|
||||
'no-dgram',
|
||||
'no-dsa',
|
||||
'no-dso',
|
||||
'no-dtls',
|
||||
'no-dtls1-method',
|
||||
'no-dtls1_2-method',
|
||||
'no-dynamic-engine',
|
||||
'no-ec2m',
|
||||
'no-engine',
|
||||
'no-err',
|
||||
'no-filenames',
|
||||
'no-gost',
|
||||
'no-hw',
|
||||
'no-idea',
|
||||
'no-ktls',
|
||||
'no-makedepend',
|
||||
'no-module',
|
||||
'no-md4',
|
||||
'no-mdc2',
|
||||
'no-multiblock',
|
||||
'no-nextprotoneg',
|
||||
'no-pic',
|
||||
'no-psk',
|
||||
'no-ocb',
|
||||
'no-ocsp',
|
||||
'no-padlockeng',
|
||||
'no-poly1305',
|
||||
'no-posix-io',
|
||||
'no-rc2',
|
||||
'no-rc4',
|
||||
'no-rc5',
|
||||
'no-rfc3779',
|
||||
'no-rmd160',
|
||||
'no-scrypt',
|
||||
'no-seed',
|
||||
'no-shared',
|
||||
'no-siphash',
|
||||
'no-siv',
|
||||
'no-sm2',
|
||||
'no-sm4',
|
||||
'no-sock',
|
||||
'no-srp',
|
||||
'no-srtp',
|
||||
'no-ssl',
|
||||
'no-ssl3-method',
|
||||
'no-ssl-trace',
|
||||
'no-static-engine',
|
||||
'no-stdio',
|
||||
'no-threads',
|
||||
'no-tls1_3',
|
||||
'no-ts',
|
||||
'no-ui-console',
|
||||
'no-whirlpool',
|
||||
'disable-legacy',
|
||||
]
|
||||
if not ec:
|
||||
cmdline += [ 'no-ec', ]
|
||||
print('')
|
||||
print(f'# -*- configure openssl for {target} (ec={ec}) -*-')
|
||||
rc = subprocess.run(cmdline, cwd = openssldir,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE)
|
||||
if rc.returncode:
|
||||
print(rc.stdout)
|
||||
print(rc.stderr)
|
||||
sys.exit(rc.returncode)
|
||||
|
||||
def openssl_run_make(openssldir, target):
|
||||
"""
|
||||
Run make utility to generate files or cleanup.
|
||||
Target can be either a string or a list of strings.
|
||||
"""
|
||||
cmdline = [ 'make', '--silent' ]
|
||||
if isinstance(target, list):
|
||||
cmdline += target
|
||||
else:
|
||||
cmdline += [ target, ]
|
||||
rc = subprocess.run(cmdline, cwd = openssldir)
|
||||
rc.check_returncode()
|
||||
|
||||
def get_configdata(openssldir):
|
||||
"""
|
||||
Slurp openssl config data as JSON,
|
||||
using a little perl helper script.
|
||||
"""
|
||||
cmdline = [
|
||||
'perl',
|
||||
'perl2json.pl',
|
||||
openssldir,
|
||||
]
|
||||
rc = subprocess.run(cmdline, stdout = subprocess.PIPE)
|
||||
rc.check_returncode()
|
||||
return json.loads(rc.stdout)
|
||||
|
||||
def is_asm(filename):
|
||||
""" Check whenevr the passed file is an assembler file """
|
||||
if filename.endswith('.s') or filename.endswith('.S'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def copy_generated_file(src, dst):
|
||||
src_file = []
|
||||
with open(src, 'r') as fsrc:
|
||||
src_file = fsrc.readlines()
|
||||
with open(dst, 'w') as fdst:
|
||||
for lines in range(len(src_file)):
|
||||
s = src_file[lines]
|
||||
s = s.rstrip() + "\r\n"
|
||||
fdst.write(s.expandtabs())
|
||||
|
||||
def generate_files(openssldir, opensslgendir, asm, filelist):
|
||||
"""
|
||||
Generate files, using make, and copy over the results to the
|
||||
directory tree for generated openssl files. Creates
|
||||
subdirectories as needed.
|
||||
"""
|
||||
openssl_run_make(openssldir, filelist)
|
||||
for filename in filelist:
|
||||
src = os.path.join(openssldir, filename)
|
||||
if is_asm(filename):
|
||||
""" rename MSFT asm files to .nasm """
|
||||
if 'IA32-MSFT' in asm:
|
||||
filename = filename.replace('.S', '.nasm')
|
||||
elif 'X64-MSFT' in asm:
|
||||
filename = filename.replace('.s', '.nasm')
|
||||
dst = os.path.join(opensslgendir, asm, filename)
|
||||
else:
|
||||
dst = os.path.join(opensslgendir, filename)
|
||||
os.makedirs(os.path.dirname(dst), exist_ok = True)
|
||||
copy_generated_file(src, dst)
|
||||
|
||||
def generate_include_files(openssldir, opensslgendir, asm, cfg):
|
||||
""" Generate openssl include files """
|
||||
print('# generate include files')
|
||||
filelist = cfg['unified_info']['generate'].keys()
|
||||
filelist = list(filter(lambda f: 'include' in f, filelist))
|
||||
generate_files(openssldir, opensslgendir, asm, filelist)
|
||||
|
||||
def generate_library_files(openssldir, opensslgendir, asm, cfg, obj):
|
||||
"""
|
||||
Generate openssl source files for a given library. Handles
|
||||
mostly assembler files, but a few C sources are generated too.
|
||||
"""
|
||||
filelist = get_source_list(cfg, obj, True)
|
||||
if filelist:
|
||||
print(f'# generate source files for {obj}')
|
||||
generate_files(openssldir, opensslgendir, asm, filelist)
|
||||
|
||||
def generate_all_files(openssldir, opensslgendir, asm, cfg):
|
||||
""" Generate all files needed. """
|
||||
generate_include_files(openssldir, opensslgendir, asm, cfg)
|
||||
generate_library_files(openssldir, opensslgendir, asm, cfg, 'libcrypto')
|
||||
generate_library_files(openssldir, opensslgendir, asm, cfg, 'providers/libcommon.a')
|
||||
generate_library_files(openssldir, opensslgendir, asm, cfg, 'libssl')
|
||||
|
||||
def get_source_list(cfg, obj, gen):
|
||||
"""
|
||||
Gets the list of source files needed to create a specific object.
|
||||
* If 'gen' is True the function returns the list of generated
|
||||
files.
|
||||
* If 'gen' is False the function returns the list of files not
|
||||
generated (which are used from the submodule directly).
|
||||
Note: Will call itself recursively to resolve nested dependencies.
|
||||
"""
|
||||
sources = cfg['unified_info']['sources']
|
||||
generate = cfg['unified_info']['generate']
|
||||
srclist = []
|
||||
if sources.get(obj):
|
||||
for item in sources.get(obj):
|
||||
srclist += get_source_list(cfg, item, gen)
|
||||
else:
|
||||
is_generated = generate.get(obj) is not None
|
||||
if is_generated == gen:
|
||||
srclist += [ obj, ]
|
||||
return srclist
|
||||
|
||||
def get_sources(cfg, obj, asm):
|
||||
"""
|
||||
Get the list of all sources files. Will fetch both generated
|
||||
and not generated file lists and update the paths accordingly, so
|
||||
the openssl submodule or the sub-tree for generated files is
|
||||
referenced as needed.
|
||||
"""
|
||||
srclist = get_source_list(cfg, obj, False)
|
||||
genlist = get_source_list(cfg, obj, True)
|
||||
srclist = list(map(lambda x: f'$(OPENSSL_PATH)/{x}', srclist))
|
||||
c_list = list(map(lambda x: f'$(OPENSSL_GEN_PATH)/{x}',
|
||||
filter(lambda x: not is_asm(x), genlist)))
|
||||
asm_list = list(map(lambda x: f'$(OPENSSL_GEN_PATH)/{asm}/{x}',
|
||||
filter(is_asm, genlist)))
|
||||
return srclist + c_list + asm_list
|
||||
|
||||
def sources_filter_fn(filename):
|
||||
"""
|
||||
Filter source lists. Drops files we don't want include or
|
||||
need replace with our own uefi-specific version.
|
||||
"""
|
||||
exclude = [
|
||||
'randfile.c',
|
||||
'/store/',
|
||||
'/storemgmt/',
|
||||
'/encode_decode/encode',
|
||||
'/pkcs12/',
|
||||
'statem_srvr.c',
|
||||
'extensions_srvr.c',
|
||||
'defltprov.c',
|
||||
'baseprov.c',
|
||||
'provider_predefined.c',
|
||||
]
|
||||
for item in exclude:
|
||||
if item in filename:
|
||||
return False
|
||||
return True
|
||||
|
||||
def libcrypto_sources(cfg, asm = None):
|
||||
""" Get source file list for libcrypto """
|
||||
files = get_sources(cfg, 'libcrypto', asm)
|
||||
files += get_sources(cfg, 'providers/libcommon.a', asm)
|
||||
files = list(filter(sources_filter_fn, files))
|
||||
return files
|
||||
|
||||
def libssl_sources(cfg, asm = None):
|
||||
""" Get source file list for libssl """
|
||||
files = get_sources(cfg, 'libssl', asm)
|
||||
files = list(filter(sources_filter_fn, files))
|
||||
return files
|
||||
|
||||
def update_inf(filename, sources, arch = None, defines = []):
|
||||
"""
|
||||
Update inf file, replace source file list and build flags.
|
||||
"""
|
||||
head = ''
|
||||
tail = ''
|
||||
state = 0
|
||||
|
||||
if arch:
|
||||
section = f'Sources.{arch}'
|
||||
flags = f'OPENSSL_FLAGS_{arch}'
|
||||
else:
|
||||
section = None
|
||||
flags = f'OPENSSL_FLAGS_NOASM'
|
||||
state = 1
|
||||
|
||||
# read and parse file
|
||||
with open(filename, 'r') as f:
|
||||
while True:
|
||||
line = f.readline()
|
||||
if line == '':
|
||||
break
|
||||
if state in [0, 1]:
|
||||
if flags in line:
|
||||
(keep, replace) = line.split('=')
|
||||
args = map(lambda x: f'-D{x}', defines)
|
||||
head += keep + '= ' + ' '.join(args)
|
||||
head = head.rstrip() + '\r\n'
|
||||
else:
|
||||
head += line.rstrip() + '\r\n'
|
||||
if state == 0 and section in line:
|
||||
state = 1
|
||||
if state == 1 and 'Autogenerated files list starts here' in line:
|
||||
state = 2
|
||||
if state == 2 and 'Autogenerated files list ends here' in line:
|
||||
state = 3
|
||||
if state == 3:
|
||||
tail += line.rstrip() + '\r\n'
|
||||
|
||||
# write updated file
|
||||
with open(filename, 'w') as f:
|
||||
f.write(head)
|
||||
for src in sources:
|
||||
f.write(f' {src}\r\n')
|
||||
f.write(tail)
|
||||
|
||||
def update_MSFT_asm_format(asm, filelist):
|
||||
""" rename MSFT asm files to .nasm """
|
||||
if 'IA32-MSFT' in asm:
|
||||
for file_index in range(len(filelist)):
|
||||
filelist[file_index] = filelist[file_index].replace('.S', '.nasm')
|
||||
elif 'X64-MSFT' in asm:
|
||||
for file_index in range(len(filelist)):
|
||||
filelist[file_index] = filelist[file_index].replace('.s', '.nasm')
|
||||
|
||||
def main():
|
||||
# prepare
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
openssldir = os.path.join(os.getcwd(), 'openssl')
|
||||
opensslgendir = os.path.join(os.getcwd(), 'OpensslGen')
|
||||
|
||||
# asm accel configs (see UefiAsm.conf)
|
||||
for ec in [True, False]:
|
||||
if ec:
|
||||
inf = 'OpensslLibFullAccel.inf'
|
||||
hdr = 'configuration-ec.h'
|
||||
else:
|
||||
inf = 'OpensslLibAccel.inf'
|
||||
hdr = 'configuration-noec.h'
|
||||
sources = {}
|
||||
defines = {}
|
||||
for asm in [ 'UEFI-IA32-MSFT', 'UEFI-IA32-GCC',
|
||||
'UEFI-X64-MSFT', 'UEFI-X64-GCC']:
|
||||
(uefi, arch, cc) = asm.split('-')
|
||||
archcc = f'{arch}-{cc}'
|
||||
|
||||
openssl_configure(openssldir, asm, ec = ec);
|
||||
cfg = get_configdata(openssldir)
|
||||
generate_all_files(openssldir, opensslgendir, archcc, cfg)
|
||||
shutil.move(os.path.join(opensslgendir, 'include', 'openssl', 'configuration.h'),
|
||||
os.path.join(opensslgendir, 'include', 'openssl', hdr))
|
||||
openssl_run_make(openssldir, 'distclean')
|
||||
|
||||
srclist = libcrypto_sources(cfg, archcc) + libssl_sources(cfg, archcc)
|
||||
sources[archcc] = list(map(lambda x: f'{x} | {cc}', filter(is_asm, srclist)))
|
||||
update_MSFT_asm_format(archcc, sources[archcc])
|
||||
sources[arch] = list(filter(lambda x: not is_asm(x), srclist))
|
||||
defines[arch] = cfg['unified_info']['defines']['libcrypto']
|
||||
|
||||
ia32accel = sources['IA32'] + sources['IA32-MSFT'] + sources['IA32-GCC']
|
||||
x64accel = sources['X64'] + sources['X64-MSFT'] + sources['X64-GCC']
|
||||
update_inf(inf, ia32accel, 'IA32', defines['IA32'])
|
||||
update_inf(inf, x64accel, 'X64', defines['X64'])
|
||||
|
||||
# noaccel - ec enabled
|
||||
openssl_configure(openssldir, 'UEFI', ec = True);
|
||||
cfg = get_configdata(openssldir)
|
||||
generate_all_files(openssldir, opensslgendir, None, cfg)
|
||||
openssl_run_make(openssldir, 'distclean')
|
||||
|
||||
defines = []
|
||||
if 'libcrypto' in cfg['unified_info']['defines']:
|
||||
defines = cfg['unified_info']['defines']['libcrypto']
|
||||
|
||||
update_inf('OpensslLibFull.inf',
|
||||
libcrypto_sources(cfg) + libssl_sources(cfg),
|
||||
defines)
|
||||
|
||||
# noaccel - ec disabled
|
||||
openssl_configure(openssldir, 'UEFI', ec = False);
|
||||
cfg = get_configdata(openssldir)
|
||||
generate_all_files(openssldir, opensslgendir, None, cfg)
|
||||
openssl_run_make(openssldir, 'distclean')
|
||||
|
||||
update_inf('OpensslLibCrypto.inf',
|
||||
libcrypto_sources(cfg),
|
||||
None, defines)
|
||||
update_inf('OpensslLib.inf',
|
||||
libcrypto_sources(cfg) + libssl_sources(cfg),
|
||||
None, defines)
|
||||
|
||||
# wrap header file
|
||||
confighdr = os.path.join(opensslgendir, 'include', 'openssl', 'configuration.h')
|
||||
with open(confighdr, 'w') as f:
|
||||
f.write('#ifdef EDK2_OPENSSL_NOEC\r\n'
|
||||
'# include "configuration-noec.h"\r\n'
|
||||
'#else\r\n'
|
||||
'# include "configuration-ec.h"\r\n'
|
||||
'#endif\r\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# write out configdata.pm as json
|
||||
#
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
|
||||
BEGIN {
|
||||
my $openssldir = shift;
|
||||
push @INC, $openssldir;
|
||||
}
|
||||
use configdata qw/%config %target %unified_info/;
|
||||
|
||||
my %data;
|
||||
$data{'config'} = \%config;
|
||||
$data{'target'} = \%target;
|
||||
$data{'unified_info'} = \%unified_info;
|
||||
print encode_json(\%data)
|
Loading…
Reference in New Issue