1{ lib, stdenv, fetchurl, buildPackages, perl, coreutils, writeShellScript
2, makeWrapper
3, withCryptodev ? false, cryptodev
4, withZlib ? false, zlib
5, enableSSL2 ? false
6, enableSSL3 ? false
7, enableKTLS ? stdenv.isLinux
8, static ? stdenv.hostPlatform.isStatic
9# path to openssl.cnf file. will be placed in $etc/etc/ssl/openssl.cnf to replace the default
10, conf ? null
11, removeReferencesTo
12, testers
13}:
14
15# Note: this package is used for bootstrapping fetchurl, and thus
16# cannot use fetchpatch! All mutable patches (generated by GitHub or
17# cgit) that are needed here should be included directly in Nixpkgs as
18# files.
19
20let
21 common = { version, sha256, patches ? [], withDocs ? false, extraMeta ? {} }:
22 stdenv.mkDerivation (finalAttrs: {
23 pname = "openssl";
24 inherit version;
25
26 src = fetchurl {
27 url = "https://www.openssl.org/source/${finalAttrs.pname}-${version}.tar.gz";
28 inherit sha256;
29 };
30
31 inherit patches;
32
33 postPatch = ''
34 patchShebangs Configure
35 '' + lib.optionalString (lib.versionOlder version "1.1.1") ''
36 patchShebangs test/*
37 for a in test/t* ; do
38 substituteInPlace "$a" \
39 --replace /bin/rm rm
40 done
41 ''
42 # config is a configure script which is not installed.
43 + lib.optionalString (lib.versionAtLeast version "1.1.1") ''
44 substituteInPlace config --replace '/usr/bin/env' '${buildPackages.coreutils}/bin/env'
45 '' + lib.optionalString (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isMusl) ''
46 substituteInPlace crypto/async/arch/async_posix.h \
47 --replace '!defined(__ANDROID__) && !defined(__OpenBSD__)' \
48 '!defined(__ANDROID__) && !defined(__OpenBSD__) && 0'
49 ''
50 # Move ENGINESDIR into OPENSSLDIR for static builds, in order to move
51 # it to the separate etc output.
52 + lib.optionalString static ''
53 substituteInPlace Configurations/unix-Makefile.tmpl \
54 --replace 'ENGINESDIR=$(libdir)/engines-{- $sover_dirname -}' \
55 'ENGINESDIR=$(OPENSSLDIR)/engines-{- $sover_dirname -}'
56 '';
57
58 outputs = [ "bin" "dev" "out" "man" ]
59 ++ lib.optional withDocs "doc"
60 # Separate output for the runtime dependencies of the static build.
61 # Specifically, move OPENSSLDIR into this output, as its path will be
62 # compiled into 'libcrypto.a'. This makes it a runtime dependency of
63 # any package that statically links openssl, so we want to keep that
64 # output minimal.
65 ++ lib.optional static "etc";
66 setOutputFlags = false;
67 separateDebugInfo =
68 !stdenv.hostPlatform.isDarwin &&
69 !(stdenv.hostPlatform.useLLVM or false) &&
70 stdenv.cc.isGNU;
71
72 nativeBuildInputs =
73 lib.optional (!stdenv.hostPlatform.isWindows) makeWrapper
74 ++ [ perl ]
75 ++ lib.optionals static [ removeReferencesTo ];
76 buildInputs = lib.optional withCryptodev cryptodev
77 ++ lib.optional withZlib zlib;
78
79 # TODO(@Ericson2314): Improve with mass rebuild
80 configurePlatforms = [];
81 configureScript = {
82 armv5tel-linux = "./Configure linux-armv4 -march=armv5te";
83 armv6l-linux = "./Configure linux-armv4 -march=armv6";
84 armv7l-linux = "./Configure linux-armv4 -march=armv7-a";
85 x86_64-darwin = "./Configure darwin64-x86_64-cc";
86 aarch64-darwin = "./Configure darwin64-arm64-cc";
87 x86_64-linux = "./Configure linux-x86_64";
88 x86_64-solaris = "./Configure solaris64-x86_64-gcc";
89 riscv64-linux = "./Configure linux64-riscv64";
90 }.${stdenv.hostPlatform.system} or (
91 if stdenv.hostPlatform == stdenv.buildPlatform
92 then "./config"
93 else if stdenv.hostPlatform.isBSD
94 then if stdenv.hostPlatform.isx86_64 then "./Configure BSD-x86_64"
95 else if stdenv.hostPlatform.isx86_32
96 then "./Configure BSD-x86" + lib.optionalString (stdenv.hostPlatform.parsed.kernel.execFormat.name == "elf") "-elf"
97 else "./Configure BSD-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
98 else if stdenv.hostPlatform.isMinGW
99 then "./Configure mingw${lib.optionalString
100 (stdenv.hostPlatform.parsed.cpu.bits != 32)
101 (toString stdenv.hostPlatform.parsed.cpu.bits)}"
102 else if stdenv.hostPlatform.isLinux
103 then if stdenv.hostPlatform.isx86_64 then "./Configure linux-x86_64"
104 else if stdenv.hostPlatform.isMips32 then "./Configure linux-mips32"
105 else if stdenv.hostPlatform.isMips64n32 then "./Configure linux-mips64"
106 else if stdenv.hostPlatform.isMips64n64 then "./Configure linux64-mips64"
107 else "./Configure linux-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
108 else if stdenv.hostPlatform.isiOS
109 then "./Configure ios${toString stdenv.hostPlatform.parsed.cpu.bits}-cross"
110 else
111 throw "Not sure what configuration to use for ${stdenv.hostPlatform.config}"
112 );
113
114 # OpenSSL doesn't like the `--enable-static` / `--disable-shared` flags.
115 dontAddStaticConfigureFlags = true;
116 configureFlags = [
117 "shared" # "shared" builds both shared and static libraries
118 "--libdir=lib"
119 (if !static then
120 "--openssldir=etc/ssl"
121 else
122 # Move OPENSSLDIR to the 'etc' output for static builds. Prepend '/.'
123 # to the path to make it appear absolute before variable expansion,
124 # else the 'prefix' would be prepended to it.
125 "--openssldir=/.$(etc)/etc/ssl"
126 )
127 ] ++ lib.optionals withCryptodev [
128 "-DHAVE_CRYPTODEV"
129 "-DUSE_CRYPTODEV_DIGESTS"
130 ] ++ lib.optional enableSSL2 "enable-ssl2"
131 ++ lib.optional enableSSL3 "enable-ssl3"
132 # We select KTLS here instead of the configure-time detection (which we patch out).
133 # KTLS should work on FreeBSD 13+ as well, so we could enable it if someone tests it.
134 ++ lib.optional (lib.versionAtLeast version "3.0.0" && enableKTLS) "enable-ktls"
135 ++ lib.optional (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isAarch64) "no-afalgeng"
136 # OpenSSL needs a specific `no-shared` configure flag.
137 # See https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options
138 # for a comprehensive list of configuration options.
139 ++ lib.optional (lib.versionAtLeast version "1.1.1" && static) "no-shared"
140 ++ lib.optional (lib.versionAtLeast version "3.0.0" && static) "no-module"
141 # This introduces a reference to the CTLOG_FILE which is undesired when
142 # trying to build binaries statically.
143 ++ lib.optional static "no-ct"
144 ++ lib.optional withZlib "zlib"
145 ;
146
147 makeFlags = [
148 "MANDIR=$(man)/share/man"
149 # This avoids conflicts between man pages of openssl subcommands (for
150 # example 'ts' and 'err') man pages and their equivalent top-level
151 # command in other packages (respectively man-pages and moreutils).
152 # This is done in ubuntu and archlinux, and possiibly many other distros.
153 "MANSUFFIX=ssl"
154 ];
155
156 enableParallelBuilding = true;
157
158 postInstall =
159 (if static then ''
160 # OPENSSLDIR has a reference to self
161 remove-references-to -t $out $out/lib/*.a
162 '' else ''
163 # If we're building dynamic libraries, then don't install static
164 # libraries.
165 if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then
166 rm "$out/lib/"*.a
167 fi
168
169 # 'etc' is a separate output on static builds only.
170 etc=$out
171 '') + ''
172 mkdir -p $bin
173 mv $out/bin $bin/bin
174
175 '' + lib.optionalString (!stdenv.hostPlatform.isWindows)
176 # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726)
177 ''
178 # c_rehash is a legacy perl script with the same functionality
179 # as `openssl rehash`
180 # this wrapper script is created to maintain backwards compatibility without
181 # depending on perl
182 makeWrapper $bin/bin/openssl $bin/bin/c_rehash \
183 --add-flags "rehash"
184 '' + ''
185
186 mkdir $dev
187 mv $out/include $dev/
188
189 # remove dependency on Perl at runtime
190 rm -r $etc/etc/ssl/misc
191
192 rmdir $etc/etc/ssl/{certs,private}
193
194 ${lib.optionalString (conf != null) "cat ${conf} > $etc/etc/ssl/openssl.cnf"}
195 '';
196
197 postFixup = lib.optionalString (!stdenv.hostPlatform.isWindows) ''
198 # Check to make sure the main output and the static runtime dependencies
199 # don't depend on perl
200 if grep -r '${buildPackages.perl}' $out $etc; then
201 echo "Found an erroneous dependency on perl ^^^" >&2
202 exit 1
203 fi
204 '';
205
206 passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
207
208 meta = with lib; {
209 homepage = "https://www.openssl.org/";
210 description = "A cryptographic library that implements the SSL and TLS protocols";
211 license = licenses.openssl;
212 pkgConfigModules = [
213 "libcrypto"
214 "libssl"
215 "openssl"
216 ];
217 platforms = platforms.all;
218 } // extraMeta;
219 });
220
221in {
222
223
224 openssl_1_1 = common {
225 version = "1.1.1u";
226 sha256 = "sha256-4vjYS1I+7NBse+diaDA3AwD7zBU4a/UULXJ1j2lj68Y=";
227 patches = [
228 ./1.1/nix-ssl-cert-file.patch
229
230 (if stdenv.hostPlatform.isDarwin
231 then ./use-etc-ssl-certs-darwin.patch
232 else ./use-etc-ssl-certs.patch)
233 ];
234 withDocs = true;
235 extraMeta = {
236 knownVulnerabilities = [
237 "OpenSSL 1.1 is reaching its end of life on 2023/09/11 and cannot be supported through the NixOS 23.05 release cycle. https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/"
238 ];
239 };
240 };
241
242 openssl_3 = common {
243 version = "3.0.8";
244 sha256 = "sha256-bBPSvzj98x6sPOKjRwc2c/XWMmM5jx9p0N9KQSU+Sz4=";
245 patches = [
246 ./3.0/nix-ssl-cert-file.patch
247
248 # openssl will only compile in KTLS if the current kernel supports it.
249 # This patch disables build-time detection.
250 ./3.0/openssl-disable-kernel-detection.patch
251
252 (if stdenv.hostPlatform.isDarwin
253 then ./use-etc-ssl-certs-darwin.patch
254 else ./use-etc-ssl-certs.patch)
255 ];
256
257 withDocs = true;
258
259 extraMeta = with lib; {
260 license = licenses.asl20;
261 };
262 };
263}