about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/libraries/openssl/default.nix
blob: 7af5085410f76630179f196e6a1824b31e304ed5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
{ lib, stdenv, fetchurl, buildPackages, perl, coreutils, writeShellScript
, makeWrapper
, withCryptodev ? false, cryptodev
, withZlib ? false, zlib
, enableSSL2 ? false
, enableSSL3 ? false
, enableKTLS ? stdenv.isLinux
, static ? stdenv.hostPlatform.isStatic
# path to openssl.cnf file. will be placed in $etc/etc/ssl/openssl.cnf to replace the default
, conf ? null
, removeReferencesTo
, testers
}:

# Note: this package is used for bootstrapping fetchurl, and thus
# cannot use fetchpatch! All mutable patches (generated by GitHub or
# cgit) that are needed here should be included directly in Nixpkgs as
# files.

let
  common = { version, hash, patches ? [], withDocs ? false, extraMeta ? {} }:
   stdenv.mkDerivation (finalAttrs: {
    pname = "openssl";
    inherit version;

    src = fetchurl {
      url = "https://www.openssl.org/source/${finalAttrs.pname}-${version}.tar.gz";
      inherit hash;
    };

    inherit patches;

    postPatch = ''
      patchShebangs Configure
    '' + lib.optionalString (lib.versionOlder version "1.1.1") ''
      patchShebangs test/*
      for a in test/t* ; do
        substituteInPlace "$a" \
          --replace /bin/rm rm
      done
    ''
    # config is a configure script which is not installed.
    + lib.optionalString (lib.versionAtLeast version "1.1.1") ''
      substituteInPlace config --replace '/usr/bin/env' '${buildPackages.coreutils}/bin/env'
    '' + lib.optionalString (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isMusl) ''
      substituteInPlace crypto/async/arch/async_posix.h \
        --replace '!defined(__ANDROID__) && !defined(__OpenBSD__)' \
                  '!defined(__ANDROID__) && !defined(__OpenBSD__) && 0'
    ''
    # Move ENGINESDIR into OPENSSLDIR for static builds, in order to move
    # it to the separate etc output.
    + lib.optionalString static ''
      substituteInPlace Configurations/unix-Makefile.tmpl \
        --replace 'ENGINESDIR=$(libdir)/engines-{- $sover_dirname -}' \
                  'ENGINESDIR=$(OPENSSLDIR)/engines-{- $sover_dirname -}'
    '';

    outputs = [ "bin" "dev" "out" "man" ]
      ++ lib.optional withDocs "doc"
      # Separate output for the runtime dependencies of the static build.
      # Specifically, move OPENSSLDIR into this output, as its path will be
      # compiled into 'libcrypto.a'. This makes it a runtime dependency of
      # any package that statically links openssl, so we want to keep that
      # output minimal.
      ++ lib.optional static "etc";
    setOutputFlags = false;
    separateDebugInfo =
      !stdenv.hostPlatform.isDarwin &&
      !(stdenv.hostPlatform.useLLVM or false) &&
      stdenv.cc.isGNU;

    nativeBuildInputs =
         lib.optional (!stdenv.hostPlatform.isWindows) makeWrapper
      ++ [ perl ]
      ++ lib.optionals static [ removeReferencesTo ];
    buildInputs = lib.optional withCryptodev cryptodev
      ++ lib.optional withZlib zlib;

    # TODO(@Ericson2314): Improve with mass rebuild
    configurePlatforms = [];
    configureScript = {
        armv5tel-linux = "./Configure linux-armv4 -march=armv5te";
        armv6l-linux = "./Configure linux-armv4 -march=armv6";
        armv7l-linux = "./Configure linux-armv4 -march=armv7-a";
        x86_64-darwin  = "./Configure darwin64-x86_64-cc";
        aarch64-darwin = "./Configure darwin64-arm64-cc";
        x86_64-linux = "./Configure linux-x86_64";
        x86_64-solaris = "./Configure solaris64-x86_64-gcc";
        riscv64-linux = "./Configure linux64-riscv64";
      }.${stdenv.hostPlatform.system} or (
        if stdenv.hostPlatform == stdenv.buildPlatform
          then "./config"
        else if stdenv.hostPlatform.isBSD
          then if stdenv.hostPlatform.isx86_64 then "./Configure BSD-x86_64"
          else if stdenv.hostPlatform.isx86_32
            then "./Configure BSD-x86" + lib.optionalString stdenv.hostPlatform.isElf "-elf"
          else "./Configure BSD-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
        else if stdenv.hostPlatform.isMinGW
          then "./Configure mingw${lib.optionalString
                                     (stdenv.hostPlatform.parsed.cpu.bits != 32)
                                     (toString stdenv.hostPlatform.parsed.cpu.bits)}"
        else if stdenv.hostPlatform.isLinux
          then if stdenv.hostPlatform.isx86_64 then "./Configure linux-x86_64"
          else if stdenv.hostPlatform.isMips32 then "./Configure linux-mips32"
          else if stdenv.hostPlatform.isMips64n32 then "./Configure linux-mips64"
          else if stdenv.hostPlatform.isMips64n64 then "./Configure linux64-mips64"
          else "./Configure linux-generic${toString stdenv.hostPlatform.parsed.cpu.bits}"
        else if stdenv.hostPlatform.isiOS
          then "./Configure ios${toString stdenv.hostPlatform.parsed.cpu.bits}-cross"
        else
          throw "Not sure what configuration to use for ${stdenv.hostPlatform.config}"
      );

    # OpenSSL doesn't like the `--enable-static` / `--disable-shared` flags.
    dontAddStaticConfigureFlags = true;
    configureFlags = [
      "shared" # "shared" builds both shared and static libraries
      "--libdir=lib"
      (if !static then
         "--openssldir=etc/ssl"
       else
         # Move OPENSSLDIR to the 'etc' output for static builds. Prepend '/.'
         # to the path to make it appear absolute before variable expansion,
         # else the 'prefix' would be prepended to it.
         "--openssldir=/.$(etc)/etc/ssl"
      )
    ] ++ lib.optionals withCryptodev [
      "-DHAVE_CRYPTODEV"
      "-DUSE_CRYPTODEV_DIGESTS"
    ] ++ lib.optional enableSSL2 "enable-ssl2"
      ++ lib.optional enableSSL3 "enable-ssl3"
      # We select KTLS here instead of the configure-time detection (which we patch out).
      # KTLS should work on FreeBSD 13+ as well, so we could enable it if someone tests it.
      ++ lib.optional (lib.versionAtLeast version "3.0.0" && enableKTLS) "enable-ktls"
      ++ lib.optional (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isAarch64) "no-afalgeng"
      # OpenSSL needs a specific `no-shared` configure flag.
      # See https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options
      # for a comprehensive list of configuration options.
      ++ lib.optional (lib.versionAtLeast version "1.1.1" && static) "no-shared"
      ++ lib.optional (lib.versionAtLeast version "3.0.0" && static) "no-module"
      # This introduces a reference to the CTLOG_FILE which is undesired when
      # trying to build binaries statically.
      ++ lib.optional static "no-ct"
      ++ lib.optional withZlib "zlib"
      ++ lib.optionals (stdenv.hostPlatform.isMips && stdenv.hostPlatform ? gcc.arch) [
      # This is necessary in order to avoid openssl adding -march
      # flags which ultimately conflict with those added by
      # cc-wrapper.  Openssl assumes that it can scan CFLAGS to
      # detect any -march flags, using this perl code:
      #
      #   && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})
      #
      # The following bogus CFLAGS environment variable triggers the
      # the code above, inhibiting `./Configure` from adding the
      # conflicting flags.
      "CFLAGS=-march=${stdenv.hostPlatform.gcc.arch}"
    ];

    makeFlags = [
      "MANDIR=$(man)/share/man"
      # This avoids conflicts between man pages of openssl subcommands (for
      # example 'ts' and 'err') man pages and their equivalent top-level
      # command in other packages (respectively man-pages and moreutils).
      # This is done in ubuntu and archlinux, and possiibly many other distros.
      "MANSUFFIX=ssl"
    ];

    enableParallelBuilding = true;

    postInstall =
    (if static then ''
      # OPENSSLDIR has a reference to self
      remove-references-to -t $out $out/lib/*.a
    '' else ''
      # If we're building dynamic libraries, then don't install static
      # libraries.
      if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then
          rm "$out/lib/"*.a
      fi

      # 'etc' is a separate output on static builds only.
      etc=$out
    '') + ''
      mkdir -p $bin
      mv $out/bin $bin/bin

    '' + lib.optionalString (!stdenv.hostPlatform.isWindows)
      # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726)
    ''
      # c_rehash is a legacy perl script with the same functionality
      # as `openssl rehash`
      # this wrapper script is created to maintain backwards compatibility without
      # depending on perl
      makeWrapper $bin/bin/openssl $bin/bin/c_rehash \
        --add-flags "rehash"
    '' + ''

      mkdir $dev
      mv $out/include $dev/

      # remove dependency on Perl at runtime
      rm -r $etc/etc/ssl/misc

      rmdir $etc/etc/ssl/{certs,private}

      ${lib.optionalString (conf != null) "cat ${conf} > $etc/etc/ssl/openssl.cnf"}
    '';

    postFixup = lib.optionalString (!stdenv.hostPlatform.isWindows) ''
      # Check to make sure the main output and the static runtime dependencies
      # don't depend on perl
      if grep -r '${buildPackages.perl}' $out $etc; then
        echo "Found an erroneous dependency on perl ^^^" >&2
        exit 1
      fi
    '';

    passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;

    meta = with lib; {
      homepage = "https://www.openssl.org/";
      changelog = "https://github.com/openssl/openssl/blob/openssl-${version}/CHANGES.md";
      description = "A cryptographic library that implements the SSL and TLS protocols";
      license = licenses.openssl;
      mainProgram = "openssl";
      maintainers = with maintainers; [ thillux ];
      pkgConfigModules = [
        "libcrypto"
        "libssl"
        "openssl"
      ];
      platforms = platforms.all;
    } // extraMeta;
  });

in {
  # intended version "policy":
  # - 1.1 as long as some package exists, which does not build without it
  # - latest 3.x LTS
  # - latest 3.x non-LTS as preview/for development
  #
  # - other versions in between only when reasonable need is stated for some package
  # - 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

  # If you do upgrade here, please update in pkgs/top-level/release.nix
  # the permitted insecure version to ensure it gets cached for our users
  # and backport this to stable release (23.05).
  openssl_1_1 = common {
    version = "1.1.1w";
    hash = "sha256-zzCYlQy02FOtlcCEHx+cbT3BAtzPys1SHZOSUgi3asg=";
    patches = [
      ./1.1/nix-ssl-cert-file.patch

      (if stdenv.hostPlatform.isDarwin
       then ./use-etc-ssl-certs-darwin.patch
       else ./use-etc-ssl-certs.patch)
    ];
    withDocs = true;
    extraMeta = {
      knownVulnerabilities = [
        "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/"
      ];
    };
  };

  openssl_3 = common {
    version = "3.0.13";
    hash = "sha256-iFJXU/edO+wn0vp8ZqoLkrOqlJja/ZPXz6SzeAza4xM=";

    patches = [
      ./3.0/nix-ssl-cert-file.patch

      # openssl will only compile in KTLS if the current kernel supports it.
      # This patch disables build-time detection.
      ./3.0/openssl-disable-kernel-detection.patch

      (if stdenv.hostPlatform.isDarwin
       then ./use-etc-ssl-certs-darwin.patch
       else ./use-etc-ssl-certs.patch)
    ];

    withDocs = true;

    extraMeta = with lib; {
      license = licenses.asl20;
    };
  };

  openssl_3_2 = common {
    version = "3.2.1";
    hash = "sha256-g8cyn+UshQZ3115dCwyiRTCbl+jsvP3B39xKufrDWzk=";

    patches = [
      ./3.0/nix-ssl-cert-file.patch

      # openssl will only compile in KTLS if the current kernel supports it.
      # This patch disables build-time detection.
      ./3.0/openssl-disable-kernel-detection.patch

      (if stdenv.hostPlatform.isDarwin
       then ./3.2/use-etc-ssl-certs-darwin.patch
       else ./3.2/use-etc-ssl-certs.patch)
    ];

    withDocs = true;

    extraMeta = with lib; {
      license = licenses.asl20;
    };
  };
}