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, hash, 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 hash;
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 ++ lib.optionals (stdenv.hostPlatform.isMips && stdenv.hostPlatform ? gcc.arch) [
146 # This is necessary in order to avoid openssl adding -march
147 # flags which ultimately conflict with those added by
148 # cc-wrapper. Openssl assumes that it can scan CFLAGS to
149 # detect any -march flags, using this perl code:
150 #
151 # && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})
152 #
153 # The following bogus CFLAGS environment variable triggers the
154 # the code above, inhibiting `./Configure` from adding the
155 # conflicting flags.
156 "CFLAGS=-march=${stdenv.hostPlatform.gcc.arch}"
157 ];
158
159 makeFlags = [
160 "MANDIR=$(man)/share/man"
161 # This avoids conflicts between man pages of openssl subcommands (for
162 # example 'ts' and 'err') man pages and their equivalent top-level
163 # command in other packages (respectively man-pages and moreutils).
164 # This is done in ubuntu and archlinux, and possiibly many other distros.
165 "MANSUFFIX=ssl"
166 ];
167
168 enableParallelBuilding = true;
169
170 postInstall =
171 (if static then ''
172 # OPENSSLDIR has a reference to self
173 remove-references-to -t $out $out/lib/*.a
174 '' else ''
175 # If we're building dynamic libraries, then don't install static
176 # libraries.
177 if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then
178 rm "$out/lib/"*.a
179 fi
180
181 # 'etc' is a separate output on static builds only.
182 etc=$out
183 '') + ''
184 mkdir -p $bin
185 mv $out/bin $bin/bin
186
187 '' + lib.optionalString (!stdenv.hostPlatform.isWindows)
188 # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726)
189 ''
190 # c_rehash is a legacy perl script with the same functionality
191 # as `openssl rehash`
192 # this wrapper script is created to maintain backwards compatibility without
193 # depending on perl
194 makeWrapper $bin/bin/openssl $bin/bin/c_rehash \
195 --add-flags "rehash"
196 '' + ''
197
198 mkdir $dev
199 mv $out/include $dev/
200
201 # remove dependency on Perl at runtime
202 rm -r $etc/etc/ssl/misc
203
204 rmdir $etc/etc/ssl/{certs,private}
205
206 ${lib.optionalString (conf != null) "cat ${conf} > $etc/etc/ssl/openssl.cnf"}
207 '';
208
209 postFixup = lib.optionalString (!stdenv.hostPlatform.isWindows) ''
210 # Check to make sure the main output and the static runtime dependencies
211 # don't depend on perl
212 if grep -r '${buildPackages.perl}' $out $etc; then
213 echo "Found an erroneous dependency on perl ^^^" >&2
214 exit 1
215 fi
216 '';
217
218 passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
219
220 meta = with lib; {
221 homepage = "https://www.openssl.org/";
222 changelog = "https://github.com/openssl/openssl/blob/openssl-${version}/CHANGES.md";
223 description = "A cryptographic library that implements the SSL and TLS protocols";
224 license = licenses.openssl;
225 mainProgram = "openssl";
226 maintainers = with maintainers; [ thillux ];
227 pkgConfigModules = [
228 "libcrypto"
229 "libssl"
230 "openssl"
231 ];
232 platforms = platforms.all;
233 } // extraMeta;
234 });
235
236in {
237
238 # If you do upgrade here, please update in pkgs/top-level/release.nix
239 # the permitted insecure version to ensure it gets cached for our users
240 # and backport this to stable release (23.05).
241 openssl_1_1 = common {
242 version = "1.1.1w";
243 hash = "sha256-zzCYlQy02FOtlcCEHx+cbT3BAtzPys1SHZOSUgi3asg=";
244 patches = [
245 ./1.1/nix-ssl-cert-file.patch
246
247 (if stdenv.hostPlatform.isDarwin
248 then ./use-etc-ssl-certs-darwin.patch
249 else ./use-etc-ssl-certs.patch)
250 ];
251 withDocs = true;
252 extraMeta = {
253 knownVulnerabilities = [
254 "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/"
255 ];
256 };
257 };
258
259 openssl_3 = common {
260 version = "3.0.12";
261 hash = "sha256-+Tyejt3l6RZhGd4xdV/Ie0qjSGNmL2fd/LoU0La2m2E=";
262
263 patches = [
264 ./3.0/nix-ssl-cert-file.patch
265
266 # openssl will only compile in KTLS if the current kernel supports it.
267 # This patch disables build-time detection.
268 ./3.0/openssl-disable-kernel-detection.patch
269
270 (if stdenv.hostPlatform.isDarwin
271 then ./use-etc-ssl-certs-darwin.patch
272 else ./use-etc-ssl-certs.patch)
273 ];
274
275 withDocs = true;
276
277 extraMeta = with lib; {
278 license = licenses.asl20;
279 };
280 };
281
282 openssl_3_1 = common {
283 version = "3.1.4";
284 hash = "sha256-hAr1Nmq5tSK95SWCa+PvD7Cvgcap69hMqmAP6hcx7uM=";
285
286 patches = [
287 ./3.0/nix-ssl-cert-file.patch
288
289 # openssl will only compile in KTLS if the current kernel supports it.
290 # This patch disables build-time detection.
291 ./3.0/openssl-disable-kernel-detection.patch
292
293 (if stdenv.hostPlatform.isDarwin
294 then ./use-etc-ssl-certs-darwin.patch
295 else ./use-etc-ssl-certs.patch)
296 ];
297
298 withDocs = true;
299
300 extraMeta = with lib; {
301 license = licenses.asl20;
302 };
303 };
304}