P11ex CLI Tool Documentation

View Source

The p11ex_cli is a command-line interface for interacting with PKCS#11 cryptographic tokens and modules. It provides a commands for managing slots, objects, and key generation on PKCS#11-compliant hardware security modules (HSMs).

Table of Contents

Installation

The CLI tool is part of the p11ex test applications. To build and run it:

cd test_apps/p11ex_cli
mix deps.get
mix compile

Configuration

Before using the CLI, you need to configure the PKCS#11 module and authentication credentials. This can be done through:

  1. Environment variables (recommended for automation)
  2. Command-line options (recommended for interactive use)

Required Configuration

  • PKCS#11 Module: Path to the PKCS#11 library (.so or.dylib file)
  • Token Label: Label of the token/slot to use
  • PIN: Authentication PIN for the token

Global Options

These options are available for all commands:

OptionShortTypeDefaultDescription
--verbose-vbooleanfalseOutput verbose information
--module-mstring-Path to PKCS#11 module file

Token Authentication Options

Available for commands that require token access:

OptionShortTypeDefaultDescription
--token-label-lstring-Token label to use
--pin-file-string-PIN file to use

p11ex_cli either reads the Token PIN from a file or the environment variable P11EX_PIN as shown below:

# from environment variable
env P11EX_PIN=1234 p11ex_cli list-objects --module /somewhere/libsofthsm2.so -l Token_0

# from file
echo -n 1234 > /ramdisk/.pin.txt
p11ex_cli list-objects --module /somewhere/libsofthsm2.so -l Token_0

Be careful with PIN files: p11ex_cli uses the complete file content including newline characters as the password.

Output Options

Available for commands that produce output:

OptionShortTypeDefaultDescription
--output-format-fstringtextOutput format (json, text)

Commands

list-slots

Lists available PKCS#11 slots and their associated tokens.

Usage:

p11ex list-slots [OPTIONS]

Options:

  • --with-token / -t (boolean, default: true): List only slots that contain a token

Example Output:

Slot 0:
  Description: SoftHSM slot 0
  Manufacturer: SoftHSM project
  Hardware Version: 2.0
  Firmware Version: 2.0
  Flags: [:removable_device, :hw_slot]
  Token Info:
    Label: MyToken
    Manufacturer: SoftHSM project
    Model: SoftHSM v2
    Serial Number: 1234567890
    Hardware Version: 2.0
    Firmware Version: 2.0
    Min. PIN Length: 4
    Max. PIN Length: 256
    Max. Session Count: 1
    Session Count: 0
    Max. R/W Session Count: 1
    Session R/W Count: 0
    Total Private Memory: 65536
    Free Private Memory: 65536
    Total Public Memory: 65536
    Free Public Memory: 65536
    UTC Time: 20240101120000Z
    Flags: [:rng, :login_required, :user_pin_initialized]

list-objects

Lists cryptographic objects (keys, certificates) stored in a token.

Usage:

p11ex list-objects [OPTIONS] <object_type>

Arguments:

  • object_type (required): Type of objects to list
    • seck: Secret keys
    • prvk: Private keys
    • pubk: Public keys

Options:

  • All global and token authentication options
  • --output-format / -f: Output format (json, text)

Example Usage:

# List all secret keys in text format
p11ex list-objects -m /usr/lib/softhsm/libsofthsm2.so -l MyToken -f text seck

# List all private keys in JSON format
p11ex list-objects -m /usr/lib/softhsm/libsofthsm2.so -l MyToken -f json prvk

Example Output (text format):

Object handle: 1234567890
  :cka_class: :cko_secret_key
  :cka_key_type: :ck_aes
  :cka_label: "MyAESKey"
  :cka_id: 48656C6C6F576F726C64
  :cka_encrypt: true
  :cka_decrypt: true
  :cka_token: true

Example Output (JSON format):

{
  "handle": 1234567890,
  "attribs": [
    {"attrib": ":cka_class", "value": ":cko_secret_key"},
    {"attrib": ":cka_key_type", "value": ":ck_aes"},
    {"attrib": ":cka_label", "value": "MyAESKey"},
    {"attrib": ":cka_id", "value": "48656C6C6F576F726C64"},
    {"attrib": ":cka_encrypt", "value": "true"},
    {"attrib": ":cka_decrypt", "value": "true"},
    {"attrib": ":cka_token", "value": "true"}
  ]
}

key-gen-aes

Generates new AES key in the token.

Usage:

p11ex key-gen-aes [OPTIONS] <key_label> <key_length>

Arguments:

  • key_label (required): Label for the generated key
  • key_length (required): Key length in bits

Options:

  • All global and token authentication options
  • --key-id: Key ID for the key (hex string, random if not provided)
  • --encrypt: Allow key for encryption (default: true)
  • --decrypt: Allow key for decryption (default: true)
  • --sign: Allow key for signing (default: false)
  • --verify: Allow key for verification (default: false)
  • --wrap: Allow key for wrapping (default: false)
  • --unwrap: Allow key for unwrapping (default: false)
  • --derive: Allow key for deriving (default: false)
  • --extract: Allow key for extracting (default: false)

Example Usage:

# Generate a 256-bit AES key for encryption/decryption
p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken "MyAESKey" 256

# Generate a key with specific ID and signing capabilities
p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --key-id 48656C6C6F576F726C64 \
  --sign --verify \
  "MySigningKey" 256

Example Output:

Generated new key ID: 48656c6c6f576f726c64
Key generated. Object handle: 1234567890abcdef

key-wrap

Wraps (encrypts) a cryptographic key using another key (the wrapping key). The wrapped key is exported as encrypted bytes that can be stored externally or transferred to another token.

Usage:

p11ex key-wrap [OPTIONS] <mechanism> <wrapping_key_ref> <key_ref> <output_file>

Arguments:

  • mechanism (required): Wrapping mechanism to use
    • ckm_aes_key_wrap_pad: AES key wrapping with padding
    • ckm_rsa_pkcs: RSA PKCS#1 v1.5 encryption
    • ckm_rsa_pkcs_oaep: RSA PKCS#1 OAEP encryption
  • wrapping_key_ref (required): Reference to the wrapping key
    • Format: label:name, id:hexstring, or handle:number
    • The key must have CKA_WRAP attribute set to true
  • key_ref (required): Reference to the key to wrap
    • Format: label:name, id:hexstring, or handle:number
    • The key must have CKA_EXTRACTABLE attribute set to true
  • output_file (required): Path where wrapped key will be written

Options:

  • All global and token authentication options
  • --output-format / -f: Output format for wrapped key (default: hex)
    • binary: Raw binary format
    • hex: Hexadecimal encoding (lowercase)
    • base64: Base64 encoding

Example Usage:

# Wrap an AES key using another AES key, output as hex
p11ex key-wrap -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  ckm_aes_key_wrap_pad \
  label:MyWrappingKey \
  label:MyKeyToWrap \
  wrapped_key.hex

# Wrap a private key using RSA public key, output as base64
p11ex key-wrap -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --output-format base64 \
  ckm_rsa_pkcs_oaep \
  label:MyRSAPublicKey \
  id:48656c6c6f \
  wrapped_key.b64

Example Output:

Wrapped key written to: wrapped_key.hex

Notes:

  • The wrapping key must be marked with CKA_WRAP=true during key generation
  • The key to wrap must be marked with CKA_EXTRACTABLE=true during key generation
  • Supported key combinations depend on the token implementation
  • Common use cases:
    • Wrapping AES keys with AES keys
    • Wrapping RSA/EC private keys with AES keys
    • Wrapping AES/RSA keys with RSA public keys

key-unwrap

Unwraps (decrypts) a previously wrapped key and imports it into the token as a new key object.

Usage:

p11ex key-unwrap [OPTIONS] <mechanism> <unwrapping_key_ref> <input_file>

Arguments:

  • mechanism (required): Unwrapping mechanism (must match the mechanism used for wrapping)
    • ckm_aes_key_wrap_pad: AES key unwrapping with padding
    • ckm_rsa_pkcs: RSA PKCS#1 v1.5 decryption
    • ckm_rsa_pkcs_oaep: RSA PKCS#1 OAEP decryption
  • unwrapping_key_ref (required): Reference to the unwrapping key
    • Format: label:name, id:hexstring, or handle:number
    • The key must have CKA_UNWRAP attribute set to true
  • input_file (required): Path to file containing wrapped key bytes

Options:

  • All global and token authentication options
  • --input-format / -f: Input format for wrapped key (default: hex)
    • binary: Raw binary format
    • hex: Hexadecimal encoding
    • base64: Base64 encoding
  • --key-label (required): Label for the unwrapped key
  • --key-id: Key ID for the unwrapped key (hex string, random if not provided)
  • --key-type (required): Type of key being unwrapped
    • aes: AES secret key
    • rsa: RSA key
    • ec: Elliptic curve key
  • --key-class (required): Object class of key being unwrapped
    • seck: Secret key
    • prvk: Private key
    • pubk: Public key
  • --encrypt: Allow key for encryption (default: false)
  • --decrypt: Allow key for decryption (default: false)
  • --sign: Allow key for signing (default: false)
  • --verify: Allow key for verification (default: false)
  • --wrap: Allow key for wrapping (default: false)
  • --unwrap: Allow key for unwrapping (default: false)
  • --derive: Allow key for key derivation (default: false)
  • --extract: Mark key as extractable (default: false)
  • --token: Store key on token (persistent) (default: true)

Example Usage:

# Unwrap an AES key from hex file
p11ex key-unwrap -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --key-label "ImportedAESKey" \
  --key-type aes \
  --key-class seck \
  --encrypt --decrypt \
  ckm_aes_key_wrap_pad \
  label:MyWrappingKey \
  wrapped_key.hex

# Unwrap an RSA private key from base64 file with specific attributes
p11ex key-unwrap -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --input-format base64 \
  --key-label "ImportedRSAKey" \
  --key-id 48656c6c6f \
  --key-type rsa \
  --key-class prvk \
  --sign --decrypt \
  ckm_rsa_pkcs_oaep \
  label:MyRSAPrivateKey \
  wrapped_key.b64

Example Output:

Generated new key ID: a3f2c8d4e5b6f7a8
Key unwrapped successfully
Object handle: 1a2b3c4d5e6f7890

Notes:

  • The unwrapping key must be marked with CKA_UNWRAP=true during key generation
  • The unwrapping mechanism must match the wrapping mechanism used
  • You must specify the correct key type and class for the unwrapped key
  • Key attributes (encrypt, decrypt, sign, etc.) can be set during unwrap
  • The unwrapped key is a completely new key object with a new handle

kcv-gen

Generates a Key Check Value (KCV) for one or more secret keys. The KCV is computed by encrypting a block of zeros using AES-ECB mode with the key and taking the first 3 bytes of the result. This provides a quick fingerprint for verifying key integrity.

Usage:

p11ex kcv-gen [OPTIONS] <key_ref...>

Arguments:

  • key_ref (required, repeatable): Reference(s) to the key(s)
    • Format: label:name, id:hexstring, or handle:number
    • The key must be a secret key (CKO_SECRET_KEY)
    • The key must have CKA_ENCRYPT capability set to true
    • Multiple keys can be specified for batch processing

Options:

  • All global and token authentication options
  • --output-format / -f: Output format (json, text)

Example Usage:

# Generate KCV for a single key by label
p11ex kcv-gen -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:MyAESKey

# Generate KCVs for multiple keys
p11ex kcv-gen -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:MyAESKey label:AnotherKey id:48656c6c6f

# Generate KCV with JSON output
p11ex kcv-gen -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  -f json label:MyAESKey

Example Output (text format):

Key reference: label:MyAESKey
  Handle: 1234567890
  KCV: 0x48656c

Key reference: label:AnotherKey
  Handle: 9876543210
  KCV: 0xa3f2c8

Example Output (JSON format):

[
  {
    "ref": "label:MyAESKey",
    "result": {
      "handle": 1234567890,
      "status": "ok",
      "kcv": "0x48656c"
    }
  },
  {
    "ref": "label:AnotherKey",
    "result": {
      "handle": 9876543210,
      "status": "ok",
      "kcv": "0xa3f2c8"
    }
  }
]

Notes:

  • The KCV algorithm uses AES-ECB mode to encrypt a zero-filled block and takes the first 3 bytes
  • KCVs provide a quick way to verify that a key was correctly loaded or transferred
  • Only secret keys can be used for KCV generation
  • The key must have encryption capability enabled
  • Error status will be shown in the output if key lookup or encryption fails

bench-aes-encrypt-block

Benchmarks AES-CBC encryption performance across various block sizes using parallel sessions. This command is useful for performance testing and capacity planning of PKCS#11 tokens and HSMs.

Usage:

p11ex bench-aes-encrypt-block [OPTIONS] <key_ref>

Arguments:

  • key_ref (required): Reference to the secret key to use for encryption
    • Format: label:name, id:hexstring, or handle:number
    • The key must be a secret key (CKO_SECRET_KEY)
    • The key must have CKA_ENCRYPT capability set to true

Options:

  • All global and token authentication options
  • --number-sessions (integer, default: 1): Number of parallel sessions to use for benchmarking
  • --rounds (integer): Number of encryption rounds per block size (overrides config default)

Configuration: The benchmark uses configuration from config.exs:

  • block_sizes: List of block sizes to test (default: [32, 256, 1024, 8192, 65536, 262144] bytes)
  • rounds_per_block: Default number of rounds per block size (default: 10)

Example Usage:

# Single session benchmark with default settings
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:MyAESKey

# Multi-session benchmark with 4 parallel sessions
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --number-sessions 4 \
  label:MyAESKey

# Custom number of rounds per block size
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --rounds 20 \
  label:MyAESKey

Example Output:

{
  "measurements": [
    {
      "block_size_bytes": 32,
      "status": "success",
      "average_duration_ms": 0.234,
      "rounds": 10
    },
    {
      "block_size_bytes": 256,
      "status": "success",
      "average_duration_ms": 0.456,
      "rounds": 10
    },
    {
      "block_size_bytes": 1024,
      "status": "success",
      "average_duration_ms": 1.234,
      "rounds": 10
    },
    {
      "block_size_bytes": 8192,
      "status": "success",
      "average_duration_ms": 8.765,
      "rounds": 10
    },
    {
      "block_size_bytes": 65536,
      "status": "success",
      "average_duration_ms": 65.432,
      "rounds": 10
    },
    {
      "block_size_bytes": 262144,
      "status": "success",
      "average_duration_ms": 254.321,
      "rounds": 10
    }
  ],
  "config": {
    "key_ref": "label:MyAESKey",
    "number_sessions": 1,
    "iv": "0x48656c6c6f576f726c6431323456",
    "block_sizes": [32, 256, 1024, 8192, 65536, 262144],
    "rounds_per_block": 10
  }
}

Notes:

  • The benchmark uses AES-CBC mode with a random IV generated at the start and reused for all measurements
  • Each block size is encrypted multiple times (based on rounds or configuration), and the average duration is reported
  • Parallel execution distributes the encryption workload across multiple sessions for better throughput testing
  • Measurements include timing information in milliseconds for each block size
  • If some measurements fail, the status will be "partial" or "error" with error details included
  • The IV used for all encryptions is included in the output for reference
  • This command is useful for:
    • Performance testing of PKCS#11 tokens
    • Capacity planning and throughput estimation
    • Comparing encryption performance across different HSMs
    • Stress testing with multiple parallel sessions

help

Shows help information for commands.

Usage:

p11ex help [subcommand]

Arguments:

  • subcommand (optional): Specific command to get help for

Examples:

# Show general usage
p11ex help

# Show help for specific command
p11ex help list-objects
p11ex help key-gen-aes

Usage Examples

Basic Workflow

  1. List available slots:

    p11ex list-slots -m /usr/lib/softhsm/libsofthsm2.so
    
  2. List objects in a token:

    p11ex list-objects -m /usr/lib/softhsm/libsofthsm2.so -l MyToken seck
    
  3. Generate a new key:

    p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken "NewKey" 256
    

Using Environment Variables

For automation and scripts, use environment variables:

export P11EX_MODULE=/usr/lib/softhsm/libsofthsm2.so
export P11EX_PIN=1234

p11ex list-slots
p11ex list-objects -l MyToken seck

Using PIN Files

For enhanced security, store PINs in files:

echo "1234" > /secure/path/pin.txt
chmod 600 /secure/path/pin.txt

p11ex list-objects -m /usr/lib/softhsm/libsofthsm2.so \
  -l MyToken \
  --pin-file /secure/path/pin.txt \
  seck

JSON Output for Scripting

Use JSON output format for programmatic processing:

p11ex list-objects -m /usr/lib/softhsm/libsofthsm2.so \
  -l MyToken \
  -f json \
  seck | jq '.[] | select(.attribs[] | select(.attrib == ":cka_label") | .value == "MyKey")'

Key Wrapping and Unwrapping Workflow

This example demonstrates how to wrap a key for export and then unwrap it back into the token:

# Step 1: Generate a wrapping key with wrap/unwrap capabilities
p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --wrap --unwrap \
  "MyWrappingKey" 256

# Step 2: Generate a key to be wrapped (must be extractable)
p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --encrypt --decrypt --extract \
  "MySecretKey" 256

# Step 3: Wrap the key for export (outputs to hex file by default)
p11ex key-wrap -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  ckm_aes_key_wrap_pad \
  label:MyWrappingKey \
  label:MySecretKey \
  exported_key.hex

# Step 4: The wrapped key can now be stored externally or transferred
# Later, unwrap it back into the token with new attributes
p11ex key-unwrap -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --key-label "ImportedSecretKey" \
  --key-type aes \
  --key-class seck \
  --encrypt --decrypt \
  ckm_aes_key_wrap_pad \
  label:MyWrappingKey \
  exported_key.hex

Key Check Value (KCV) Workflow

This example demonstrates how to generate KCVs to verify key integrity:

# Step 1: Generate a key for testing
p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --encrypt --decrypt \
  "MyTestKey" 256

# Step 2: Generate the KCV for verification
# Save the KCV to a file for later comparison
p11ex kcv-gen -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:MyTestKey > kcv.txt

# Step 3: Generate KCVs for multiple keys at once
p11ex kcv-gen -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:MyTestKey label:AnotherKey label:ThirdKey

# Step 4: Use JSON output to programmatically verify keys
p11ex kcv-gen -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  -f json label:MyTestKey | jq '.[] | select(.result.status == "ok")'

Performance Benchmarking Workflow

This example demonstrates how to benchmark AES encryption performance:

# Step 1: Generate a key for benchmarking
p11ex key-gen-aes -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --encrypt --decrypt \
  "BenchKey" 256

# Step 2: Run single-session benchmark
# This measures encryption performance with sequential operations
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:BenchKey

# Step 3: Run parallel benchmark with 4 sessions
# This measures throughput with concurrent encryption operations
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --number-sessions 4 \
  label:BenchKey

# Step 4: Run extended benchmark with more rounds for better statistics
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  --rounds 50 \
  label:BenchKey

# Step 5: Process results programmatically
# Extract and analyze performance metrics
p11ex bench-aes-encrypt-block -m /usr/lib/softhsm/libsofthsm2.so -l MyToken \
  label:BenchKey | jq '.measurements[] | {size: .block_size_bytes, duration_ms: .average_duration_ms}'

Environment Variables

VariableDescriptionRequired
P11EX_MODULEPath to PKCS#11 module fileYes*
P11EX_PINAuthentication PIN for tokenYes*

*Required if not specified via command-line options

Error Handling

The CLI provides detailed error messages for common issues:

  • Module loading errors: Invalid module path or incompatible library
  • Authentication errors: Invalid PIN or token access issues
  • Token errors: Token not found, insufficient permissions
  • Object errors: Invalid object types, object not found
  • Validation errors: Invalid arguments or options

Exit Codes:

  • 0: Success
  • 1: General error (module loading, authentication, etc.)
  • 2: Validation error (invalid arguments, options, etc.)