# 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. import hashlib import os import re import shutil import pytest import isctest.mark pytestmark = [ isctest.mark.softhsm2_environment, pytest.mark.extra_artifacts( [ "*.example.db", "*.example.db.signed", "K*", "dsset-*", "keyfromlabel.out.*", "pin", "pkcs11-tool.out.*", "signer.out.*", ], ), ] EMPTY_OPENSSL_CONF_ENV = {**os.environ, "OPENSSL_CONF": ""} HSMPIN = "1234" @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_init_command = [ "softhsm2-util", "--init-token", "--free", "--pin", HSMPIN, "--so-pin", HSMPIN, "--label", "softhsm2-keyfromlabel", ] token_cleanup_command = [ "softhsm2-util", "--delete-token", "--token", "softhsm2-keyfromlabel", ] isctest.run.cmd( token_cleanup_command, env=EMPTY_OPENSSL_CONF_ENV, log_stderr=False, raise_on_exception=False, ) try: output = isctest.run.cmd( token_init_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True ).stdout.decode("utf-8") assert "The token has been initialized and is reassigned to slot" in output yield finally: output = isctest.run.cmd( token_cleanup_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True ).stdout.decode("utf-8") assert re.search("Found token (.*) with matching token label", output) assert re.search("The token (.*) has been deleted", output) # pylint: disable-msg=too-many-locals @pytest.mark.parametrize( "alg_name,alg_type,alg_bits", [ ("rsasha256", "rsa", "2048"), ("rsasha512", "rsa", "2048"), ("ecdsap256sha256", "EC", "prime256v1"), ("ecdsap384sha384", "EC", "prime384v1"), # Edwards curves are not yet supported by OpenSC # ("ed25519","EC","edwards25519"), # ("ed448","EC","edwards448") ], ) def test_keyfromlabel(alg_name, alg_type, alg_bits): def keygen(alg_type, alg_bits, zone, key_id): label = f"{key_id}-{zone}" p11_id = hashlib.sha1(label.encode("utf-8")).hexdigest() pkcs11_command = [ "pkcs11-tool", "--module", os.environ.get("SOFTHSM2_MODULE"), "--token-label", "softhsm2-keyfromlabel", "-l", "-k", "--key-type", f"{alg_type}:{alg_bits}", "--label", label, "--id", p11_id, "--pin", HSMPIN, ] output = isctest.run.cmd( pkcs11_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True ).stdout.decode("utf-8") assert "Key pair generated" in output def keyfromlabel(alg_name, zone, key_id, key_flag): key_flag = key_flag.split() if key_flag else [] keyfrlab_command = [ os.environ["KEYFRLAB"], *os.environ.get("ENGINE_ARG", "").split(), "-a", alg_name, "-l", f"pkcs11:token=softhsm2-keyfromlabel;object={key_id}-{zone};pin-source=pin", *key_flag, zone, ] output = isctest.run.cmd(keyfrlab_command, log_stdout=True) output_decoded = output.stdout.decode("utf-8").rstrip() + ".key" assert os.path.exists(output_decoded) return output_decoded if f"{alg_name.upper()}_SUPPORTED" not in os.environ: pytest.skip(f"{alg_name} is not supported") # Generate keys for the $zone zone zone = f"{alg_name}.example" keygen(alg_type, alg_bits, zone, "keyfromlabel-zsk") keygen(alg_type, alg_bits, zone, "keyfromlabel-ksk") # Get ZSK zsk_file = keyfromlabel(alg_name, zone, "keyfromlabel-zsk", "") # Get KSK ksk_file = keyfromlabel(alg_name, zone, "keyfromlabel-ksk", "-f KSK") # Sign zone with KSK and ZSK zone_file = f"zone.{alg_name}.example.db" with open(zone_file, "w", encoding="utf-8") as outfile: for f in ["template.db.in", ksk_file, zsk_file]: with open(f, "r", encoding="utf-8") as fd: shutil.copyfileobj(fd, outfile) signer_command = [ os.environ["SIGNER"], *os.environ.get("ENGINE_ARG", "").split(), "-S", "-a", "-g", "-o", zone, zone_file, ] isctest.run.cmd(signer_command, log_stdout=True) assert os.path.exists(f"{zone_file}.signed")