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 powerpc-linux = "./Configure linux-ppc";
130 powerpc64-linux = "./Configure linux-ppc64";
131 riscv32-linux = "./Configure ${
132 if lib.versionAtLeast version "3.2" then "linux32-riscv32" else "linux-latomic"
133 }";
134 riscv64-linux = "./Configure linux64-riscv64";
135 }
136 .${stdenv.hostPlatform.system} or (
137 if stdenv.hostPlatform == stdenv.buildPlatform then
138 "./config"
139 else if stdenv.hostPlatform.isBSD then
140 if stdenv.hostPlatform.isx86_64 then
141 "./Configure BSD-x86_64"
142 else if stdenv.hostPlatform.isx86_32 then
143 "./Configure BSD-x86" + lib.optionalString stdenv.hostPlatform.isElf "-elf"
144 else
145 "./Configure BSD-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
146 else if stdenv.hostPlatform.isMinGW then
147 "./Configure mingw${
148 lib.optionalString (stdenv.hostPlatform.parsed.cpu.bits != 32) (
149 toString stdenv.hostPlatform.parsed.cpu.bits
150 )
151 }"
152 else if stdenv.hostPlatform.isLinux then
153 if stdenv.hostPlatform.isx86_64 then
154 "./Configure linux-x86_64"
155 else if stdenv.hostPlatform.isMicroBlaze then
156 "./Configure linux-latomic"
157 else if stdenv.hostPlatform.isMips32 then
158 "./Configure linux-mips32"
159 else if stdenv.hostPlatform.isMips64n32 then
160 "./Configure linux-mips64"
161 else if stdenv.hostPlatform.isMips64n64 then
162 "./Configure linux64-mips64"
163 else
164 "./Configure linux-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
165 else if stdenv.hostPlatform.isiOS then
166 "./Configure ios${toString stdenv.hostPlatform.parsed.cpu.bits}-cross"
167 else
168 throw "Not sure what configuration to use for ${stdenv.hostPlatform.config}"
169 );
170
171 # OpenSSL doesn't like the `--enable-static` / `--disable-shared` flags.
172 dontAddStaticConfigureFlags = true;
173 configureFlags = [
174 "shared" # "shared" builds both shared and static libraries
175 "--libdir=lib"
176 (
177 if !static then
178 "--openssldir=etc/ssl"
179 else
180 # Move OPENSSLDIR to the 'etc' output for static builds. Prepend '/.'
181 # to the path to make it appear absolute before variable expansion,
182 # else the 'prefix' would be prepended to it.
183 "--openssldir=/.$(etc)/etc/ssl"
184 )
185 ]
186 ++ lib.optionals withCryptodev [
187 "-DHAVE_CRYPTODEV"
188 "-DUSE_CRYPTODEV_DIGESTS"
189 ]
190 # enable optimized EC curve primitives on x86_64,
191 # can provide a 2x up to 4x speedup at best
192 # with combined PQC and conventional crypto handshakes
193 # starting with 3.5 its nice to speed things up for free
194 ++ lib.optional stdenv.hostPlatform.isx86_64 "enable-ec_nistp_64_gcc_128"
195 # useful to set e.g. 256 bit security level with setting this to 5
196 ++ lib.optional (
197 securityLevel != null
198 ) "-DOPENSSL_TLS_SECURITY_LEVEL=${builtins.toString securityLevel}"
199 ++ lib.optional enableMD2 "enable-md2"
200 ++ lib.optional enableSSL2 "enable-ssl2"
201 ++ lib.optional enableSSL3 "enable-ssl3"
202 # We select KTLS here instead of the configure-time detection (which we patch out).
203 # KTLS should work on FreeBSD 13+ as well, so we could enable it if someone tests it.
204 ++ lib.optional (lib.versionAtLeast version "3.0.0" && enableKTLS) "enable-ktls"
205 ++ lib.optional (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isAarch64) "no-afalgeng"
206 # OpenSSL needs a specific `no-shared` configure flag.
207 # See https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options
208 # for a comprehensive list of configuration options.
209 ++ lib.optional (lib.versionAtLeast version "1.1.1" && static) "no-shared"
210 ++ lib.optional (lib.versionAtLeast version "3.0.0" && static) "no-module"
211 # This introduces a reference to the CTLOG_FILE which is undesired when
212 # trying to build binaries statically.
213 ++ lib.optional static "no-ct"
214 ++ lib.optional withZlib "zlib"
215 # /dev/crypto support has been dropped in OpenBSD 5.7.
216 #
217 # OpenBSD's ports does this too,
218 # https://github.com/openbsd/ports/blob/a1147500c76970fea22947648fb92a093a529d7c/security/openssl/3.3/Makefile#L25.
219 #
220 # https://github.com/openssl/openssl/pull/10565 indicated the
221 # intent was that this would be configured properly automatically,
222 # but that doesn't appear to be the case.
223 ++ lib.optional stdenv.hostPlatform.isOpenBSD "no-devcryptoeng"
224 ++ lib.optionals (stdenv.hostPlatform.isMips && stdenv.hostPlatform ? gcc.arch) [
225 # This is necessary in order to avoid openssl adding -march
226 # flags which ultimately conflict with those added by
227 # cc-wrapper. Openssl assumes that it can scan CFLAGS to
228 # detect any -march flags, using this perl code:
229 #
230 # && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})
231 #
232 # The following bogus CFLAGS environment variable triggers the
233 # the code above, inhibiting `./Configure` from adding the
234 # conflicting flags.
235 "CFLAGS=-march=${stdenv.hostPlatform.gcc.arch}"
236 ];
237
238 makeFlags = [
239 "MANDIR=$(man)/share/man"
240 # This avoids conflicts between man pages of openssl subcommands (for
241 # example 'ts' and 'err') man pages and their equivalent top-level
242 # command in other packages (respectively man-pages and moreutils).
243 # This is done in ubuntu and archlinux, and possibly many other distros.
244 "MANSUFFIX=ssl"
245 ];
246
247 enableParallelBuilding = true;
248
249 postInstall =
250 (
251 if static then
252 ''
253 # OPENSSLDIR has a reference to self
254 remove-references-to -t $out $out/lib/*.a
255 ''
256 else
257 ''
258 # If we're building dynamic libraries, then don't install static
259 # libraries.
260 if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then
261 rm "$out/lib/"*.a
262 fi
263
264 # 'etc' is a separate output on static builds only.
265 etc=$out
266 ''
267 )
268 + ''
269 mkdir -p $bin
270 mv $out/bin $bin/bin
271
272 ''
273 +
274 lib.optionalString (!stdenv.hostPlatform.isWindows)
275 # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726)
276 ''
277 # c_rehash is a legacy perl script with the same functionality
278 # as `openssl rehash`
279 # this wrapper script is created to maintain backwards compatibility without
280 # depending on perl
281 makeWrapper $bin/bin/openssl $bin/bin/c_rehash \
282 --add-flags "rehash"
283 ''
284 + ''
285
286 mkdir $dev
287 mv $out/include $dev/
288
289 # remove dependency on Perl at runtime
290 rm -r $etc/etc/ssl/misc
291
292 rmdir $etc/etc/ssl/{certs,private}
293 ''
294 + lib.optionalString (conf != null) ''
295 cat ${conf} > $etc/etc/ssl/openssl.cnf
296 '';
297
298 allowedImpureDLLs = [ "CRYPT32.dll" ];
299
300 postFixup =
301 lib.optionalString (!stdenv.hostPlatform.isWindows) ''
302 # Check to make sure the main output and the static runtime dependencies
303 # don't depend on perl
304 if grep -r '${buildPackages.perl}' $out $etc; then
305 echo "Found an erroneous dependency on perl ^^^" >&2
306 exit 1
307 fi
308 ''
309 + lib.optionalString (lib.versionAtLeast version "3.3.0") ''
310 # cleanup cmake helpers for now (for OpenSSL >= 3.3), only rely on pkg-config.
311 # pkg-config gets its paths fixed correctly
312 rm -rf $dev/lib/cmake
313 '';
314
315 passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
316
317 meta = {
318 homepage = "https://www.openssl.org/";
319 changelog = "https://github.com/openssl/openssl/blob/openssl-${version}/CHANGES.md";
320 description = "Cryptographic library that implements the SSL and TLS protocols";
321 license = lib.licenses.openssl;
322 mainProgram = "openssl";
323 maintainers = with lib.maintainers; [ thillux ];
324 teams = [ lib.teams.stridtech ];
325 pkgConfigModules = [
326 "libcrypto"
327 "libssl"
328 "openssl"
329 ];
330 platforms = lib.platforms.all;
331 }
332 // extraMeta;
333 });
334
335in
336{
337 # intended version "policy":
338 # - 1.1 as long as some package exists, which does not build without it
339 # (tracking issue: https://github.com/NixOS/nixpkgs/issues/269713)
340 # try to remove in 24.05 for the first time, if possible then
341 # - latest 3.x LTS
342 # - latest 3.x non-LTS as preview/for development
343 #
344 # - other versions in between only when reasonable need is stated for some package
345 # - 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
346
347 # If you do upgrade here, please update in pkgs/top-level/release.nix
348 # the permitted insecure version to ensure it gets cached for our users
349 # and backport this to stable release (at time of writing this 23.11).
350 openssl_1_1 = common {
351 version = "1.1.1w";
352 hash = "sha256-zzCYlQy02FOtlcCEHx+cbT3BAtzPys1SHZOSUgi3asg=";
353 patches = [
354 ./1.1/nix-ssl-cert-file.patch
355
356 (
357 if stdenv.hostPlatform.isDarwin then ./use-etc-ssl-certs-darwin.patch else ./use-etc-ssl-certs.patch
358 )
359 ];
360 withDocs = true;
361 extraMeta = {
362 knownVulnerabilities = [
363 "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/"
364 ];
365 };
366 };
367
368 openssl_3 = common {
369 version = "3.0.17";
370 hash = "sha256-39135OobV/86bb3msL3D8x21rJnn/dTq+eH7tuwtuM4=";
371
372 patches = [
373 ./3.0/nix-ssl-cert-file.patch
374
375 # openssl will only compile in KTLS if the current kernel supports it.
376 # This patch disables build-time detection.
377 ./3.0/openssl-disable-kernel-detection.patch
378
379 (
380 if stdenv.hostPlatform.isDarwin then ./use-etc-ssl-certs-darwin.patch else ./use-etc-ssl-certs.patch
381 )
382 ];
383
384 withDocs = true;
385
386 extraMeta = {
387 license = lib.licenses.asl20;
388 };
389 };
390
391 openssl_3_5 = common {
392 version = "3.5.1";
393 hash = "sha256-UpBDsVz/pfNgd6TQr4Pz3jmYBxgdYHRB1zQZbYibZB8=";
394
395 patches = [
396 ./3.0/nix-ssl-cert-file.patch
397
398 # openssl will only compile in KTLS if the current kernel supports it.
399 # This patch disables build-time detection.
400 ./3.0/openssl-disable-kernel-detection.patch
401
402 (
403 if stdenv.hostPlatform.isDarwin then
404 ./3.5/use-etc-ssl-certs-darwin.patch
405 else
406 ./3.5/use-etc-ssl-certs.patch
407 )
408 ];
409
410 withDocs = true;
411
412 extraMeta = {
413 license = lib.licenses.asl20;
414 };
415 };
416}