commit 709fb483dcd89b560f14a2f0b26bdead70f26490 Author: Mikhail Novosyolov Date: Sat Nov 30 04:54:09 2019 +0300 Init diff --git a/.abf.yml b/.abf.yml new file mode 100644 index 0000000..136f8f6 --- /dev/null +++ b/.abf.yml @@ -0,0 +1,2 @@ +sources: + libressl-3.0.2.tar.gz: 3d025eb32b0304b5b1c317bb59add037680e3298 diff --git a/0001-Allow-custom-config-location.patch b/0001-Allow-custom-config-location.patch new file mode 100644 index 0000000..da1c68a --- /dev/null +++ b/0001-Allow-custom-config-location.patch @@ -0,0 +1,56 @@ +From 4074611c49806fa5e8937a5aa24d9084235a89a5 Mon Sep 17 00:00:00 2001 +From: Mikhail Novosyolov +Date: Fri, 29 Nov 2019 21:24:49 +0300 +Subject: [PATCH] Allow custom config location + +I want LibreSSL to: +- coexist with OpenSSL +- be installed into /opt +- do not conflict with OpenSSL devel packages +- use /etc/ssl (/etc/pki/tls in ROSA) from OpenSSL + +For this purpose, it is required to be able to separate configs of OpenSSL and LibreSSL. + +Example: +export CFLAGS="$CFLAGS -DX509_CONF_FILE='\"/etc/ssl/libressl.cnf\"'" +--- + src/lib/libcrypto/conf/conf_mod.c | 4 ++++ + src/usr.bin/openssl/apps.c | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/src/lib/libcrypto/conf/conf_mod.c b/src/lib/libcrypto/conf/conf_mod.c +index 9f252385e..f5271c89d 100644 +--- a/src/lib/libcrypto/conf/conf_mod.c ++++ b/src/lib/libcrypto/conf/conf_mod.c +@@ -545,8 +545,12 @@ CONF_get1_default_config_file(void) + { + char *file = NULL; + ++#ifndef X509_CONF_FILE + if (asprintf(&file, "%s/openssl.cnf", + X509_get_default_cert_area()) == -1) ++#else ++ if (asprintf(&file, X509_CONF_FILE) == -1) ++#endif + return (NULL); + return file; + } +diff --git a/src/usr.bin/openssl/apps.c b/src/usr.bin/openssl/apps.c +index c9a2f34b2..313d6ecee 100644 +--- a/src/usr.bin/openssl/apps.c ++++ b/src/usr.bin/openssl/apps.c +@@ -1213,7 +1213,11 @@ make_config_name() + const char *t = X509_get_default_cert_area(); + char *p; + ++#ifndef X509_CONF_FILE + if (asprintf(&p, "%s/openssl.cnf", t) == -1) ++#else ++ if (asprintf(&p, X509_CONF_FILE) == -1) ++#endif + return NULL; + return p; + } +-- +2.20.1 + diff --git a/SUSE-extra-symver.patch b/SUSE-extra-symver.patch new file mode 100644 index 0000000..4106df3 --- /dev/null +++ b/SUSE-extra-symver.patch @@ -0,0 +1,66 @@ +From f2969c659b4cbccbb3766f72926a9a829b17d561 Mon Sep 17 00:00:00 2001 +From: Jan Engelhardt +Date: Mon, 4 Dec 2017 21:25:11 +0100 +Subject: [PATCH 8/8] SUSE extra symver + +Add symbol versions into the library to be on par with openssl. +--- + libressl/crypto/Makefile.am | 6 +++++- + libressl/ssl/Makefile.am | 6 +++++- + libressl/tls/Makefile.am | 6 +++++- + 3 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/libressl/crypto/Makefile.am b/libressl/crypto/Makefile.am +index f66bb73..fdb970b 100644 +--- a/libressl/crypto/Makefile.am ++++ b/libressl/crypto/Makefile.am +@@ -93,7 +93,11 @@ if HOST_WIN + -mv crypto_portable.sym.tmp crypto_portable.sym + endif + +-libcrypto_la_LDFLAGS = -version-info @LIBCRYPTO_VERSION@ -no-undefined -export-symbols crypto_portable.sym ++crypto2.sym: crypto_portable.sym ++ (echo 'LIBRESSL { global: '; sed -e 's/\(.*\)/\1;/' <$<; echo 'local: *; };') >$@ ++ ++libcrypto_la_DEPENDENCIES = crypto2.sym libcompat.la ++libcrypto_la_LDFLAGS = -version-info @LIBCRYPTO_VERSION@ -no-undefined -Wl,--version-script=crypto2.sym + libcrypto_la_LIBADD = libcompat.la + if !HAVE_EXPLICIT_BZERO + libcrypto_la_LIBADD += libcompatnoopt.la +diff --git a/libressl/ssl/Makefile.am b/libressl/ssl/Makefile.am +index 02109f5..a92c86c 100644 +--- a/libressl/ssl/Makefile.am ++++ b/libressl/ssl/Makefile.am +@@ -6,7 +6,11 @@ EXTRA_DIST = VERSION + EXTRA_DIST += CMakeLists.txt + EXTRA_DIST += ssl.sym + +-libssl_la_LDFLAGS = -version-info @LIBSSL_VERSION@ -no-undefined -export-symbols $(top_srcdir)/ssl/ssl.sym ++ssl2.sym: ssl.sym ++ (echo 'LIBRESSL { global: '; sed -e 's/\(.*\)/\1;/' <$<; echo 'local: *; };') >$@ ++ ++libssl_la_DEPENDENCIES = ssl2.sym ++libssl_la_LDFLAGS = -version-info @LIBSSL_VERSION@ -no-undefined -Wl,--version-script=ssl2.sym + libssl_la_LIBADD = $(abs_top_builddir)/crypto/libcrypto.la + + libssl_la_SOURCES = bio_ssl.c +diff --git a/libressl/tls/Makefile.am b/libressl/tls/Makefile.am +index 40ba156..cc03b2d 100644 +--- a/libressl/tls/Makefile.am ++++ b/libressl/tls/Makefile.am +@@ -6,7 +6,11 @@ EXTRA_DIST = VERSION + EXTRA_DIST += CMakeLists.txt + EXTRA_DIST += tls.sym + +-libtls_la_LDFLAGS = -version-info @LIBTLS_VERSION@ -no-undefined -export-symbols $(top_srcdir)/tls/tls.sym ++tls2.sym: tls.sym ++ (echo 'LIBRESSL { global: '; sed -e 's/\(.*\)/\1;/' <$<; echo 'local: *; };') >$@ ++ ++libtls_la_DEPENDENCIES = tls2.sym ++libtls_la_LDFLAGS = -version-info @LIBTLS_VERSION@ -no-undefined -Wl,--version-script=tls2.sym + libtls_la_LIBADD = $(abs_top_builddir)/ssl/libssl.la + libtls_la_LIBADD += $(abs_top_builddir)/crypto/libcrypto.la + libtls_la_LIBADD += $(PLATFORM_LDADD) +-- +2.21.0 + diff --git a/libressl.rpmlintrc b/libressl.rpmlintrc new file mode 100644 index 0000000..68e6f3c --- /dev/null +++ b/libressl.rpmlintrc @@ -0,0 +1,7 @@ +# I have put %define _use_internal_dependency_generator 0 +# Why does this error still occur?! +addFilter("E: external-depfilter-with-internal-depgen") +# /opt is used intentionally +addFilter("E: dir-or-file-in-opt") +# We add rpath to *.pc in %%install intentionally +addFilter("E: rpath-in-buildconfig") diff --git a/libressl.spec b/libressl.spec new file mode 100644 index 0000000..5b4c190 --- /dev/null +++ b/libressl.spec @@ -0,0 +1,421 @@ +# Initial purpose of packaging LibreSSL was the need to have a handy +# tool to work with GOST keys easily (LibreSSL has GOSTs out of the box). +# netcat-openbsd is now also packaged here. +# LibreSSL is a fork of OpenSSL and has same libraries, binaries +# and fucntions names, that is why it cannot coexist with OpenSSL +# easily and is packages to a separate prefix here. +# Remember some directories before changing %%_prefix, o - original +%define _oprefix /usr +%define _obindir %{_oprefix}/bin +%define _omandir %{_oprefix}/share/man +%define _olibdir %{_oprefix}/%{_lib} +%define _prefix /opt/libressl +# No need to have /opt/libressl/lib64, use /opt/libressl/lib +%define _libdir %{_prefix}/lib +# Keep package docs in normal locations +%define _defaultdocdir %{_oprefix}/share/doc +# Disable /usr/share/spec-helper/relink_symlinks +# to make sure that symlinks are not broken +%define dont_relink 1 +# If man pages compression is not set up, skip it +%{?!_compress:%define _compress /bin/true} +%{?!_extension:%define _extension .xz} + +# Fallback to the old external dependency generator +# http://lists.rosalab.ru/pipermail/rosa-devel/2013-April/004702.html +# http://lists.rosalab.ru/pipermail/rosa-devel/2013-April/004703.html +# because there is no way to filter by filepath in the internal one +# TODO: avoid using external dep. gen. +%define _use_internal_dependency_generator 0 +# Those libraries in /opt are not available without RPATH or ld.so.conf +%define _exclude_files_from_autoprov %{_libdir} +# We rename e.g. libtls.pc to libressl-tls.pc, make sure that we do not +# get odd provides and break the repository if forgot to rename something +#define __noautoprov '.*openssl.*|pkgconfig\\(lib.*' +%define _provides_exceptions '.*openssl.*|pkgconfig(lib.*' +# libressl-devel must not require devel(libxxx) +# because it has those devels inside himself +%define _requires_exceptions 'devel(lib.*' +# Ideas behind this dependency generation crap are the following: +# - libressl-devel must provide pkgconfig(libressl*) +# - libressl-devel must not provide pkgconfig(openssl), +# pkgconfig(libtls), pkgconfig(libcrypto), pkgconfig(libssl) +# to prevent conflicts with OpenSSL +# - libressl must not depend from separate library packages with +# libtls.so.*, libcrypto.so.*, libssl.so.*, instead it has +# copies of those libraries in /opt/libressl/lib/ and has RPATH +# - packages netcat-openbsd and ocspcheck are intended to be +# installable without installing libressl package with a lot of +# odd stuff; so libtls.so.*, libcrypto.so.* and libssl.so.* are +# packaged into separate packages, RPATHs are removed and nc +# and ocspcheck must depend from separate libs packages and will +# use /usr/lib(64)/lib*.so.* instead of /opt/libressl/lib/*.so.* +# - there are no per-library devel packages, only one libressl-devel. +# // mikhailnov, 30.11.2019 + +%define libcrypto_sover 45 +%define libssl_sover 47 +%define libtls_sover 19 +%define libssl_pkg %mklibname ssl_libressl %{libssl_sover} +%define libcrypto_pkg %mklibname crypto_libressl %{libcrypto_sover} +%define libtls_pkg %mklibname tls_libressl %{libtls_sover} + +Summary: LibreSSL utils and libs coexisting with OpenSSL +Name: libressl +Version: 3.0.2 +Release: 1 +# The code is distributed under ISC license except of original OpenSSL code +License: ISC and BSD-like +Group: System/Libraries +Url: http://libressl.org +Source0: http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-%{version}.tar.gz +# TODO: add printing config location to `openssl version` +Source1: 0001-Allow-custom-config-location.patch +Source10: libressl.rpmlintrc +# If both openssl and libressl libraries are loaded into one runtime, +# versioning their symbols will or may allow them to coexist +# (patch from ALT Linux) +Patch2: SUSE-extra-symver.patch +# From https://www.mitchr.me/SS/exampleCode/openssl.html +Source20: test.c +Source22: test2.c +# From import/openssl, originates from Fedora +Source25: test5.c +# To get %%_openssldir and for %%check +BuildRequires: openssl-devel +# readelf <...> | <...> +BuildRequires: binutils grep gawk +BuildRequires: chrpath +# This LibreSSL uses /etc/pki/tls from system OpenSSL +# but most functions will work without its files +Suggests: openssl +# Prevent dependencies from lib*_libressl* subpackages for the main package +# because it may freely use /opt/libressl/lib/*.so.* +# but put "Autoreq: 1" in other subpackages which may be installed without +# libressl main package being installed and will use /usr/lib(64)/.*so.* +Autoreq: 0 + +%description +LibreSSL utils and libs coexisting with OpenSSL. +GOST is supported out of the box. + +%files +%doc ChangeLog COPYING +# %%_bindir here is /opt/libressl/bin +# %%_obindir is /usr/bin +# %%_mandir is /opt/libressl/share/man +# %%_omandir is /usr/share/man +%{_bindir}/openssl +%{_bindir}/libressl +%{_obindir}/libressl +%{_mandir}/man1/* +%{_mandir}/man5/* +%{_omandir}/*/* +%{_libdir}/*.so.* +%config(noreplace) %{_openssldir}/libressl.cnf +%config(noreplace) %{_openssldir}/x509v3.cnf +%exclude %{_omandir}/man3/* +%exclude %{_omandir}/*/nc.* +%exclude %{_omandir}/*/netcat.* +%exclude %{_omandir}/*/ocspcheck.* +%exclude %{_libdir}/*.so +#------------------------------------------------------------------------------------- + +%package -n %{libcrypto_pkg} +Summary: libcrypto library from LibreSSL +Autoreq: 1 + +%description -n %{libcrypto_pkg} +libcrypto library from LibreSSL + +%files -n %{libcrypto_pkg} +%{_olibdir}/libcrypto.so.%{libcrypto_sover}* +#------------------------------------------------------------------------------------- + +%package -n %{libssl_pkg} +Summary: libssl library from LibreSSL +Autoreq: 1 + +%description -n %{libssl_pkg} +libssl library from LibreSSL + +%files -n %{libssl_pkg} +%{_olibdir}/libssl.so.%{libssl_sover}* +#------------------------------------------------------------------------------------- + +%package -n %{libtls_pkg} +Summary: libtls library from LibreSSL +Autoreq: 1 + +%description -n %{libtls_pkg} +libtls library from LibreSSL + +%files -n %{libtls_pkg} +%{_olibdir}/libtls.so.%{libtls_sover}* +#------------------------------------------------------------------------------------- + +%package devel +Summary: LibreSSL devel package +Requires: %{name} = %{EVRD} +Autoreq: 1 + +%description devel +LibreSSL devel package. Devel libraries are in %{_libdir}, +but the same runtime libraries exist in +%{_libdir} +and +%{_olibdir}. +After linking, binaries will load libs from %{_olibdir}. +When using pkg-config, RPATH is set to %{_libdir}, +remove RPATH/RUNPATH manually if needed. + +%files devel +%doc ChangeLog COPYING +%{_libdir}/*.so +%{_olibdir}/pkgconfig/*.pc +%{_includedir} +%{_mandir}/man3/* +%{_omandir}/man3/* +#------------------------------------------------------------------------------------- + +%package -n ocspcheck +Summary: Utility to validate certificates +Autoreq: 1 + +%description -n ocspcheck +Utility to validate a certificate against its OCSP responder and +save the reply for stapling + +%files -n ocspcheck +%doc ChangeLog COPYING +%{_obindir}/ocspcheck +%{_omandir}/man*/ocspcheck.* +#------------------------------------------------------------------------------------- + +%package -n netcat-openbsd +Summary: Reads and writes data across network connections using TCP or UDP +Conflicts: netcat < 1.0 +Conflicts: netcat-traditional +Conflicts: netcat-gnu +# netcat-openbsd 1.89 was imported from Mandriva in 2012 and now, in 2019, is replaced +#Obsoletes: netcat-openbsd < 1.89.1 +Provides: netcat-tls = %{EVRD} +Provides: netcat-libressl = %{EVRD} +Provides: nc = %{EVRD} +Autoreq: 1 + +%description -n netcat-openbsd +The nc package contains Netcat (the program is actually nc), a simple +utility for reading and writing data across network connections, using +the TCP or UDP protocols. Netcat is intended to be a reliable back-end +tool which can be used directly or easily driven by other programs and +scripts. Netcat is also a feature-rich network debugging and +exploration tool, since it can create many different connections and +has many built-in capabilities. + +You may want to install the netcat package if you are administering a +network and you'd like to use its debugging and network exploration +capabilities. + +%files -n netcat-openbsd +%doc ChangeLog COPYING +%{_obindir}/nc +%{_obindir}/netcat +%{_omandir}/man*/nc.* +%{_omandir}/man*/netcat.* +#------------------------------------------------------------------------------------- + +%prep +%setup -q +%patch2 -p2 +# Patch is against gits https://github.com/libressl-portable/ +# Release tarball is packaged in a tricky way +cat %{SOURCE1} | sed \ + -e 's,src/lib/libcrypto/,crypto/,g' \ + -e 's,src/usr.bin/openssl/,apps/openssl/,g' \ + > 1.patch +patch -p1 < 1.patch + +%build +%setup_compile_flags +%serverbuild +# Use the same %%_openssl dir with OpenSSL, but separate the config +# (note that we patch libressl, X509_CONF_FILE is not upstream) +export CFLAGS="$CFLAGS -DX509_CONF_FILE='\"%{_openssldir}/libressl.cnf\"'" +# TODO: why by default without this runpath is not set on libcrypto.so*, +# but is set on libtls.so* and libssl.so*? +export LDFLAGS="$LDFLAGS -Wl,-rpath=%{_libdir}" +autoreconf -if #patch2 +# static libs are required for tests target in Makefile +%configure2_5x \ + --enable-nc \ + --enable-static \ + --with-openssldir=%{_openssldir} +%make + +%install +set +f # explicitly enable shell globbing + +%makeinstall_std + +# Some ideas about mans are from ALT Linux spec +install -m 0644 apps/nc/nc.1 %{buildroot}%{_mandir}/man1/nc.1 +install -m 0644 apps/nc/nc.1 %{buildroot}%{_mandir}/man1/netcat.1 +mkdir -p %{buildroot}%{_mandir}/man8/ +install -m 0644 apps/ocspcheck/ocspcheck.8 %{buildroot}%{_mandir}/man8/ocspcheck.8 +for i in $(seq 1 8) +do + man_dir="%{buildroot}%{_mandir}/man${i}" + if [ ! -d "$man_dir" ]; then continue; fi + ( cd "$man_dir" + grep -Irl '/etc/ssl' . | xargs sed -i 's,/etc/ssl,%{_openssldir},g' || : + if find . -name 'libressl_*' | grep -q '.' ; then + echo 'Rewrite spec because upstream libressl_* manpages appeared!' + exit 1 + fi + # Make all man pages with potentially the same names as in OpenSSL + # be avaialble in standard man directories, but prevent conflicts with OpenSSL + for openssl_manpage in $(ls -1v | grep -vE '^LIBRESSL_|^netcat|^nc|^ocspcheck|^openssl\.') ; do + openssl_LibreSSL_manpage="libressl_${openssl_manpage}" + cp -v "$openssl_manpage" "$openssl_LibreSSL_manpage" + done + for openssl_manpage in $(ls -1v | grep '^openssl\.') ; do + openssl_LibreSSL_manpage="$(echo "$openssl_manpage" | sed -e 's,openssl,libressl,g')" + cp -v "$openssl_manpage" "$openssl_LibreSSL_manpage" + done + ) +done +mkdir -p %{buildroot}%{_omandir} +cp -rv %{buildroot}%{_mandir}/* %{buildroot}%{_omandir}/ +# We have put libressl_ prefixed mans to system man directory, +# now delete them from /opt/libressl/share/man to leave +# mans with original names in /opt/libressl/share/man +rm -fv %{buildroot}%{_mandir}/*/libressl_* +rm -fv %{buildroot}%{_omandir}/*/openssl.* +# Fully delete other mans from /opt +rm -fv %{buildroot}%{_mandir}/*/{nc,netcat,ocspcheck}* +# Manually compress man pages because we use both +# /usr/share/man and /opt/libressl/share/man, +# /usr/lib/rpm/brp-compress will not compress both of them +mkdir tmp +pushd tmp + sed -e 's,./usr/share/man/man*,%{buildroot}%{_mandir}/man* %{buildroot}%{_omandir}/man*,g' \ + %{_usrlibrpm}/brp-compress > ./brp-compress.sh + chmod +x ./brp-compress.sh + COMPRESS="%{_compress}" COMPRESS_EXT="%{_extension}" ./brp-compress.sh +popd + +mkdir -p %{buildroot}%{_obindir} +mv -v %{buildroot}%{_bindir}/{nc,ocspcheck} %{buildroot}%{_obindir}/ +( cd %{buildroot}%{_bindir} ; ln -s openssl libressl ) +( cd %{buildroot}%{_obindir} ; ln -s %{_bindir}/openssl libressl ) +( cd %{buildroot}%{_obindir} ; ln -s nc netcat ) +( cd %{buildroot}%{_includedir} ; ln -s openssl libressl ) +# Remove static libs +( cd %{buildroot}%{_libdir} ; rm -fv *.la *.a ) + +# Build scripts set RUNPATH, it is needed because /usr/bin/* are linked with +# /opt/libressl/lib/*.so.*, make sure that RUNPATH exists +for i in $(find %{buildroot}%{_bindir} %{buildroot}%{_libdir} -type f -executable) ; do + rpath="$(readelf -a "$i" | grep '(RUNPATH)' | head -n 1 | awk '{print $NF}' | tr -d '[]')" + if [ "$rpath" != '%{_libdir}' ]; then + echo "Empty or incorrect RPATH on ${i}!" + exit 1 + fi +done + +mkdir -p %{buildroot}/%{_olibdir}/pkgconfig +mv -v %{buildroot}/%{_libdir}/pkgconfig/*.pc %{buildroot}/%{_olibdir}/pkgconfig +for i in share %{_lib} +do + pkgconfig_dir="%{buildroot}/%{_oprefix}/${i}/pkgconfig" + if [ ! -d "$pkgconfig_dir" ]; then continue; fi + ( cd "$pkgconfig_dir" + for f in *.pc + do + if [ "$f" != 'openssl.pc' ] && ! grep '^Name:' "$f" | grep -qi 'libressl\-'; then + echo "Name in $f is not prefixed with LibreSSL-" + exit 1 + fi + # Restore ability to work with custom prefix + # It is lost due to --exec_prefix=XXX in %%configure2_5x + sed -i -r \ + -e 's,^exec_prefix=.+,exec_prefix=${prefix},' \ + -e 's,^libdir=.+,libdir=${exec_prefix}/lib,' \ + -e 's,^includedir=.+,includedir=${prefix}/include,' \ + "$f" + # TODO: is rpath in *.pc really needed? + if ! grep '^Libs:' "$f" + then + echo 'Libs: -Wl,-rpath=${libdir}' >> "$f" + else + # https://unix.stackexchange.com/a/328656 + sed -i -e '/^Libs:/s/$/ -Wl,-rpath=${libdir}/' "$f" + grep '^Libs:' "$f" | grep -q rpath || exit 1 + fi + mv -v "$f" "libressl-${f}" + # Requires: libxx -> Requires: libressl-libxx + sed -i \ + -e 's/libcrypto/libressl-libcrypto/g' \ + -e 's/libtls/libressl-liblts/g' \ + -e 's/libssl/libressl-libssl/g' \ + -e 's/libressl-libressl-/libressl-/g' \ + "libressl-${f}" + if [ -f libressl-openssl.pc ]; then + mv -v libressl-openssl.pc libressl.pc + fi + done + ) +done + +cp -v %{buildroot}/%{_libdir}/{libcrypto,libtls,libssl}.so.* %{buildroot}/%{_olibdir}/ +chrpath --delete %{buildroot}/%{_olibdir}/*.so.* +chrpath --delete %{buildroot}/%{_obindir}/{nc,ocspcheck} + +# Stuff from system OpenSSL will be used +rm -fvr %{buildroot}/%{_openssldir}/{certs,cert.pem} +mv -v %{buildroot}/%{_openssldir}/openssl.cnf %{buildroot}/%{_openssldir}/libressl.cnf + +%check +_pcf(){ + unset oflags nflags + oflags="$(eval $@)" + nflags="$(echo "$oflags" | sed -e 's,%{_prefix},%{buildroot}%{_prefix},g')" +} +rflags="-Wl,-rpath=%{buildroot}%{_libdir},-rpath=%{buildroot}%{_olibdir}" +# These tests caught a lot of mistakes during first builds +export PKG_CONFIG_PATH=%{buildroot}/%{_olibdir}/pkgconfig +# (test 1) Check that openssldir is correct +export LD_LIBRARY_PATH=%{buildroot}/%{_libdir} +%{buildroot}/%{_bindir}/libressl version -d | awk '{print $NF}' | tr -d '""' | grep -q '^%{_openssldir}$' +unset LD_LIBRARY_PATH +# (test 2) Check that path to config file is correct +# and also check that pkg-config libressl points to libressl, not openssl +_pcf pkg-config --libs --cflags libressl +%__cc -o test2 %{SOURCE22} $nflags $rflags +ldd ./test2 +[ "$(./test2)" = "%{_openssldir}/libressl.cnf" ] || exit 1 +# Check that our pkgconfig hacks somehow work +# (test 3) There is no /opt/libressl/ at build time +_pcf pkg-config --libs --cflags libressl-libcrypto +%__cc -o test3 %{SOURCE20} $nflags $rflags +ldd ./test3 +ldd ./test3 | grep -E '%{_prefix}.*/libcrypto\.so\.%{libcrypto_sover}' +./test3 | grep Hello +# (test 4) Check that OpenSSL and LibreSSL devel parts coexist correctly +# (build with libcrypto from OpenSSL) +_pcf pkg-config --libs --cflags libcrypto +%__cc -o test4 %{SOURCE20} $nflags $rflags +ldd ./test4 +ldd ./test4 | grep -v 'libcrypto\.so\.%{libcrypto_sover}' +ldd ./test4 | grep -v '%{_prefix}' +./test4 | grep Hello +# (test 5) Check that flags from all *.pc are valid +# libtls is overlinking here, but check linking +_pcf pkg-config --libs --cflags libressl libressl-libssl libressl-libtls libressl-libcrypto +%__сс -o test5 %{SOURCE25} $nflags $rflags -lpthread -lz -ldl +ldd ./test5 +ldd ./test3 | grep -E '%{_prefix}.*/libcrypto\.so\.%{libcrypto_sover}' +ldd ./test3 | grep -E '%{_prefix}.*/libssl\.so\.%{libssl_sover}' +ldd ./test3 | grep -E '%{_prefix}.*/libtls\.so\.%{libtls_sover}' +./test5 --threads 2 diff --git a/test.c b/test.c new file mode 100644 index 0000000..9b4a4a2 --- /dev/null +++ b/test.c @@ -0,0 +1,32 @@ +/** + @file bio_hello.c + @author Mitch Richling + @Copyright Copyright 2008 by Mitch Richling. All rights reserved. + @brief Simple OpenSSL I/O example program.@EOL + @Keywords hello world openssl bio + @Std C99 + + This code has no error checking so that the basic + concepts are more visible. + + https://www.mitchr.me/SS/exampleCode/openssl.html +*/ + +#include +#include +#include + +int main(int argc, char *argv[]); + +int main(int argc, char *argv[]) { + + BIO *bio_stdout; + + bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); + + BIO_printf(bio_stdout, "Hello\n"); + + BIO_free_all(bio_stdout); + + return 0; +} diff --git a/test2.c b/test2.c new file mode 100644 index 0000000..0e3065f --- /dev/null +++ b/test2.c @@ -0,0 +1,6 @@ +// by mikhailnov +#include +int main(){ + char *f = NULL; + printf("%s", CONF_get1_default_config_file()); +} diff --git a/test5.c b/test5.c new file mode 100644 index 0000000..3b90285 --- /dev/null +++ b/test5.c @@ -0,0 +1,400 @@ +/* Test program to verify that RSA signing is thread-safe in OpenSSL. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Just assume we want to do engine stuff if we're using 0.9.6b or + * higher. This assumption is only valid for versions bundled with RHL. */ +#if OPENSSL_VERSION_NUMBER >= 0x0090602fL +#include +#define USE_ENGINE +#endif + +#define MAX_THREAD_COUNT 10000 +#define ITERATION_COUNT 10 +#define MAIN_COUNT 100 + +/* OpenSSL requires us to provide thread ID and locking primitives. */ +pthread_mutex_t *mutex_locks = NULL; +static unsigned long +thread_id_cb(void) +{ + return (unsigned long) pthread_self(); +} +static void +lock_cb(int mode, int n, const char *file, int line) +{ + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&mutex_locks[n]); + } else { + pthread_mutex_unlock(&mutex_locks[n]); + } +} + +struct thread_args { + RSA *rsa; + int digest_type; + unsigned char *digest; + unsigned int digest_len; + unsigned char *signature; + unsigned int signature_len; + pthread_t main_thread; +}; + +static int print = 0; + +pthread_mutex_t sign_lock = PTHREAD_MUTEX_INITIALIZER; +static int locked_sign = 0; +static void SIGN_LOCK() {if (locked_sign) pthread_mutex_lock(&sign_lock);} +static void SIGN_UNLOCK() {if (locked_sign) pthread_mutex_unlock(&sign_lock);} + +pthread_mutex_t verify_lock = PTHREAD_MUTEX_INITIALIZER; +static int locked_verify = 0; +static void VERIFY_LOCK() {if (locked_verify) pthread_mutex_lock(&verify_lock);} +static void VERIFY_UNLOCK() {if (locked_verify) pthread_mutex_unlock(&verify_lock);} + +pthread_mutex_t failure_count_lock = PTHREAD_MUTEX_INITIALIZER; +long failure_count = 0; +static void +failure() +{ + pthread_mutex_lock(&failure_count_lock); + failure_count++; + pthread_mutex_unlock(&failure_count_lock); +} + +static void * +thread_main(void *argp) +{ + struct thread_args *args = argp; + unsigned char *signature; + unsigned int signature_len, signature_alloc_len; + int ret, i; + + signature_alloc_len = args->signature_len; + if (RSA_size(args->rsa) > signature_alloc_len) { + signature_alloc_len = RSA_size(args->rsa); + } + signature = malloc(signature_alloc_len); + if (signature == NULL) { + fprintf(stderr, "Skipping checks in thread %lu -- %s.\n", + (unsigned long) pthread_self(), strerror(errno)); + pthread_exit(0); + return NULL; + } + for (i = 0; i < ITERATION_COUNT; i++) { + signature_len = signature_alloc_len; + SIGN_LOCK(); + ret = RSA_check_key(args->rsa); + ERR_print_errors_fp(stdout); + if (ret != 1) { + failure(); + break; + } + ret = RSA_sign(args->digest_type, + args->digest, + args->digest_len, + signature, &signature_len, + args->rsa); + SIGN_UNLOCK(); + ERR_print_errors_fp(stdout); + if (ret != 1) { + failure(); + break; + } + + VERIFY_LOCK(); + ret = RSA_verify(args->digest_type, + args->digest, + args->digest_len, + signature, signature_len, + args->rsa); + VERIFY_UNLOCK(); + if (ret != 1) { + fprintf(stderr, + "Signature from thread %lu(%d) fails " + "verification (passed in thread #%lu)!\n", + (long) pthread_self(), i, + (long) args->main_thread); + ERR_print_errors_fp(stdout); + failure(); + continue; + } + if (print) { + fprintf(stderr, ">%d\n", i); + } + } + free(signature); + + pthread_exit(0); + + return NULL; +} + +unsigned char * +xmemdup(unsigned char *s, size_t len) +{ + unsigned char *r; + r = malloc(len); + if (r == NULL) { + fprintf(stderr, "Out of memory.\n"); + ERR_print_errors_fp(stdout); + assert(r != NULL); + } + memcpy(r, s, len); + return r; +} + +int +main(int argc, char **argv) +{ + RSA *rsa; + MD5_CTX md5; + int fd, i; + pthread_t threads[MAX_THREAD_COUNT]; + int thread_count = 1000; + unsigned char *message, *digest; + unsigned int message_len, digest_len; + unsigned char *correct_signature; + unsigned int correct_siglen, ret; + struct thread_args master_args, *args; + int sync = 0, seed = 0; + int again = 1; +#ifdef USE_ENGINE + char *engine = NULL; + ENGINE *e = NULL; +#endif + + pthread_mutex_init(&failure_count_lock, NULL); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--seed") == 0) { + printf("Seeding PRNG.\n"); + seed++; + } else + if (strcmp(argv[i], "--sync") == 0) { + printf("Running synchronized.\n"); + sync++; + } else + if ((strcmp(argv[i], "--threads") == 0) && (i < argc - 1)) { + i++; + thread_count = atol(argv[i]); + if (thread_count > MAX_THREAD_COUNT) { + thread_count = MAX_THREAD_COUNT; + } + printf("Starting %d threads.\n", thread_count); + sync++; + } else + if (strcmp(argv[i], "--sign") == 0) { + printf("Locking signing.\n"); + locked_sign++; + } else + if (strcmp(argv[i], "--verify") == 0) { + printf("Locking verifies.\n"); + locked_verify++; + } else + if (strcmp(argv[i], "--print") == 0) { + printf("Tracing.\n"); + print++; +#ifdef USE_ENGINE + } else + if ((strcmp(argv[i], "--engine") == 0) && (i < argc - 1)) { + printf("Using engine \"%s\".\n", argv[i + 1]); + engine = argv[i + 1]; + i++; +#endif + } else { + printf("Bad argument: %s\n", argv[i]); + return 1; + } + } + + /* Get some random data to sign. */ + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Error opening /dev/urandom: %s\n", + strerror(errno)); + } + + if (print) { + fprintf(stderr, "Reading random data.\n"); + } + message = malloc(message_len = 9371); + read(fd, message, message_len); + close(fd); + + /* Initialize the SSL library and set up thread-safe locking. */ + ERR_load_crypto_strings(); + SSL_library_init(); + mutex_locks = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); + for (i = 0; i < CRYPTO_num_locks(); i++) { + pthread_mutex_init(&mutex_locks[i], NULL); + } + CRYPTO_set_id_callback(thread_id_cb); + CRYPTO_set_locking_callback(lock_cb); + ERR_print_errors_fp(stdout); + + /* Seed the PRNG if we were asked to do so. */ + if (seed) { + if (print) { + fprintf(stderr, "Seeding PRNG.\n"); + } + RAND_add(message, message_len, message_len); + ERR_print_errors_fp(stdout); + } + + /* Turn on a hardware crypto device if asked to do so. */ +#ifdef USE_ENGINE + if (engine) { +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + ENGINE_load_builtin_engines(); +#endif + if (print) { + fprintf(stderr, "Initializing \"%s\" engine.\n", + engine); + } + e = ENGINE_by_id(engine); + ERR_print_errors_fp(stdout); + if (e) { + i = ENGINE_init(e); + ERR_print_errors_fp(stdout); + i = ENGINE_set_default_RSA(e); + ERR_print_errors_fp(stdout); + } + } +#endif + + /* Compute the digest for the signature. */ + if (print) { + fprintf(stderr, "Computing digest.\n"); + } + digest = malloc(digest_len = MD5_DIGEST_LENGTH); + MD5_Init(&md5); + MD5_Update(&md5, message, message_len); + MD5_Final(digest, &md5); + + /* Generate a signing key. */ + if (print) { + fprintf(stderr, "Generating key.\n"); + } + rsa = RSA_generate_key(4096, 3, NULL, NULL); + ERR_print_errors_fp(stdout); + if (rsa == NULL) { + _exit(1); + } + + /* Sign the data. */ + correct_siglen = RSA_size(rsa); + correct_signature = malloc(correct_siglen); + for (i = 0; i < MAIN_COUNT; i++) { + if (print) { + fprintf(stderr, "Signing data (%d).\n", i); + } + ret = RSA_check_key(rsa); + ERR_print_errors_fp(stdout); + if (ret != 1) { + failure(); + } + correct_siglen = RSA_size(rsa); + ret = RSA_sign(NID_md5, digest, digest_len, + correct_signature, &correct_siglen, + rsa); + ERR_print_errors_fp(stdout); + if (ret != 1) { + _exit(2); + } + if (print) { + fprintf(stderr, "Verifying data (%d).\n", i); + } + ret = RSA_verify(NID_md5, digest, digest_len, + correct_signature, correct_siglen, + rsa); + if (ret != 1) { + _exit(2); + } + } + + /* Collect up the inforamtion which other threads will need for + * comparing their signature results with ours. */ + master_args.rsa = rsa; + master_args.digest_type = NID_md5; + master_args.digest = digest; + master_args.digest_len = digest_len; + master_args.signature = correct_signature; + master_args.signature_len = correct_siglen; + master_args.main_thread = pthread_self(); + + fprintf(stdout, "Performing %d signatures in each of %d threads " + "(%d, %d).\n", ITERATION_COUNT, thread_count, + digest_len, correct_siglen); + fflush(NULL); + + /* Start up all of the threads. */ + for (i = 0; i < thread_count; i++) { + args = malloc(sizeof(struct thread_args)); + args->rsa = RSAPrivateKey_dup(master_args.rsa); + args->digest_type = master_args.digest_type; + args->digest_len = master_args.digest_len; + args->digest = xmemdup(master_args.digest, args->digest_len); + args->signature_len = master_args.signature_len; + args->signature = xmemdup(master_args.signature, + args->signature_len); + args->main_thread = pthread_self(); + ret = pthread_create(&threads[i], NULL, thread_main, args); + while ((ret != 0) && (errno == EAGAIN)) { + ret = pthread_create(&threads[i], NULL, + thread_main, &args); + fprintf(stderr, "Thread limit hit at %d.\n", i); + } + if (ret != 0) { + fprintf(stderr, "Unable to create thread %d: %s.\n", + i, strerror(errno)); + threads[i] = -1; + } else { + if (sync) { + ret = pthread_join(threads[i], NULL); + assert(ret == 0); + } + if (print) { + fprintf(stderr, "%d\n", i); + } + } + } + + /* Wait for all threads to complete. So long as we can find an + * unjoined thread, keep joining threads. */ + do { + again = 0; + for (i = 0; i < thread_count; i++) { + /* If we have an unterminated thread, join it. */ + if (threads[i] != -1) { + again = 1; + if (print) { + fprintf(stderr, "Joining thread %d.\n", + i); + } + pthread_join(threads[i], NULL); + threads[i] = -1; + break; + } + } + } while (again == 1); + + fprintf(stderr, "%ld failures\n", failure_count); + + return (failure_count != 0); +}