cryptography

Performing Hardware Security Module Integration

Integrate Hardware Security Modules (HSMs) using PKCS#11 interface for cryptographic key management, signing operations, and secure key storage with python-pkcs11, AWS CloudHSM, and YubiHSM2.

cloudhsmcryptographic-operationshardware-securityhsmkey-managementpkcs11yubihsm2
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Hardware Security Modules (HSMs) provide tamper-resistant cryptographic key storage and operations. This skill covers integrating with HSMs via the PKCS#11 standard interface using python-pkcs11, performing key generation, signing, encryption, and verification operations, querying token and slot information, and validating HSM configuration for compliance with FIPS 140-2/3 requirements.

When to Use

  • When conducting security assessments that involve performing hardware security module integration
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing

Prerequisites

  • HSM device or software HSM (SoftHSM2 for testing)
  • PKCS#11 shared library (.so/.dll) for the HSM vendor
  • Python 3.9+ with python-pkcs11
  • Token initialized with SO PIN and user PIN
  • For AWS CloudHSM: cloudhsm-pkcs11 provider configured

Steps

  1. Load PKCS#11 library and enumerate available slots and tokens
  2. Open session and authenticate with user PIN
  3. Generate RSA 2048-bit or EC P-256 key pairs on the HSM
  4. Perform signing and verification using on-device keys
  5. List all objects (keys, certificates) stored on the token
  6. Query mechanism list to verify supported algorithms
  7. Generate compliance report with key inventory and algorithm audit

Expected Output

  • JSON report listing HSM slots, tokens, stored keys, supported mechanisms, and compliance status
  • Signing test results with key metadata and algorithm details
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md3.1 KB

API Reference — Performing Hardware Security Module Integration

Libraries Used

  • python-pkcs11: Python PKCS#11 wrapper for HSM cryptographic operations
  • json: JSON serialization for audit reports

CLI Interface

python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 slots
python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 objects
python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 gen-rsa --label mykey --bits 2048
python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 gen-ec --label myec
python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 sign-verify --key-label mykey
python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 mechanisms
python agent.py --lib /usr/lib/softhsm/libsofthsm2.so --token MyToken --pin 1234 full

Core Functions

load_library(lib_path) — Load PKCS#11 shared library

Calls pkcs11.lib(lib_path) to initialize the PKCS#11 provider.

enumerate_slots(lib) — List slots and token info

Iterates lib.get_slots(token_present=True). Returns token label, manufacturer, model, serial, initialization status, and supported mechanism list.

list_objects(lib, token_label, pin) — Inventory stored keys

Opens authenticated session, calls session.get_objects(). Returns object class, label, key type, key length, and object ID.

generate_rsa_keypair(lib, token_label, pin, key_label, bits) — RSA key generation

Calls session.generate_keypair(KeyType.RSA, bits, store=True, label=key_label).

generate_ec_keypair(lib, token_label, pin, key_label) — EC P-256 key generation

Creates domain parameters for secp256r1 via encode_named_curve_parameters, then calls ecparams.generate_keypair().

sign_and_verify(lib, token_label, pin, key_label) — Signing test

Signs with priv.sign(data, mechanism=Mechanism.SHA256_RSA_PKCS). Verifies with pub.verify(data, signature, mechanism=Mechanism.SHA256_RSA_PKCS).

query_mechanisms(lib, token_label) — Algorithm support audit

Enumerates all mechanisms with min/max key sizes from the slot.

full_audit(lib, token_label, pin) — Comprehensive compliance report

PKCS#11 Object Classes

Class Description
PUBLIC_KEY RSA/EC public keys
PRIVATE_KEY RSA/EC private keys (non-extractable)
SECRET_KEY Symmetric keys (AES, DES3)
CERTIFICATE X.509 certificates

FIPS 140-2 Required Mechanisms

RSA_PKCS, SHA256_RSA_PKCS, SHA384_RSA_PKCS, SHA512_RSA_PKCS, ECDSA, ECDSA_SHA256, AES_CBC, AES_GCM, SHA256, SHA384, SHA512

Common PKCS#11 Libraries

HSM Library Path
SoftHSM2 /usr/lib/softhsm/libsofthsm2.so
AWS CloudHSM /opt/cloudhsm/lib/libcloudhsm_pkcs11.so
YubiHSM2 /usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so
Thales Luna /usr/safenet/lunaclient/lib/libCryptoki2_64.so

Dependencies

  • python-pkcs11 >= 0.7.0
  • PKCS#11 shared library for target HSM
  • Initialized token with user PIN

Scripts 1

agent.py8.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for Hardware Security Module integration via PKCS#11 interface."""

import json
import argparse
from datetime import datetime

try:
    import pkcs11
    from pkcs11 import KeyType, ObjectClass, Mechanism
except ImportError:
    pkcs11 = None


def load_library(lib_path):
    """Load PKCS#11 shared library."""
    if not pkcs11:
        raise RuntimeError("python-pkcs11 not installed: pip install python-pkcs11")
    return pkcs11.lib(lib_path)


def enumerate_slots(lib):
    """List all available PKCS#11 slots and token info."""
    slots = []
    for slot in lib.get_slots(token_present=True):
        token = slot.get_token()
        mechs = slot.get_mechanisms()
        slots.append({
            "slot_id": slot.slot_id,
            "slot_description": slot.slot_description.strip() if hasattr(slot, 'slot_description') else str(slot),
            "token_label": token.label.strip(),
            "token_manufacturer": token.manufacturer_id.strip(),
            "token_model": token.model.strip(),
            "token_serial": token.serial.strip(),
            "token_initialized": token.flags & pkcs11.TokenFlag.TOKEN_INITIALIZED != 0,
            "mechanism_count": len(list(mechs)),
            "supported_mechanisms": sorted([m.name for m in mechs])[:30],
        })
    return slots


def list_objects(lib, token_label, pin):
    """List all cryptographic objects stored on the HSM token."""
    token = lib.get_token(token_label=token_label)
    with token.open(user_pin=pin) as session:
        objects = []
        for obj in session.get_objects():
            obj_info = {
                "object_class": obj.object_class.name if hasattr(obj.object_class, 'name') else str(obj.object_class),
                "label": getattr(obj, 'label', 'N/A'),
            }
            if hasattr(obj, 'key_type'):
                obj_info["key_type"] = obj.key_type.name if hasattr(obj.key_type, 'name') else str(obj.key_type)
            if hasattr(obj, 'key_length'):
                obj_info["key_length"] = obj.key_length
            if hasattr(obj, 'id'):
                obj_info["id"] = obj.id.hex() if isinstance(obj.id, bytes) else str(obj.id)
            objects.append(obj_info)
        return objects


def generate_rsa_keypair(lib, token_label, pin, key_label="agent-rsa-2048", bits=2048):
    """Generate an RSA key pair on the HSM."""
    token = lib.get_token(token_label=token_label)
    with token.open(rw=True, user_pin=pin) as session:
        pub, priv = session.generate_keypair(
            KeyType.RSA, bits,
            store=True,
            label=key_label,
        )
        return {
            "action": "generate_rsa_keypair",
            "key_label": key_label,
            "key_size": bits,
            "public_key_class": pub.object_class.name,
            "private_key_class": priv.object_class.name,
            "status": "SUCCESS",
        }


def generate_ec_keypair(lib, token_label, pin, key_label="agent-ec-p256"):
    """Generate an EC P-256 key pair on the HSM."""
    token = lib.get_token(token_label=token_label)
    with token.open(rw=True, user_pin=pin) as session:
        ecparams = session.create_domain_parameters(
            KeyType.EC,
            {pkcs11.Attribute.EC_PARAMS: pkcs11.util.ec.encode_named_curve_parameters("secp256r1")},
            local=True,
        )
        pub, priv = ecparams.generate_keypair(store=True, label=key_label)
        return {
            "action": "generate_ec_keypair",
            "key_label": key_label,
            "curve": "secp256r1 (P-256)",
            "public_key_class": pub.object_class.name,
            "private_key_class": priv.object_class.name,
            "status": "SUCCESS",
        }


def sign_and_verify(lib, token_label, pin, key_label, data=b"HSM test message"):
    """Sign data with an RSA private key and verify with the public key."""
    token = lib.get_token(token_label=token_label)
    with token.open(user_pin=pin) as session:
        priv_keys = list(session.get_objects({
            pkcs11.Attribute.CLASS: ObjectClass.PRIVATE_KEY,
            pkcs11.Attribute.LABEL: key_label,
        }))
        if not priv_keys:
            return {"error": f"Private key '{key_label}' not found"}
        priv = priv_keys[0]
        signature = priv.sign(data, mechanism=Mechanism.SHA256_RSA_PKCS)

        pub_keys = list(session.get_objects({
            pkcs11.Attribute.CLASS: ObjectClass.PUBLIC_KEY,
            pkcs11.Attribute.LABEL: key_label,
        }))
        if not pub_keys:
            return {"error": f"Public key '{key_label}' not found"}
        pub = pub_keys[0]
        try:
            pub.verify(data, signature, mechanism=Mechanism.SHA256_RSA_PKCS)
            verified = True
        except Exception:
            verified = False

        return {
            "action": "sign_and_verify",
            "key_label": key_label,
            "data_length": len(data),
            "signature_length": len(signature),
            "signature_hex": signature[:32].hex() + "...",
            "mechanism": "SHA256_RSA_PKCS",
            "verified": verified,
        }


def query_mechanisms(lib, token_label):
    """List all supported mechanisms for the token's slot."""
    token = lib.get_token(token_label=token_label)
    slot = token.slot
    mechs = []
    for m in slot.get_mechanisms():
        info = slot.get_mechanism_info(m)
        mechs.append({
            "mechanism": m.name,
            "min_key_size": info.min_key_size if hasattr(info, 'min_key_size') else None,
            "max_key_size": info.max_key_size if hasattr(info, 'max_key_size') else None,
        })
    return mechs


def full_audit(lib, token_label, pin):
    """Run comprehensive HSM compliance audit."""
    slots = enumerate_slots(lib)
    objects = list_objects(lib, token_label, pin)
    mechanisms = query_mechanisms(lib, token_label)
    rsa_keys = [o for o in objects if o.get("key_type") == "RSA"]
    ec_keys = [o for o in objects if o.get("key_type") == "EC"]
    weak_keys = [o for o in objects if o.get("key_type") == "RSA" and (o.get("key_length") or 2048) < 2048]
    fips_mechs = {"RSA_PKCS", "SHA256_RSA_PKCS", "SHA384_RSA_PKCS", "SHA512_RSA_PKCS",
                  "ECDSA", "ECDSA_SHA256", "AES_CBC", "AES_GCM", "SHA256", "SHA384", "SHA512"}
    supported_names = {m["mechanism"] for m in mechanisms}
    fips_coverage = len(fips_mechs & supported_names)
    return {
        "audit_type": "HSM PKCS#11 Compliance Audit",
        "timestamp": datetime.utcnow().isoformat(),
        "slots": slots,
        "stored_objects": len(objects),
        "objects": objects[:30],
        "rsa_key_count": len(rsa_keys),
        "ec_key_count": len(ec_keys),
        "weak_rsa_keys": len(weak_keys),
        "total_mechanisms": len(mechanisms),
        "fips_mechanism_coverage": f"{fips_coverage}/{len(fips_mechs)}",
        "compliance": "PASS" if not weak_keys and fips_coverage >= 6 else "REVIEW",
    }


def main():
    parser = argparse.ArgumentParser(description="HSM PKCS#11 Integration Agent")
    parser.add_argument("--lib", required=True, help="Path to PKCS#11 shared library")
    parser.add_argument("--token", required=True, help="Token label")
    parser.add_argument("--pin", required=True, help="User PIN")
    sub = parser.add_subparsers(dest="command")
    sub.add_parser("slots", help="Enumerate PKCS#11 slots and tokens")
    sub.add_parser("objects", help="List stored cryptographic objects")
    p_rsa = sub.add_parser("gen-rsa", help="Generate RSA key pair")
    p_rsa.add_argument("--label", default="agent-rsa-2048")
    p_rsa.add_argument("--bits", type=int, default=2048)
    p_ec = sub.add_parser("gen-ec", help="Generate EC P-256 key pair")
    p_ec.add_argument("--label", default="agent-ec-p256")
    p_sign = sub.add_parser("sign-verify", help="Sign and verify test data")
    p_sign.add_argument("--key-label", required=True)
    sub.add_parser("mechanisms", help="List supported mechanisms")
    sub.add_parser("full", help="Full HSM compliance audit")
    args = parser.parse_args()

    lib = load_library(args.lib)

    if args.command == "slots":
        result = enumerate_slots(lib)
    elif args.command == "objects":
        result = list_objects(lib, args.token, args.pin)
    elif args.command == "gen-rsa":
        result = generate_rsa_keypair(lib, args.token, args.pin, args.label, args.bits)
    elif args.command == "gen-ec":
        result = generate_ec_keypair(lib, args.token, args.pin, args.label)
    elif args.command == "sign-verify":
        result = sign_and_verify(lib, args.token, args.pin, args.key_label)
    elif args.command == "mechanisms":
        result = query_mechanisms(lib, args.token)
    elif args.command == "full":
        result = full_audit(lib, args.token, args.pin)
    else:
        parser.print_help()
        return
    print(json.dumps(result, indent=2, default=str))


if __name__ == "__main__":
    main()
Keep exploring