current commit
261103.6 · tools: bump nixpkgs pins
# PKCS#11 fixture for `test/parallel/test-crypto-key-store-pkcs11.js`.
#
# Builds a SoftHSM2 token holding the key material that test expects, together
# with the OpenSSL configuration that activates pkcs11-provider against it.
# `shell.nix` exposes the result through the `NODE_TEST_PKCS11_*` environment
# variables when it is instantiated with `--arg pkcs11 true`.
{
  pkgs ? import ./pkgs.nix { },

  # pkcs11-provider is dlopen'd into the libcrypto Node.js itself links, so it
  # has to be built against that very OpenSSL. SoftHSM links OpenSSL too;
  # building it against the same one keeps a single libcrypto in the process.
  openssl ? (import ./openssl-matrix.nix { inherit pkgs; }).openssl_3_5,

  pin ? "1234",
}:

let
  # An override that yields the very same derivation is free, the package still
  # comes from the binary cache. Skipping pkcs11-provider's test suite is what
  # would cost that cache hit, so only do it once the override has forced a
  # rebuild anyway. SoftHSM needs neither, it does not run tests at all.
  pkcs11-provider =
    let
      inherit (pkgs) pkcs11-provider;
      pkcs11-provider' = pkcs11-provider.override { inherit openssl; };
    in
    if pkcs11-provider != pkcs11-provider' then
      pkcs11-provider'.overrideAttrs {
        doCheck = false;
      }
    else
      pkcs11-provider;

  softhsm = pkgs.softhsm.override { inherit openssl; };

  # OpenSSL names its provider modules after the platform's shared library
  # extension, while SoftHSM is a libtool module and keeps the `.so` suffix
  # everywhere, macOS included.
  providerModule = "${pkcs11-provider}/lib/ossl-modules/pkcs11${pkgs.stdenv.hostPlatform.extensions.sharedLibrary}";
  softhsmModule = "${softhsm}/lib/softhsm/libsofthsm2.so";

  # SoftHSM resolves a relative `directories.tokendir` against the working
  # directory, so naming it that way keeps this a plain store file rather than
  # something that has to be generated once the token's location is known.
  softhsmConf = pkgs.writeText "softhsm2.conf" ''
    directories.tokendir = tokens
    objectstore.backend = file
    log.level = ERROR
    slots.removable = false
  '';
in
{
  inherit
    pkcs11-provider
    softhsm
    ;

  opensslConf = pkgs.writeText "openssl-pkcs11.cnf" ''
    nodejs_conf = nodejs_init

    [nodejs_init]
    providers = provider_sect

    [provider_sect]
    default = default_sect
    pkcs11 = pkcs11_sect

    [default_sect]
    activate = 1

    [pkcs11_sect]
    module = ${providerModule}
    pkcs11-module-path = ${softhsmModule}
    pkcs11-module-quirks = no-deinit
    activate = 1
  '';

  # A SoftHSM working directory: the configuration above next to the token it
  # names. SoftHSM opens its token read-write, which a store path can never be,
  # so this is meant to be copied somewhere writable and used from there.
  #
  # `pkcs11-tool` comes from OpenSC and only fills the token here; neither it
  # nor `softhsm2-util` is needed to run the test.
  softhsmDir =
    pkgs.runCommand "node-pkcs11-softhsm"
      {
        nativeBuildInputs = [
          softhsm
          pkgs.opensc
        ];

        passthru = {
          inherit pin;
        };
      }
      ''
        export SOFTHSM2_CONF=${softhsmConf}
        mkdir tokens

        softhsm2-util --init-token --free --label node-test \
          --pin "${pin}" --so-pin "${pin}"

        keypairgen() {
          pkcs11-tool --module "${softhsmModule}" --login --pin "${pin}" \
            --keypairgen --key-type "$1" --id "$2" --label "$3" "$4"
        }

        # Keep this fixture limited to key types that SoftHSM and
        # pkcs11-provider can both generate and operate. Node's PQC APIs
        # require OpenSSL >= 3.5, but that does not imply ML-DSA or ML-KEM
        # support in this PKCS#11 stack.
        #
        # RSA decryption is likewise not covered: pkcs11-provider fails every
        # padding mode with `provider asym cipher failure` even for a key whose
        # PKCS#11 attributes include the decrypt usage, so
        # crypto.privateDecrypt() cannot be exercised against this stack.
        keypairgen RSA:2048 01 node-rsa --usage-sign
        keypairgen EC:prime256v1 02 node-ec --usage-sign
        keypairgen EC:ED25519 03 node-ed25519 --usage-sign
        keypairgen EC:ED448 04 node-ed448 --usage-sign
        keypairgen EC:prime256v1 05 node-ecdh --usage-derive

        mkdir -p "$out"
        cp -R tokens "$out/tokens"
        cp ${softhsmConf} "$out/softhsm2.conf"
      '';
}