1{
2 lib,
3 stdenv,
4 fetchurl,
5 buildPackages,
6 perl,
7 coreutils,
8 writeShellScript,
9 makeBinaryWrapper,
10 withCryptodev ? false,
11 cryptodev,
12 withZlib ? false,
13 zlib,
14 enableSSL2 ? false,
15 enableSSL3 ? false,
16 enableMD2 ? false,
17 enableKTLS ? stdenv.hostPlatform.isLinux,
18 # change this to a value between 0 and 5 (as of OpenSSL 3.5)
19 # if null, default is used, changes the permitted algorithms
20 # and key lengths in the default config
21 # see: https://docs.openssl.org/3.5/man3/SSL_CTX_set_security_level/
22 securityLevel ? null,
23 static ? stdenv.hostPlatform.isStatic,
24 # path to openssl.cnf file. will be placed in $etc/etc/ssl/openssl.cnf to replace the default
25 conf ? null,
26 removeReferencesTo,
27 testers,
28}:
29
30# Note: this package is used for bootstrapping fetchurl, and thus
31# cannot use fetchpatch! All mutable patches (generated by GitHub or
32# cgit) that are needed here should be included directly in Nixpkgs as
33# files.
34
35# check from time to time, if this range is still correct
36assert (securityLevel == null) || (securityLevel >= 0 && securityLevel <= 5);
37
38let
39 common =
40 {
41 version,
42 hash,
43 patches ? [ ],
44 withDocs ? false,
45 extraMeta ? { },
46 }:
47 stdenv.mkDerivation (finalAttrs: {
48 pname = "openssl";
49 inherit version;
50
51 src = fetchurl {
52 url =
53 if lib.versionOlder version "3.0" then
54 let
55 versionFixed = builtins.replaceStrings [ "." ] [ "_" ] version;
56 in
57 "https://github.com/openssl/openssl/releases/download/OpenSSL_${versionFixed}/openssl-${version}.tar.gz"
58 else
59 "https://github.com/openssl/openssl/releases/download/openssl-${version}/openssl-${version}.tar.gz";
60 inherit hash;
61 };
62
63 inherit patches;
64
65 postPatch = ''
66 patchShebangs Configure
67 ''
68 + lib.optionalString (lib.versionOlder version "1.1.1") ''
69 patchShebangs test/*
70 for a in test/t* ; do
71 substituteInPlace "$a" \
72 --replace /bin/rm rm
73 done
74 ''
75 # config is a configure script which is not installed.
76 + lib.optionalString (lib.versionAtLeast version "1.1.1") ''
77 substituteInPlace config --replace '/usr/bin/env' '${buildPackages.coreutils}/bin/env'
78 ''
79 + lib.optionalString (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isMusl) ''
80 substituteInPlace crypto/async/arch/async_posix.h \
81 --replace '!defined(__ANDROID__) && !defined(__OpenBSD__)' \
82 '!defined(__ANDROID__) && !defined(__OpenBSD__) && 0'
83 ''
84 # Move ENGINESDIR into OPENSSLDIR for static builds, in order to move
85 # it to the separate etc output.
86 + lib.optionalString static ''
87 substituteInPlace Configurations/unix-Makefile.tmpl \
88 --replace 'ENGINESDIR=$(libdir)/engines-{- $sover_dirname -}' \
89 'ENGINESDIR=$(OPENSSLDIR)/engines-{- $sover_dirname -}'
90 '';
91
92 outputs = [
93 "bin"
94 "dev"
95 "out"
96 "man"
97 ]
98 ++ lib.optional withDocs "doc"
99 # Separate output for the runtime dependencies of the static build.
100 # Specifically, move OPENSSLDIR into this output, as its path will be
101 # compiled into 'libcrypto.a'. This makes it a runtime dependency of
102 # any package that statically links openssl, so we want to keep that
103 # output minimal.
104 ++ lib.optional static "etc";
105 setOutputFlags = false;
106 separateDebugInfo =
107 !stdenv.hostPlatform.isDarwin
108 && !stdenv.hostPlatform.isAndroid
109 && !(stdenv.hostPlatform.useLLVM or false)
110 && stdenv.cc.isGNU;
111
112 nativeBuildInputs =
113 lib.optional (!stdenv.hostPlatform.isWindows) makeBinaryWrapper
114 ++ [ perl ]
115 ++ lib.optionals static [ removeReferencesTo ];
116 buildInputs = lib.optional withCryptodev cryptodev ++ lib.optional withZlib zlib;
117
118 # TODO(@Ericson2314): Improve with mass rebuild
119 configurePlatforms = [ ];
120 configureScript =
121 {
122 armv5tel-linux = "./Configure linux-armv4 -march=armv5te";
123 armv6l-linux = "./Configure linux-armv4 -march=armv6";
124 armv7l-linux = "./Configure linux-armv4 -march=armv7-a";
125 x86_64-darwin = "./Configure darwin64-x86_64-cc";
126 aarch64-darwin = "./Configure darwin64-arm64-cc";
127 x86_64-linux = "./Configure linux-x86_64";
128 x86_64-solaris = "./Configure solaris64-x86_64-gcc";
129 powerpc64-linux = "./Configure linux-ppc64";
130 riscv32-linux = "./Configure ${
131 if lib.versionAtLeast version "3.2" then "linux32-riscv32" else "linux-latomic"
132 }";
133 riscv64-linux = "./Configure linux64-riscv64";
134 }
135 .${stdenv.hostPlatform.system} or (
136 if stdenv.hostPlatform == stdenv.buildPlatform then
137 "./config"
138 else if stdenv.hostPlatform.isBSD then
139 if stdenv.hostPlatform.isx86_64 then
140 "./Configure BSD-x86_64"
141 else if stdenv.hostPlatform.isx86_32 then
142 "./Configure BSD-x86" + lib.optionalString stdenv.hostPlatform.isElf "-elf"
143 else
144 "./Configure BSD-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
145 else if stdenv.hostPlatform.isMinGW then
146 "./Configure mingw${
147 lib.optionalString (stdenv.hostPlatform.parsed.cpu.bits != 32) (
148 toString stdenv.hostPlatform.parsed.cpu.bits
149 )
150 }"
151 else if stdenv.hostPlatform.isLinux then
152 if stdenv.hostPlatform.isx86_64 then
153 "./Configure linux-x86_64"
154 else if stdenv.hostPlatform.isMicroBlaze then
155 "./Configure linux-latomic"
156 else if stdenv.hostPlatform.isMips32 then
157 "./Configure linux-mips32"
158 else if stdenv.hostPlatform.isMips64n32 then
159 "./Configure linux-mips64"
160 else if stdenv.hostPlatform.isMips64n64 then
161 "./Configure linux64-mips64"
162 else
163 "./Configure linux-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
164 else if stdenv.hostPlatform.isiOS then
165 "./Configure ios${toString stdenv.hostPlatform.parsed.cpu.bits}-cross"
166 else
167 throw "Not sure what configuration to use for ${stdenv.hostPlatform.config}"
168 );
169
170 # OpenSSL doesn't like the `--enable-static` / `--disable-shared` flags.
171 dontAddStaticConfigureFlags = true;
172 configureFlags = [
173 "shared" # "shared" builds both shared and static libraries
174 "--libdir=lib"
175 (
176 if !static then
177 "--openssldir=etc/ssl"
178 else
179 # Move OPENSSLDIR to the 'etc' output for static builds. Prepend '/.'
180 # to the path to make it appear absolute before variable expansion,
181 # else the 'prefix' would be prepended to it.
182 "--openssldir=/.$(etc)/etc/ssl"
183 )
184 ]
185 ++ lib.optionals withCryptodev [
186 "-DHAVE_CRYPTODEV"
187 "-DUSE_CRYPTODEV_DIGESTS"
188 ]
189 # enable optimized EC curve primitives on x86_64,
190 # can provide a 2x up to 4x speedup at best
191 # with combined PQC and conventional crypto handshakes
192 # starting with 3.5 its nice to speed things up for free
193 ++ lib.optional stdenv.hostPlatform.isx86_64 "enable-ec_nistp_64_gcc_128"
194 # useful to set e.g. 256 bit security level with setting this to 5
195 ++ lib.optional (
196 securityLevel != null
197 ) "-DOPENSSL_TLS_SECURITY_LEVEL=${builtins.toString securityLevel}"
198 ++ lib.optional enableMD2 "enable-md2"
199 ++ lib.optional enableSSL2 "enable-ssl2"
200 ++ lib.optional enableSSL3 "enable-ssl3"
201 # We select KTLS here instead of the configure-time detection (which we patch out).
202 # KTLS should work on FreeBSD 13+ as well, so we could enable it if someone tests it.
203 ++ lib.optional (lib.versionAtLeast version "3.0.0" && enableKTLS) "enable-ktls"
204 ++ lib.optional (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isAarch64) "no-afalgeng"
205 # OpenSSL needs a specific `no-shared` configure flag.
206 # See https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options
207 # for a comprehensive list of configuration options.
208 ++ lib.optional (lib.versionAtLeast version "1.1.1" && static) "no-shared"
209 ++ lib.optional (lib.versionAtLeast version "3.0.0" && static) "no-module"
210 # This introduces a reference to the CTLOG_FILE which is undesired when
211 # trying to build binaries statically.
212 ++ lib.optional static "no-ct"
213 ++ lib.optional withZlib "zlib"
214 # /dev/crypto support has been dropped in OpenBSD 5.7.
215 #
216 # OpenBSD's ports does this too,
217 # https://github.com/openbsd/ports/blob/a1147500c76970fea22947648fb92a093a529d7c/security/openssl/3.3/Makefile#L25.
218 #
219 # https://github.com/openssl/openssl/pull/10565 indicated the
220 # intent was that this would be configured properly automatically,
221 # but that doesn't appear to be the case.
222 ++ lib.optional stdenv.hostPlatform.isOpenBSD "no-devcryptoeng"
223 ++ lib.optionals (stdenv.hostPlatform.isMips && stdenv.hostPlatform ? gcc.arch) [
224 # This is necessary in order to avoid openssl adding -march
225 # flags which ultimately conflict with those added by
226 # cc-wrapper. Openssl assumes that it can scan CFLAGS to
227 # detect any -march flags, using this perl code:
228 #
229 # && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})
230 #
231 # The following bogus CFLAGS environment variable triggers the
232 # the code above, inhibiting `./Configure` from adding the
233 # conflicting flags.
234 "CFLAGS=-march=${stdenv.hostPlatform.gcc.arch}"
235 ];
236
237 makeFlags = [
238 "MANDIR=$(man)/share/man"
239 # This avoids conflicts between man pages of openssl subcommands (for
240 # example 'ts' and 'err') man pages and their equivalent top-level
241 # command in other packages (respectively man-pages and moreutils).
242 # This is done in ubuntu and archlinux, and possibly many other distros.
243 "MANSUFFIX=ssl"
244 ];
245
246 enableParallelBuilding = true;
247
248 postInstall =
249 (
250 if static then
251 ''
252 # OPENSSLDIR has a reference to self
253 remove-references-to -t $out $out/lib/*.a
254 ''
255 else
256 ''
257 # If we're building dynamic libraries, then don't install static
258 # libraries.
259 if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then
260 rm "$out/lib/"*.a
261 fi
262
263 # 'etc' is a separate output on static builds only.
264 etc=$out
265 ''
266 )
267 + ''
268 mkdir -p $bin
269 mv $out/bin $bin/bin
270
271 ''
272 +
273 lib.optionalString (!stdenv.hostPlatform.isWindows)
274 # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726)
275 ''
276 # c_rehash is a legacy perl script with the same functionality
277 # as `openssl rehash`
278 # this wrapper script is created to maintain backwards compatibility without
279 # depending on perl
280 makeWrapper $bin/bin/openssl $bin/bin/c_rehash \
281 --add-flags "rehash"
282 ''
283 + ''
284
285 mkdir $dev
286 mv $out/include $dev/
287
288 # remove dependency on Perl at runtime
289 rm -r $etc/etc/ssl/misc
290
291 rmdir $etc/etc/ssl/{certs,private}
292 ''
293 + lib.optionalString (conf != null) ''
294 cat ${conf} > $etc/etc/ssl/openssl.cnf
295 '';
296
297 postFixup =
298 lib.optionalString (!stdenv.hostPlatform.isWindows) ''
299 # Check to make sure the main output and the static runtime dependencies
300 # don't depend on perl
301 if grep -r '${buildPackages.perl}' $out $etc; then
302 echo "Found an erroneous dependency on perl ^^^" >&2
303 exit 1
304 fi
305 ''
306 + lib.optionalString (lib.versionAtLeast version "3.3.0") ''
307 # cleanup cmake helpers for now (for OpenSSL >= 3.3), only rely on pkg-config.
308 # pkg-config gets its paths fixed correctly
309 rm -rf $dev/lib/cmake
310 '';
311
312 passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
313
314 meta = {
315 homepage = "https://www.openssl.org/";
316 changelog = "https://github.com/openssl/openssl/blob/openssl-${version}/CHANGES.md";
317 description = "Cryptographic library that implements the SSL and TLS protocols";
318 license = lib.licenses.openssl;
319 mainProgram = "openssl";
320 maintainers = with lib.maintainers; [ thillux ];
321 teams = [ lib.teams.stridtech ];
322 pkgConfigModules = [
323 "libcrypto"
324 "libssl"
325 "openssl"
326 ];
327 platforms = lib.platforms.all;
328 }
329 // extraMeta;
330 });
331
332in
333{
334 # intended version "policy":
335 # - 1.1 as long as some package exists, which does not build without it
336 # (tracking issue: https://github.com/NixOS/nixpkgs/issues/269713)
337 # try to remove in 24.05 for the first time, if possible then
338 # - latest 3.x LTS
339 # - latest 3.x non-LTS as preview/for development
340 #
341 # - other versions in between only when reasonable need is stated for some package
342 # - backport every security critical fix release e.g. 3.0.y -> 3.0.y+1 but no new version, e.g. 3.1 -> 3.2
343
344 # If you do upgrade here, please update in pkgs/top-level/release.nix
345 # the permitted insecure version to ensure it gets cached for our users
346 # and backport this to stable release (at time of writing this 23.11).
347 openssl_1_1 = common {
348 version = "1.1.1w";
349 hash = "sha256-zzCYlQy02FOtlcCEHx+cbT3BAtzPys1SHZOSUgi3asg=";
350 patches = [
351 ./1.1/nix-ssl-cert-file.patch
352
353 (
354 if stdenv.hostPlatform.isDarwin then ./use-etc-ssl-certs-darwin.patch else ./use-etc-ssl-certs.patch
355 )
356 ];
357 withDocs = true;
358 extraMeta = {
359 knownVulnerabilities = [
360 "OpenSSL 1.1 is reaching its end of life on 2023/09/11 and cannot be supported through the NixOS 23.11 release cycle. https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/"
361 ];
362 };
363 };
364
365 openssl_3 = common {
366 version = "3.0.17";
367 hash = "sha256-39135OobV/86bb3msL3D8x21rJnn/dTq+eH7tuwtuM4=";
368
369 patches = [
370 ./3.0/nix-ssl-cert-file.patch
371
372 # openssl will only compile in KTLS if the current kernel supports it.
373 # This patch disables build-time detection.
374 ./3.0/openssl-disable-kernel-detection.patch
375
376 (
377 if stdenv.hostPlatform.isDarwin then ./use-etc-ssl-certs-darwin.patch else ./use-etc-ssl-certs.patch
378 )
379 ];
380
381 withDocs = true;
382
383 extraMeta = {
384 license = lib.licenses.asl20;
385 };
386 };
387
388 openssl_3_5 = common {
389 version = "3.5.1";
390 hash = "sha256-UpBDsVz/pfNgd6TQr4Pz3jmYBxgdYHRB1zQZbYibZB8=";
391
392 patches = [
393 ./3.0/nix-ssl-cert-file.patch
394
395 # openssl will only compile in KTLS if the current kernel supports it.
396 # This patch disables build-time detection.
397 ./3.0/openssl-disable-kernel-detection.patch
398
399 (
400 if stdenv.hostPlatform.isDarwin then
401 ./3.5/use-etc-ssl-certs-darwin.patch
402 else
403 ./3.5/use-etc-ssl-certs.patch
404 )
405 ];
406
407 withDocs = true;
408
409 extraMeta = {
410 license = lib.licenses.asl20;
411 };
412 };
413}