diff --git a/Makefile.am b/Makefile.am index 8cb708b9..88ad1c7e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,3 +54,5 @@ MAINTAINERCLEANFILES = \ m4/* \ missing \ test-driver + +EXTRA_DIST = meson.build diff --git a/docs/Makefile.am b/docs/Makefile.am index e7fa12d6..c571d1c1 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,2 +1,4 @@ dist_man_MANS = provider-pkcs11.7 + +EXTRA_DIST = meson.build diff --git a/docs/meson.build b/docs/meson.build new file mode 100644 index 00000000..0286673a --- /dev/null +++ b/docs/meson.build @@ -0,0 +1 @@ +install_man('provider-pkcs11.7') diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..1cf3dc86 --- /dev/null +++ b/meson.build @@ -0,0 +1,84 @@ +project( + 'pkcs11-provider', 'c', + version: '0.2', + meson_version: '>= 0.57', + default_options: ['c_std=c11'], +) + +version_arr = meson.project_version().split('.') +major_version = version_arr[0].to_int() +minor_version = version_arr[1].to_int() + +cc = meson.get_compiler('c') + +warning_c_args = [ + '-Wwrite-strings', + '-Wpointer-arith', + '-Wno-missing-field-initializers', + '-Wformat', + '-Wshadow', + # Temporarily disable unused parameter until the implementation is complete + '-Wno-unused-parameter', + # These should be always errors + '-Werror=implicit-function-declaration', + '-Werror=missing-prototypes', + '-Werror=format-security', + '-Werror=parentheses', + '-Werror=implicit', + '-Werror=strict-prototypes', +] + +extra_c_args = [ + '-fno-strict-aliasing', + '-fno-delete-null-pointer-checks', + '-fdiagnostics-show-option', +] + +add_project_arguments(cc.get_supported_arguments(warning_c_args + extra_c_args), + language: 'c') + +configinc = include_directories('.') + +conf = configuration_data() + +conf.set_quoted('PACKAGE_NAME', meson.project_name()) +conf.set('PACKAGE_MAJOR', major_version) +conf.set('PACKAGE_MINOR', minor_version) + +libcrypto = dependency('libcrypto', version: '>= 3.0.7') +provider_path = libcrypto.get_variable(pkgconfig: 'modulesdir') +libssl = dependency('libssl', version: '>= 3.0.7') + +host_system = host_machine.system() +if host_system == 'windows' + shlext = '.dll' +else + shlext = '.so' +endif + +if host_machine.endian() == 'big' + conf.set('WORDS_BIGENDIAN', 1) +endif + +p11_kit = dependency('p11-kit-1', required: false) +if p11_kit.found() + default_pkcs11_module = p11_kit.get_variable(pkgconfig: 'proxy_module') + conf.set_quoted('DEFAULT_PKCS11_MODULE', default_pkcs11_module) +endif + +headers = [ + 'dlfcn.h', +] + +foreach h : headers + if cc.has_header(h) + conf.set('HAVE_' + h.underscorify().to_upper(), 1) + endif +endforeach + +configure_file(output: 'config.h', configuration: conf) + +subdir('src') +subdir('docs') +subdir('tests') + diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..7e7b9bee --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,4 @@ +option('preload_libasan', + type: 'string', + value: 'no', + description: 'Path to libasan.so to preload') diff --git a/src/Makefile.am b/src/Makefile.am index 4c0711ce..a0d8e472 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,11 +49,13 @@ pkcs11_la_SOURCES = \ tls.c \ util.c \ provider.exports \ + provider.map \ $(NULL) EXTRA_DIST = \ interface.gen.c \ encoder.gen.c \ + meson.build \ $(NULL) pkcs11_la_CFLAGS = $(AM_CFLAGS) $(OPENSSL_CFLAGS) -Wall -Werror diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 00000000..cbaad021 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,35 @@ +pkcs11_provider_sources = [ + 'asymmetric_cipher.c', + 'debug.c', + 'encoder.c', + 'digests.c', + 'exchange.c', + 'kdf.c', + 'keymgmt.c', + 'interface.c', + 'objects.c', + 'provider.h', + 'provider.c', + 'random.c', + 'session.c', + 'signature.c', + 'slot.c', + 'store.c', + 'tls.c', + 'util.c', +] + +pkcs11_provider_map = meson.current_source_dir() / 'provider.map' +pkcs11_provider_ldflags = cc.get_supported_link_arguments([ + '-Wl,--version-script,' + pkcs11_provider_map +]) + +pkcs11_provider = shared_module( + 'pkcs11', + pkcs11_provider_sources, + name_prefix: '', + dependencies: [libcrypto], + include_directories: [configinc], + link_depends: [pkcs11_provider_map], + link_args: pkcs11_provider_ldflags, +) diff --git a/src/provider.map b/src/provider.map new file mode 100644 index 00000000..42b8f3c8 --- /dev/null +++ b/src/provider.map @@ -0,0 +1,6 @@ +{ + global: + OSSL_provider_init; + local: + *; +}; diff --git a/tests/Makefile.am b/tests/Makefile.am index 1f9b7100..188cde5f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,7 @@ EXTRA_DIST = openssl.cnf.in \ lsan.supp \ - explicit_ec.key.der explicit_ec.pub.der + explicit_ec.key.der explicit_ec.pub.der \ + meson.build libspath=@abs_top_builddir@/src/.libs testsblddir=@abs_top_builddir@/tests diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 00000000..39a41dba --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,157 @@ +if p11_kit.found() + # p11-kit-client module doesn't support Windows, so hard-coding .so is fine + p11_module_path = p11_kit.get_variable(pkgconfig: 'p11_module_path') + p11_client_path = p11_module_path / 'p11-kit-client.so' +endif + +nss_softokn = dependency('nss-softokn', required: false) +if not nss_softokn.found() + nss_softokn = dependency('nss', required: false) +endif +softokendir = '' +softokensubdir = '' +if nss_softokn.found() + fs = import('fs') + softokendir = nss_softokn.get_variable(pkgconfig: 'libdir') + if fs.exists(softokendir / 'libsoftokn3@0@'.format(shlext)) + softokensubdir = '' + elif fs.exists(softokendir / 'nss' / 'libsoftokn3@0@'.format(shlext)) + softokensubdir = 'nss' + else + warning('Softoken library missing, tests will fail!') + endif +endif + +conf_env = environment({ + 'LIBSPATH': meson.project_build_root() / 'src', + 'TESTSSRCDIR': meson.current_source_dir(), + 'TESTBLDDIR': meson.current_build_dir(), + 'SHARED_EXT': shlext, + 'SOFTOKNPATH': softokendir / softokensubdir, + 'P11KITCLIENTPATH': p11_client_path, +}) + +softoken_conf = custom_target( + 'generate softoken configuration', + output: 'tmp.softokn.log', + env: conf_env, + command: [ + find_program('setup-softokn.sh'), + ], + capture: true, +) + +softhsm_conf = custom_target( + 'generate softhsm configuration', + output: 'tmp.softhsm.log', + env: conf_env, + command: [ + find_program('setup-softhsm.sh'), + ], + capture: true, +) + +test_env = environment({ + 'TEST_PATH': meson.current_source_dir(), + 'TESTBLDDIR': meson.current_build_dir(), +}) + +valgrind = find_program('valgrind', required: false) +if valgrind.found() + add_test_setup('valgrind', + exe_wrapper: [ + valgrind, + '--num-callers=30', + '-q', + '--keep-debuginfo=yes', + ], + env: test_env, + timeout_multiplier: 20, + ) +endif + +if get_option('b_sanitize') == 'address' + preload_libasan = get_option('preload_libasan') + if preload_libasan == 'auto' + preload_libasan = run_command( + [cc.cmd_array()[0], '-print-file-name=libasan.so'], + check: true, + capture: true, + ).stdout().strip() + endif + + # Avoids closing dlopened libraries for ASan to be able to print usable traces + fake_dlclose = shared_module( + 'fake_dlclose', + 'fake_dlclose.c', + name_prefix: '', + ) + + test_env.set('ASAN_OPTIONS', 'fast_unwind_on_malloc=0') + test_env.set('LSAN_OPTIONS', 'suppressions=@0@/lsan.supp'.format(meson.current_source_dir())) + test_env.set('FAKE_DLCLOSE', fake_dlclose.full_path()) + # LD_PRELOAD is needed before invoking openssl as it is not instrumented with + # asan and asan needs to be loaded as a first dynamic library of the process. + if preload_libasan != 'no' + test_env.set('CHECKER', 'env LD_PRELOAD=@0@:@1@'.format(preload_libasan, fake_dlclose.full_path())) + else + test_env.set('CHECKER', 'env LD_PRELOAD=@0@'.format(fake_dlclose.full_path())) + endif +endif + +test_programs = [ + 'tsession', + 'tgenkey', + 'tlsctx', + 'tdigests', + 'treadkeys', + 'tcmpkeys', + 'tfork', + 'pincache', +] + +foreach t : test_programs + executable(t, '@0@.c'.format(t), + include_directories: [configinc], + dependencies: [libcrypto, libssl]) +endforeach + +tests = { + 'basic': {'suites': ['softokn', 'softhsm']}, + 'pubkey': {'suites': ['softokn', 'softhsm']}, + 'certs': {'suites': ['softokn', 'softhsm']}, + 'ecc': {'suites': ['softokn', 'softhsm']}, + 'edwards': {'suites': ['softhsm']}, + 'ecdh': {'suites': ['softokn']}, + 'democa': {'suites': ['softokn', 'softhsm'], 'is_parallel': false}, + 'digest': {'suites': ['softokn', 'softhsm']}, + 'fork': {'suites': ['softokn', 'softhsm']}, + 'oaepsha2': {'suites': ['softokn']}, + 'hkdf': {'suites': ['softokn']}, + 'rsapss': {'suites': ['softokn']}, + 'genkey': {'suites': ['softokn', 'softhsm']}, + 'session': {'suites': ['softokn', 'softhsm']}, + 'rand': {'suites': ['softokn', 'softhsm']}, + 'readkeys': {'suites': ['softokn', 'softhsm']}, + 'tls': {'suites': ['softokn', 'softhsm'], 'is_parallel': false}, + 'uri': {'suites': ['softokn', 'softhsm']}, + 'ecxc': {'suites': ['softhsm']}, + 'cms': {'suites': ['softokn']}, +} + +test_wrapper = find_program('test-wrapper') + +foreach t, extra_args : tests + is_parallel = extra_args.get('is_parallel', true) + foreach suite : extra_args.get('suites', []) + test( + t, + test_wrapper, + args: '@0@-@1@.t'.format(t, suite), + suite: suite, + depends: [softoken_conf, softhsm_conf], + env: test_env, + is_parallel: is_parallel, + ) + endforeach +endforeach