Home | History | Annotate | Line # | Download | only in keyfromlabel
      1 # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      2 #
      3 # SPDX-License-Identifier: MPL-2.0
      4 #
      5 # This Source Code Form is subject to the terms of the Mozilla Public
      6 # License, v. 2.0.  If a copy of the MPL was not distributed with this
      7 # file, you can obtain one at https://mozilla.org/MPL/2.0/.
      8 #
      9 # See the COPYRIGHT file distributed with this work for additional
     10 # information regarding copyright ownership.
     11 
     12 import hashlib
     13 import os
     14 from re import compile as Re
     15 import shutil
     16 
     17 import pytest
     18 
     19 import isctest.mark
     20 
     21 
     22 pytestmark = [
     23     isctest.mark.softhsm2_environment,
     24     pytest.mark.extra_artifacts(
     25         [
     26             "*.example.db",
     27             "*.example.db.signed",
     28             "K*",
     29             "dsset-*",
     30             "keyfromlabel.out.*",
     31             "pin",
     32             "pkcs11-tool.out.*",
     33             "signer.out.*",
     34         ],
     35     ),
     36 ]
     37 
     38 
     39 EMPTY_OPENSSL_CONF_ENV = {**os.environ, "OPENSSL_CONF": ""}
     40 
     41 HSMPIN = "1234"
     42 
     43 
     44 @pytest.fixture(autouse=True)
     45 def token_init_and_cleanup():
     46 
     47     # Create pin file for the $KEYFRLAB command
     48     with open("pin", "w", encoding="utf-8") as pinfile:
     49         pinfile.write(HSMPIN)
     50 
     51     token_init_command = [
     52         "softhsm2-util",
     53         "--init-token",
     54         "--free",
     55         "--pin",
     56         HSMPIN,
     57         "--so-pin",
     58         HSMPIN,
     59         "--label",
     60         "softhsm2-keyfromlabel",
     61     ]
     62 
     63     token_cleanup_command = [
     64         "softhsm2-util",
     65         "--delete-token",
     66         "--token",
     67         "softhsm2-keyfromlabel",
     68     ]
     69 
     70     isctest.run.cmd(
     71         token_cleanup_command,
     72         env=EMPTY_OPENSSL_CONF_ENV,
     73         raise_on_exception=False,
     74     )
     75 
     76     try:
     77         cmd = isctest.run.cmd(token_init_command, env=EMPTY_OPENSSL_CONF_ENV)
     78         assert "The token has been initialized and is reassigned to slot" in cmd.out
     79         yield
     80     finally:
     81         cmd = isctest.run.cmd(
     82             token_cleanup_command,
     83             env=EMPTY_OPENSSL_CONF_ENV,
     84             raise_on_exception=False,
     85         )
     86         assert Re("Found token (.*) with matching token label") in cmd.out
     87 
     88 
     89 # pylint: disable-msg=too-many-locals
     90 @pytest.mark.parametrize(
     91     "alg_name,alg_type,alg_bits",
     92     [
     93         ("rsasha256", "rsa", "2048"),
     94         ("rsasha512", "rsa", "2048"),
     95         ("ecdsap256sha256", "EC", "prime256v1"),
     96         ("ecdsap384sha384", "EC", "prime384v1"),
     97         # Edwards curves are not yet supported by OpenSC
     98         # ("ed25519","EC","edwards25519"),
     99         # ("ed448","EC","edwards448")
    100     ],
    101 )
    102 def test_keyfromlabel(alg_name, alg_type, alg_bits):
    103 
    104     def keygen(alg_type, alg_bits, zone, key_id):
    105         label = f"{key_id}-{zone}"
    106         p11_id = hashlib.sha1(label.encode("utf-8")).hexdigest()
    107 
    108         pkcs11_command = [
    109             "pkcs11-tool",
    110             "--module",
    111             os.environ.get("SOFTHSM2_MODULE"),
    112             "--token-label",
    113             "softhsm2-keyfromlabel",
    114             "-l",
    115             "-k",
    116             "--key-type",
    117             f"{alg_type}:{alg_bits}",
    118             "--label",
    119             label,
    120             "--id",
    121             p11_id,
    122             "--pin",
    123             HSMPIN,
    124         ]
    125 
    126         cmd = isctest.run.cmd(pkcs11_command, env=EMPTY_OPENSSL_CONF_ENV)
    127 
    128         assert "Key pair generated" in cmd.out
    129 
    130     def keyfromlabel(alg_name, zone, key_id, key_flag):
    131         key_flag = key_flag.split() if key_flag else []
    132 
    133         keyfrlab_command = [
    134             os.environ["KEYFRLAB"],
    135             *os.environ.get("ENGINE_ARG", "").split(),
    136             "-a",
    137             alg_name,
    138             "-y",
    139             "-l",
    140             f"pkcs11:token=softhsm2-keyfromlabel;object={key_id}-{zone};pin-source=pin",
    141             *key_flag,
    142             zone,
    143         ]
    144 
    145         cmd = isctest.run.cmd(keyfrlab_command)
    146         keyfile = cmd.out.rstrip() + ".key"
    147 
    148         assert os.path.exists(keyfile)
    149 
    150         return keyfile
    151 
    152     if f"{alg_name.upper()}_SUPPORTED" not in os.environ:
    153         pytest.skip(f"{alg_name} is not supported")
    154 
    155     # Generate keys for the $zone zone
    156     zone = f"{alg_name}.example"
    157 
    158     keygen(alg_type, alg_bits, zone, "keyfromlabel-zsk")
    159     keygen(alg_type, alg_bits, zone, "keyfromlabel-ksk")
    160 
    161     # Get ZSK
    162     zsk_file = keyfromlabel(alg_name, zone, "keyfromlabel-zsk", "")
    163 
    164     # Get KSK
    165     ksk_file = keyfromlabel(alg_name, zone, "keyfromlabel-ksk", "-f KSK")
    166 
    167     # Sign zone with KSK and ZSK
    168     zone_file = f"zone.{alg_name}.example.db"
    169 
    170     with open(zone_file, "w", encoding="utf-8") as outfile:
    171         for f in ["template.db.in", ksk_file, zsk_file]:
    172             with open(f, "r", encoding="utf-8") as fd:
    173                 shutil.copyfileobj(fd, outfile)
    174 
    175     signer_command = [
    176         os.environ["SIGNER"],
    177         *os.environ.get("ENGINE_ARG", "").split(),
    178         "-S",
    179         "-a",
    180         "-g",
    181         "-o",
    182         zone,
    183         zone_file,
    184     ]
    185     isctest.run.cmd(signer_command)
    186 
    187     assert os.path.exists(f"{zone_file}.signed")
    188