{
  lib,
  pkgs,
  stdenv,
  fetchurl,
  perl,
  makeBinaryWrapper,
  withCryptodev ? false,
  cryptodev,
  withZlib ? false,
  zlib,
  enableSSL2 ? false,
  enableSSL3 ? false,
  enableMD2 ? false,
  enableKTLS ? stdenv.hostPlatform.isLinux,
  static ? stdenv.hostPlatform.isStatic,
  removeReferencesTo,
}:

stdenv.mkDerivation rec {
    pname = "openssl";
    version = pkgs.openssl.version;

    src = pkgs.openssl.src;

    outputs = [ "out" ];

    nativeBuildInputs =
      lib.optional (!stdenv.hostPlatform.isWindows) makeBinaryWrapper
      ++ [ 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";
        powerpc64-linux = "./Configure linux-ppc64";
        riscv32-linux = "./Configure ${
          if lib.versionAtLeast version "3.2" then "linux32-riscv32" else "linux-latomic"
        }";
        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.isMicroBlaze then
            "./Configure linux-latomic"
          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
        "--prefix=/"
        "--libdir=lib"
        "--openssldir=/etc/ssl"
      ]
      ++ lib.optionals withCryptodev [
        "-DHAVE_CRYPTODEV"
        "-DUSE_CRYPTODEV_DIGESTS"
      ]
      ++ lib.optional enableMD2 "enable-md2"
      ++ 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"
      # /dev/crypto support has been dropped in OpenBSD 5.7.
      #
      # OpenBSD's ports does this too,
      # https://github.com/openbsd/ports/blob/a1147500c76970fea22947648fb92a093a529d7c/security/openssl/3.3/Makefile#L25.
      #
      # https://github.com/openssl/openssl/pull/10565 indicated the
      # intent was that this would be configured properly automatically,
      # but that doesn't appear to be the case.
      ++ lib.optional stdenv.hostPlatform.isOpenBSD "no-devcryptoeng"
      ++ 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}"
      ];

    postPatch = ''
      patchShebangs Configure
    '';

    installPhase = ''
      make DESTDIR=$out install
      rm -rf $out/etc/ssl/*.dist $out/etc/ssl/misc
    '';

    enableParallelBuilding = true;

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