Commit 83017efaf2 for bind

commit 83017efaf2b889f0613ac96b63b6219df6216fc1
Author: Aydın Mercan <aydin@isc.org>
Date:   Mon Aug 17 10:46:19 2026 +0300

    Switch the PKCS#11 system tests from SoftHSMv2 to Kryoptic

    SoftHSMv2 has been a source of instability for the system tests: key
    generation through pkcs11-provider fails intermittently with
    CKR_GENERAL_ERROR when named creates keys for many zones at once, and
    named then backs off for ten minutes. Replace it with Kryoptic. The
    tests expect the environment variable BIND9_TEST_KRYOPTIC_MODULE to
    hold the path of the Kryoptic PKCS#11 module and render their own
    OpenSSL and Kryoptic configurations, so OPENSSL_CONF and SOFTHSM2_CONF
    no longer have to be set globally. The PINs live in _common/hsm_pin
    and _common/so_pin and are shared by the enginepkcs11 and keyfromlabel
    tests.

    The pkcs11-provider key cache is disabled in the test configurations.
    With the cache enabled, OSSL_STORE could return the same private key
    twice, which is what made enginepkcs11 fail at random; with the cache
    off the test passed in 100 parallel CI runs, so the flaky marker is
    gone.

    Assisted-by: Claude:claude-opus-5-5

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ab533e80bd..77f309addd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1386,8 +1386,7 @@ gcc:ossl3:trixie:amd64:
 system:gcc:ossl3:trixie:amd64:
   # Set up environment variables to run pkcs11-provider based system tests
   variables:
-    OPENSSL_CONF: "/var/tmp/etc/openssl-provider.cnf"
-    SOFTHSM2_CONF: "/var/tmp/softhsm2/softhsm2.conf"
+    BIND9_TEST_KRYOPTIC_MODULE: "/usr/lib/kryoptic/libkryoptic_pkcs11.so"
   <<: *debian_trixie_amd64_image
   <<: *system_test_job
   needs:
@@ -1395,10 +1394,6 @@ system:gcc:ossl3:trixie:amd64:
       artifacts: true

 unit:gcc:ossl3:amd64:
-  # Set up environment variables to run unit tests with PKCS#11-aware OpenSSL
-  variables:
-    OPENSSL_CONF: "/var/tmp/etc/openssl-provider.cnf"
-    SOFTHSM2_CONF: "/var/tmp/softhsm2/softhsm2.conf"
   <<: *debian_trixie_amd64_image
   <<: *unit_test_job
   needs:
diff --git a/bin/tests/system/README.md b/bin/tests/system/README.md
index ad0263dc03..ef15cb1314 100644
--- a/bin/tests/system/README.md
+++ b/bin/tests/system/README.md
@@ -337,7 +337,7 @@ Pytest marks control test collection and setup:
 - `@pytest.mark.requires_zones_loaded("ns1", ...)` delays the test until the
   listed servers have loaded all zones.
 - `isctest.mark` has skip-unless conditions for environment prerequisites,
-  e.g. `isctest.mark.with_dnstap`, `isctest.mark.softhsm2_environment`,
+  e.g. `isctest.mark.with_dnstap`, `isctest.mark.kryoptic_environment`,
   `isctest.mark.live_internet_test`.

 ### Parametrization
diff --git a/bin/tests/system/_common/hsm_pin b/bin/tests/system/_common/hsm_pin
new file mode 100644
index 0000000000..274c0052dd
--- /dev/null
+++ b/bin/tests/system/_common/hsm_pin
@@ -0,0 +1 @@
+1234
\ No newline at end of file
diff --git a/bin/tests/system/_common/so_pin b/bin/tests/system/_common/so_pin
new file mode 100644
index 0000000000..4632e068d5
--- /dev/null
+++ b/bin/tests/system/_common/so_pin
@@ -0,0 +1 @@
+123456
\ No newline at end of file
diff --git a/bin/tests/system/enginepkcs11/ns1/kryoptic.toml.j2.manual b/bin/tests/system/enginepkcs11/ns1/kryoptic.toml.j2.manual
new file mode 100644
index 0000000000..017df1b705
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/ns1/kryoptic.toml.j2.manual
@@ -0,0 +1,26 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+[ec_point_encoding]
+encoding = "Der"
+
+[[slots]]
+slot = 0
+dbtype = "sqlite"
+dbargs = "@database@"
+mechanisms = [
+    "CKM_RSA_PKCS_KEY_PAIR_GEN",
+    "CKM_RSA_PKCS",
+    "CKM_EC_KEY_PAIR_GEN",
+    "CKM_ECDSA",
+    "CKM_EC_EDWARDS_KEY_PAIR_GEN",
+    "CKM_EDDSA",
+]
diff --git a/bin/tests/system/enginepkcs11/ns1/named.conf.j2 b/bin/tests/system/enginepkcs11/ns1/named.conf.j2
index df534720e4..044b37f986 100644
--- a/bin/tests/system/enginepkcs11/ns1/named.conf.j2
+++ b/bin/tests/system/enginepkcs11/ns1/named.conf.j2
@@ -9,12 +9,12 @@ options {

 key-store "hsm" {
 	directory ".";
-	pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-value=1234";
+	pkcs11-uri "pkcs11:token=kryoptic-enginepkcs11;pin-value={%- include "_common/hsm_pin" -%}";
 };

 key-store "pin" {
 	directory ".";
-	pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-source=pin";
+	pkcs11-uri "pkcs11:token=kryoptic-enginepkcs11;pin-source=@pin_path@";
 };

 key-store "disk" {
diff --git a/bin/tests/system/enginepkcs11/ns2/kryoptic.toml.j2.manual b/bin/tests/system/enginepkcs11/ns2/kryoptic.toml.j2.manual
new file mode 100644
index 0000000000..017df1b705
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/ns2/kryoptic.toml.j2.manual
@@ -0,0 +1,26 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+[ec_point_encoding]
+encoding = "Der"
+
+[[slots]]
+slot = 0
+dbtype = "sqlite"
+dbargs = "@database@"
+mechanisms = [
+    "CKM_RSA_PKCS_KEY_PAIR_GEN",
+    "CKM_RSA_PKCS",
+    "CKM_EC_KEY_PAIR_GEN",
+    "CKM_ECDSA",
+    "CKM_EC_EDWARDS_KEY_PAIR_GEN",
+    "CKM_EDDSA",
+]
diff --git a/bin/tests/system/enginepkcs11/ns2/named.conf.j2 b/bin/tests/system/enginepkcs11/ns2/named.conf.j2
index c163e74dc8..13f3bd30d3 100644
--- a/bin/tests/system/enginepkcs11/ns2/named.conf.j2
+++ b/bin/tests/system/enginepkcs11/ns2/named.conf.j2
@@ -19,17 +19,17 @@ key "keyforview2" {

 key-store "hsm" {
 	directory ".";
-	pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-value=1234";
+	pkcs11-uri "pkcs11:token=kryoptic-enginepkcs11;pin-value={%- include "_common/hsm_pin" -%}";
 };

 key-store "hsm2" {
 	directory "keys";
-	pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-value=1234";
+	pkcs11-uri "pkcs11:token=kryoptic-enginepkcs11;pin-value={%- include "_common/hsm_pin" -%}";
 };

 key-store "pin" {
 	directory ".";
-	pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-source=pin";
+	pkcs11-uri "pkcs11:token=kryoptic-enginepkcs11;pin-source=@pin_path@";
 };

 key-store "disk" {
diff --git a/bin/tests/system/enginepkcs11/openssl.cnf.j2.manual b/bin/tests/system/enginepkcs11/openssl.cnf.j2.manual
new file mode 100644
index 0000000000..4d1fec9e53
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/openssl.cnf.j2.manual
@@ -0,0 +1,28 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+openssl_conf = openssl_init
+
+[openssl_init]
+providers = provider_sect
+
+[provider_sect]
+default = default_sect
+pkcs11 = pkcs11_sect
+
+[default_sect]
+activate = 1
+
+[pkcs11_sect]
+pkcs11-module-load-behavior = early
+pkcs11-module-path = @pkcs11_module_path@
+pkcs11-module-cache-keys = false
+activate = 1
diff --git a/bin/tests/system/enginepkcs11/openssl_pin.cnf.j2.manual b/bin/tests/system/enginepkcs11/openssl_pin.cnf.j2.manual
new file mode 100644
index 0000000000..b70fd9b4ee
--- /dev/null
+++ b/bin/tests/system/enginepkcs11/openssl_pin.cnf.j2.manual
@@ -0,0 +1,29 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+openssl_conf = openssl_init
+
+[openssl_init]
+providers = provider_sect
+
+[provider_sect]
+default = default_sect
+pkcs11 = pkcs11_sect
+
+[default_sect]
+activate = 1
+
+[pkcs11_sect]
+pkcs11-module-load-behavior = early
+pkcs11-module-path = @pkcs11_module_path@
+pkcs11-module-token-pin = file:@pin_path@
+pkcs11-module-cache-keys = false
+activate = 1
diff --git a/bin/tests/system/enginepkcs11/setup.sh b/bin/tests/system/enginepkcs11/setup.sh
index f10df0c118..404c2bb851 100644
--- a/bin/tests/system/enginepkcs11/setup.sh
+++ b/bin/tests/system/enginepkcs11/setup.sh
@@ -16,11 +16,9 @@

 set -e

-OPENSSL_CONF= softhsm2-util --delete-token --token "softhsm2-enginepkcs11" >/dev/null 2>&1 || true
-OPENSSL_CONF= softhsm2-util --init-token --free --pin 1234 --so-pin 1234 --label "softhsm2-enginepkcs11" | awk '/^The token has been initialized and is reassigned to slot/ { print $NF }'
-
-printf '%s' "${HSMPIN:-1234}" >ns1/pin
 PWD=$(pwd)
+SO_PIN=$(cat ../_common/so_pin)
+HSM_PIN=$(cat ../_common/hsm_pin)

 keygen() {
   type="$1"
@@ -30,7 +28,7 @@ keygen() {

   label="${id}-${zone}"
   p11id=$(echo "${label}" | openssl sha1 -r | awk '{print $1}')
-  OPENSSL_CONF= pkcs11-tool --module $SOFTHSM2_MODULE --token-label "softhsm2-enginepkcs11" -l -k --key-type $type:$bits --label "${label}" --id "${p11id}" --pin $(cat $PWD/ns1/pin) >pkcs11-tool.out.$zone.$id 2>pkcs11-tool.err.$zone.$id || return 1
+  OPENSSL_CONF= pkcs11-tool --module $BIND9_TEST_KRYOPTIC_MODULE --token-label "kryoptic-enginepkcs11" -l -k --key-type $type:$bits --label "${label}" --id "${p11id}" --pin $HSM_PIN >pkcs11-tool.out.$zone.$id 2>pkcs11-tool.err.$zone.$id || return 1
 }

 keyfromlabel() {
@@ -40,7 +38,7 @@ keyfromlabel() {
   dir="$4"
   shift 4

-  $KEYFRLAB -K $dir -a $alg -y -l "pkcs11:token=softhsm2-enginepkcs11;object=${id}-${zone};pin-source=$PWD/ns1/pin" "$@" $zone >>keyfromlabel.out.$zone.$id 2>keyfromlabel.err.$zone.$id || return 1
+  OPENSSL_CONF="${PWD}/openssl_pin.cnf" KRYOPTIC_CONF=$KRYOPTIC_CONF $KEYFRLAB -K $dir -a $alg -y -l "pkcs11:token=kryoptic-enginepkcs11;object=${id}-${zone};pin-source=$PWD/../_common/hsm_pin" "$@" $zone >>keyfromlabel.out.$zone.$id 2>keyfromlabel.err.$zone.$id || return 1
   cat keyfromlabel.out.$zone.$id
 }

@@ -66,6 +64,9 @@ hsmkey() {
 }

 mkdir ns1/keys
+export KRYOPTIC_CONF=${PWD}/ns1/kryoptic.toml
+OPENSSL_CONF= pkcs11-tool --module $BIND9_TEST_KRYOPTIC_MODULE --init-token --label "kryoptic-enginepkcs11" --so-pin $SO_PIN
+OPENSSL_CONF= pkcs11-tool --module $BIND9_TEST_KRYOPTIC_MODULE --init-pin --login --login-type so --so-pin $SO_PIN --pin $HSM_PIN

 dir="ns1"
 infile="${dir}/template.db.in"
@@ -104,7 +105,7 @@ for algtypebits in rsasha256:rsa:2048 rsasha512:rsa:2048 \

     echo_i "Sign zone with $ksk1 $zsk1"
     cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" >"${dir}/${zonefile}"
-    $SIGNER -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile}" >signer.out.$zone || ret=1
+    OPENSSL_CONF="${PWD}/openssl_pin.cnf" $SIGNER -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile}" >signer.out.$zone || ret=1
     test "$ret" -eq 0 || exit 1

     echo_i "Generate successor keys $alg $type:$bits for zone $zone"
@@ -192,6 +193,9 @@ EOF
 done

 mkdir ns2/keys
+export KRYOPTIC_CONF=${PWD}/ns2/kryoptic.toml
+OPENSSL_CONF= pkcs11-tool --module $BIND9_TEST_KRYOPTIC_MODULE --init-token --label "kryoptic-enginepkcs11" --so-pin $SO_PIN
+OPENSSL_CONF= pkcs11-tool --module $BIND9_TEST_KRYOPTIC_MODULE --init-pin --login --login-type so --so-pin $SO_PIN --pin $HSM_PIN

 dir="ns2"
 infile="${dir}/template.db.in"
@@ -229,11 +233,11 @@ if [ "${supported}" = 1 ]; then

   echo_i "Sign zone with $ksk1 $zsk1"
   cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" >"${dir}/${zonefile1}"
-  $SIGNER -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile1}" >signer.out.view1.$zone || ret=1
+  OPENSSL_CONF="${PWD}/openssl_pin.cnf" $SIGNER -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile1}" >signer.out.view1.$zone || ret=1
   test "$ret" -eq 0 || exit 1

   cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" >"${dir}/${zonefile2}"
-  $SIGNER -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile2}" >signer.out.view2.$zone || ret=1
+  OPENSSL_CONF="${PWD}/openssl_pin.cnf" $SIGNER -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile2}" >signer.out.view2.$zone || ret=1
   test "$ret" -eq 0 || exit 1

   echo_i "Generate successor keys $alg $type:$bits for zone $zone"
diff --git a/bin/tests/system/enginepkcs11/tests.sh b/bin/tests/system/enginepkcs11/tests.sh
index 0546a7c62a..ce22820431 100644
--- a/bin/tests/system/enginepkcs11/tests.sh
+++ b/bin/tests/system/enginepkcs11/tests.sh
@@ -261,7 +261,7 @@ EOF
   n=$((n + 1))
   ret=0
   echo_i "Test dnssec-keygen for $zone ($n)"
-  $KEYGEN -k $alg -l named.conf $zone >keygen.out.$zone.$n 2>/dev/null || ret=1
+  OPENSSL_CONF="../openssl_pin.cnf" KRYOPTIC_CONF="kryoptic.toml" $KEYGEN -k $alg -l named.conf $zone >keygen.out.$zone.$n || ret=1
   check_keys $zone 2 || ret=1
   status=$((status + ret))

diff --git a/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py b/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py
index 367913efce..9c0ce12013 100644
--- a/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py
+++ b/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py
@@ -9,12 +9,20 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.

+from pathlib import Path
+from typing import Any
+
+import os
+
 import pytest

 import isctest.mark
+import isctest.template

 EXTRA_ARTIFACTS = pytest.mark.extra_artifacts(
     [
+        "openssl.cnf",
+        "openssl_pin.cnf",
         "dig.out.*",
         "dsset-*",
         "keyfromlabel.err.*",
@@ -28,13 +36,14 @@ EXTRA_ARTIFACTS = pytest.mark.extra_artifacts(
         "ns*/update.cmd.*",
         "ns*/update.log.*",
         "ns*/verify.out.*",
-        "ns*/pin",
         "ns*/zone.*.jbk",
         "ns*/zone.*.jnl",
         "ns*/*.kskid1",
         "ns*/*.kskid2",
         "ns*/*.zskid1",
         "ns*/*.zskid2",
+        "ns*/kryoptic.toml",
+        "ns*/kryoptic.db",
         "ns1/keys",
         "ns1/*.example.db",
         "ns1/*.example.db.signed",
@@ -52,11 +61,37 @@ EXTRA_ARTIFACTS = pytest.mark.extra_artifacts(

 pytestmark = [
     isctest.mark.with_pkcs11_provider,
-    isctest.mark.softhsm2_environment,
+    isctest.mark.kryoptic_environment,
     EXTRA_ARTIFACTS,
 ]


-@pytest.mark.flaky(max_runs=5)  # GL#4605
+def bootstrap() -> dict[str, Any]:
+    templates = isctest.template.TemplateEngine(".")
+
+    pin_path = Path.cwd().parent.joinpath("_common", "hsm_pin").resolve()
+
+    database = Path.cwd().joinpath("ns1", "kryoptic.db").resolve()
+    templates.render("ns1/kryoptic.toml", {"database": str(database)})
+
+    database = Path.cwd().joinpath("ns2", "kryoptic.db").resolve()
+    templates.render("ns2/kryoptic.toml", {"database": str(database)})
+
+    templates.render(
+        "openssl.cnf",
+        {"pkcs11_module_path": os.environ["BIND9_TEST_KRYOPTIC_MODULE"]},
+    )
+
+    templates.render(
+        "openssl_pin.cnf",
+        {
+            "pkcs11_module_path": os.environ["BIND9_TEST_KRYOPTIC_MODULE"],
+            "pin_path": pin_path,
+        },
+    )
+
+    return {"pin_path": pin_path}
+
+
 def test_enginepkcs11(run_tests_sh):
     run_tests_sh()
diff --git a/bin/tests/system/isctest/mark.py b/bin/tests/system/isctest/mark.py
index 1f3da608aa..ddb4f85cc3 100644
--- a/bin/tests/system/isctest/mark.py
+++ b/bin/tests/system/isctest/mark.py
@@ -9,6 +9,8 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.

+from pathlib import Path
+
 import os
 import platform
 import shutil
@@ -133,19 +135,31 @@ with_curl = pytest.mark.skipif(
     not shutil.which(os.getenv("CURL", "")), reason="curl is required"
 )

-softhsm2_environment = pytest.mark.skipif(
-    not (
-        os.getenv("SOFTHSM2_CONF")
-        and os.getenv("SOFTHSM2_MODULE")
-        and shutil.which("pkcs11-tool")
-        and shutil.which("softhsm2-util")
-    ),
-    reason="SOFTHSM2_CONF and SOFTHSM2_MODULE environmental variables must be set and pkcs11-tool and softhsm2-util tools present",
+
+def _openssl_provider_available(provider: str) -> bool:
+    dylib = f".{os.environ.get('DYLIB', 'so')}"
+    try:
+        moduledir = subprocess.run(
+            ["openssl", "info", "-modulesdir"],
+            capture_output=True,
+            check=True,
+            text=True,
+        ).stdout.strip()
+
+        return Path(moduledir).joinpath(provider).with_suffix(dylib).resolve().is_file()
+    except (subprocess.CalledProcessError, FileNotFoundError):
+        return False
+
+
+kryoptic_environment = pytest.mark.skipif(
+    os.getenv("BIND9_TEST_KRYOPTIC_MODULE") is None
+    or shutil.which("pkcs11-tool") is None,
+    reason="BIND9_TEST_KRYOPTIC_MODULE environmental variable must be set and the pkcs11-tool tool present",
 )

 with_pkcs11_provider = pytest.mark.skipif(
-    os.path.basename(os.getenv("OPENSSL_CONF") or "") != "openssl-provider.cnf",
-    reason="pkcs11-provider not enabled",
+    not _openssl_provider_available("pkcs11"),
+    reason="pkcs11-provider not available in default OpenSSL module path",
 )


diff --git a/bin/tests/system/isctest/vars/openssl.py b/bin/tests/system/isctest/vars/openssl.py
index 2458db46f8..a07efb0225 100644
--- a/bin/tests/system/isctest/vars/openssl.py
+++ b/bin/tests/system/isctest/vars/openssl.py
@@ -17,15 +17,15 @@ from .. import log

 OPENSSL_VARS = {
     "OPENSSL_CONF": os.getenv("OPENSSL_CONF", None),
-    "SOFTHSM2_CONF": os.getenv("SOFTHSM2_CONF", None),
-    "SOFTHSM2_MODULE": None,
+    "BIND9_TEST_KRYOPTIC_MODULE": os.getenv("BIND9_TEST_KRYOPTIC_MODULE", None),
 }


 def parse_openssl_config(path: str | None):
+    # An explicitly set module takes precedence over the OpenSSL config.
+    if OPENSSL_VARS["BIND9_TEST_KRYOPTIC_MODULE"] is not None:
+        return
     if path is None or not os.path.exists(path):
-        OPENSSL_VARS["SOFTHSM2_MODULE"] = None
-        os.environ.pop("SOFTHSM2_MODULE", None)
         return
     assert os.path.isfile(path), f"{path} exists, but it's not a file"

@@ -38,8 +38,8 @@ def parse_openssl_config(path: str | None):
                 key = res.group(1).strip()
                 val = res.group(2).strip()
                 if key in ["MODULE_PATH", "pkcs11-module-path"]:
-                    OPENSSL_VARS["SOFTHSM2_MODULE"] = val
-                    os.environ["SOFTHSM2_MODULE"] = val
+                    OPENSSL_VARS["BIND9_TEST_KRYOPTIC_MODULE"] = val
+                    os.environ["BIND9_TEST_KRYOPTIC_MODULE"] = val
                     log.debug(
-                        "SOFTHSM2_MODULE set to {OPENSSL_VARS['SOFTHSM2_MODULE']}"
+                        f"BIND9_TEST_KRYOPTIC_MODULE set to {OPENSSL_VARS['BIND9_TEST_KRYOPTIC_MODULE']}"
                     )
diff --git a/bin/tests/system/keyfromlabel/kryoptic.toml.j2.manual b/bin/tests/system/keyfromlabel/kryoptic.toml.j2.manual
new file mode 100644
index 0000000000..017df1b705
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/kryoptic.toml.j2.manual
@@ -0,0 +1,26 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+[ec_point_encoding]
+encoding = "Der"
+
+[[slots]]
+slot = 0
+dbtype = "sqlite"
+dbargs = "@database@"
+mechanisms = [
+    "CKM_RSA_PKCS_KEY_PAIR_GEN",
+    "CKM_RSA_PKCS",
+    "CKM_EC_KEY_PAIR_GEN",
+    "CKM_ECDSA",
+    "CKM_EC_EDWARDS_KEY_PAIR_GEN",
+    "CKM_EDDSA",
+]
diff --git a/bin/tests/system/keyfromlabel/openssl.cnf.j2.manual b/bin/tests/system/keyfromlabel/openssl.cnf.j2.manual
new file mode 100644
index 0000000000..b70fd9b4ee
--- /dev/null
+++ b/bin/tests/system/keyfromlabel/openssl.cnf.j2.manual
@@ -0,0 +1,29 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+openssl_conf = openssl_init
+
+[openssl_init]
+providers = provider_sect
+
+[provider_sect]
+default = default_sect
+pkcs11 = pkcs11_sect
+
+[default_sect]
+activate = 1
+
+[pkcs11_sect]
+pkcs11-module-load-behavior = early
+pkcs11-module-path = @pkcs11_module_path@
+pkcs11-module-token-pin = file:@pin_path@
+pkcs11-module-cache-keys = false
+activate = 1
diff --git a/bin/tests/system/keyfromlabel/tests_keyfromlabel.py b/bin/tests/system/keyfromlabel/tests_keyfromlabel.py
index 3e2ee37dfd..a67d1a9b93 100644
--- a/bin/tests/system/keyfromlabel/tests_keyfromlabel.py
+++ b/bin/tests/system/keyfromlabel/tests_keyfromlabel.py
@@ -9,7 +9,8 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.

-from re import compile as Re
+from pathlib import Path
+from typing import Any

 import hashlib
 import os
@@ -22,7 +23,7 @@ from isctest.util import param
 import isctest.mark

 pytestmark = [
-    isctest.mark.softhsm2_environment,
+    isctest.mark.kryoptic_environment,
     pytest.mark.extra_artifacts(
         [
             "*.example.db",
@@ -30,62 +31,88 @@ pytestmark = [
             "K*",
             "dsset-*",
             "keyfromlabel.out.*",
-            "pin",
             "pkcs11-tool.out.*",
             "signer.out.*",
+            "kryoptic.db",
+            "kryoptic.toml",
+            "openssl.cnf",
         ],
     ),
 ]

+HSMPIN = None
+SOPIN = None

-EMPTY_OPENSSL_CONF_ENV = {**os.environ, "OPENSSL_CONF": ""}

-HSMPIN = "1234"
+def bootstrap() -> dict[str, Any]:
+    global HSMPIN  # pylint: disable=global-statement
+    HSMPIN = (
+        Path.cwd().parent.joinpath("_common", "hsm_pin").read_text(encoding="utf-8")
+    )
+
+    global SOPIN  # pylint: disable=global-statement
+    SOPIN = Path.cwd().parent.joinpath("_common", "so_pin").read_text(encoding="utf-8")
+
+    templates = isctest.template.TemplateEngine(".")
+
+    database = Path.cwd() / "kryoptic.db"
+    templates.render("kryoptic.toml", {"database": str(database)})
+
+    templates.render(
+        "openssl.cnf",
+        {
+            "pkcs11_module_path": os.environ["BIND9_TEST_KRYOPTIC_MODULE"],
+            "pin_path": Path.cwd().parent.joinpath("_common", "hsm_pin").resolve(),
+        },
+    )
+
+    return {}


 @pytest.fixture(autouse=True)
 def token_init_and_cleanup():
-
-    # Create pin file for the $KEYFRLAB command
-    with open("pin", "w", encoding="utf-8") as pinfile:
-        pinfile.write(HSMPIN)
+    token_env = {
+        **os.environ,
+        "OPENSSL_CONF": "",
+        "KRYOPTIC_CONF": Path.cwd().joinpath("kryoptic.toml").as_posix(),
+    }

     token_init_command = [
-        "softhsm2-util",
+        "pkcs11-tool",
+        "--module",
+        os.environ["BIND9_TEST_KRYOPTIC_MODULE"],
         "--init-token",
-        "--free",
-        "--pin",
-        HSMPIN,
-        "--so-pin",
-        HSMPIN,
         "--label",
-        "softhsm2-keyfromlabel",
+        "kryoptic-keyfromlabel",
+        "--so-pin",
+        SOPIN,
     ]

-    token_cleanup_command = [
-        "softhsm2-util",
-        "--delete-token",
-        "--token",
-        "softhsm2-keyfromlabel",
+    token_pin_init_command = [
+        "pkcs11-tool",
+        "--module",
+        os.environ["BIND9_TEST_KRYOPTIC_MODULE"],
+        "--init-pin",
+        "--login",
+        "--login-type",
+        "so",
+        "--so-pin",
+        SOPIN,
+        "--pin",
+        HSMPIN,
     ]

-    isctest.run.cmd(
-        token_cleanup_command,
-        env=EMPTY_OPENSSL_CONF_ENV,
-        raise_on_exception=False,
-    )
+    database = Path.cwd() / "kryoptic.db"

     try:
-        cmd = isctest.run.cmd(token_init_command, env=EMPTY_OPENSSL_CONF_ENV)
-        assert "The token has been initialized and is reassigned to slot" in cmd.out
+        cmd = isctest.run.cmd(token_init_command, env=token_env)
+        assert "Token successfully initialized" in cmd.out
+        cmd = isctest.run.cmd(token_pin_init_command, env=token_env)
+        assert "User PIN successfully initialized" in cmd.out
+        assert database.exists()
         yield
     finally:
-        cmd = isctest.run.cmd(
-            token_cleanup_command,
-            env=EMPTY_OPENSSL_CONF_ENV,
-            raise_on_exception=False,
-        )
-        assert Re("Found token (.*) with matching token label") in cmd.out
+        database.unlink(missing_ok=True)


 @pytest.mark.parametrize(
@@ -116,6 +143,11 @@ def token_init_and_cleanup():
     ],
 )
 def test_keyfromlabel(alg_name, alg_type, alg_bits):
+    test_env = {
+        **os.environ,
+        "OPENSSL_CONF": Path.cwd().joinpath("openssl.cnf").as_posix(),
+        "KRYOPTIC_CONF": Path.cwd().joinpath("kryoptic.toml").as_posix(),
+    }

     def keygen(alg_type, alg_bits, label):
         p11_id = hashlib.sha1(label.encode("utf-8")).hexdigest()
@@ -123,9 +155,9 @@ def test_keyfromlabel(alg_name, alg_type, alg_bits):
         pkcs11_command = [
             "pkcs11-tool",
             "--module",
-            os.environ.get("SOFTHSM2_MODULE"),
+            os.environ.get("BIND9_TEST_KRYOPTIC_MODULE"),
             "--token-label",
-            "softhsm2-keyfromlabel",
+            "kryoptic-keyfromlabel",
             "-l",
             "-k",
             "--key-type",
@@ -138,7 +170,7 @@ def test_keyfromlabel(alg_name, alg_type, alg_bits):
             HSMPIN,
         ]

-        cmd = isctest.run.cmd(pkcs11_command, env=EMPTY_OPENSSL_CONF_ENV)
+        cmd = isctest.run.cmd(pkcs11_command, env=test_env)

         assert "Key pair generated" in cmd.out

@@ -151,12 +183,12 @@ def test_keyfromlabel(alg_name, alg_type, alg_bits):
             alg_name,
             "-y",
             "-l",
-            f"pkcs11:token=softhsm2-keyfromlabel;object={label};pin-source=pin",
+            f"pkcs11:token=kryoptic-keyfromlabel;object={label};pin-source=../_common/hsm_pin",
             *key_flag,
             zone,
         ]

-        cmd = isctest.run.cmd(keyfrlab_command, raise_on_exception=False)
+        cmd = isctest.run.cmd(keyfrlab_command, env=test_env, raise_on_exception=False)
         if cmd.rc != 0 and "already exists" in cmd.err:
             return None
         assert cmd.rc == 0
@@ -208,6 +240,6 @@ def test_keyfromlabel(alg_name, alg_type, alg_bits):
         zone,
         zone_file,
     ]
-    isctest.run.cmd(signer_command)
+    isctest.run.cmd(signer_command, env=test_env)

     assert os.path.exists(f"{zone_file}.signed")