p11ex logo

p11ex --- PKCS#11 bindings for Elixir

p11ex is an Elixir library that provides access to the PKCS#11 interface for cryptographic tokens such as Hardware Security Modules and smartcards. The library exposes most PKCS#11 functionality to Elixir, though it is not yet feature complete. Available functions include:

  • C_GetSlotList: List tokens
  • C_GetTokenInfo: Retrieve information about a token
  • C_OpenSession: Open a new PKCS#11 session
  • C_CloseSession: Close a PKCS#11 session
  • C_CloseAllSession: Close all open sessions for a token
  • C_GetSessionInfo: Retrieve status information about a session
  • C_Login: Authenticate an open session
  • C_Logout: Deauthenticate an open session
  • C_GenerateKey: Generate a symmetric key
  • C_FindObjects: Search for objects stored in the token
  • C_GetAttributeValue: Retrieve attributes of an object
  • C_EncryptInit, C_Encrypt, C_EncryptUpdate, and C_EncryptFinal: Encryption in chunks and as a complete block
  • C_DecryptInit, C_Decrypt, C_DecryptUpdate, and C_DecryptFinal: Decryption in chunks and as a complete block
  • C_GenerateRandom: Generate random bytes using the token
  • C_DestroyObject: Delete objects in the token or session
  • C_GetMechanismList: List cryptographic mechanisms supported by token
  • C_GetMechanismInfo: Retrieve information about a mechanism
  • C_SignInit, C_Sign, C_SignUpdate, C_SignFinal: Sign data in chunks and as a complete block
  • C_VerifyInit, C_Verify: Verify a signature
  • C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal: Compute a hash digest in the token
  • C_GenKeyPair: Generate asymmetric key pair
  • C_WrapKey: Encrypt an extractable key and make it exportable
  • C_UnwrapKey: Decrypt an exported key into the token

Some PKCS#11 functions require mechanism parameters as arguments. Common parameter types are supported and documented in the Elixir documentation.

The implementation is automatically tested with SoftHSM on Linux (AMD64 and ARM64) and macOS (ARM64). Additional tests are available for the Yubikey PKCS#11 module, though these do not run automatically as part of the build.

Build Prerequisite: PKCS#11 Headers

The NIF build expects PKCS#11 C headers in c_src/. In CI these files are downloaded before compilation; for local builds, do the same manually:

cd c_src
curl -fL -O https://raw.githubusercontent.com/oasis-tcs/pkcs11/master/published/3-01/pkcs11.h
curl -fL -O https://raw.githubusercontent.com/oasis-tcs/pkcs11/master/published/3-01/pkcs11t.h
curl -fL -O https://raw.githubusercontent.com/oasis-tcs/pkcs11/master/published/3-01/pkcs11f.h
cd ..
mix deps.compile p11ex --force

Do not commit downloaded header files accidentally if your workflow stores them outside the source tree.

p11ex_cli --- CLI program to use PKCS#11 tokens

The project also includes a CLI program named p11ex_cli for working with cryptographic tokens. This program provides access to key p11ex functions.

Available Commands

  • slot-list: List available PKCS#11 slots/tokens
  • object-list: List objects (keys, certificates) on a token
  • key-gen-aes: Generate AES symmetric keys
  • export-pubk: Export public keys (RSA, EC, EdDSA)
  • sign: Sign data with RSA, EC, or EdDSA algorithms
  • key-wrap / key-unwrap: Wrap/unwrap keys for secure transport
  • kcv-gen: Compute Key Check Value (fingerprint) of secret keys
  • bench-aes-encrypt-block: Benchmark AES encryption performance

For detailed documentation on each command, run p11ex_cli <command> --help.

EdDSA Support

p11ex_cli supports EdDSA signatures (Ed25519, Ed448). Use the sign command with the appropriate mechanism:

p11ex_cli sign --mechanism Ed25519 --key-label my-ed25519-key --data-file input.txt --signature-file output.sig

Release Process

The release process is semi-automated using three GitHub Actions workflows. Before creating a release, ensure the CHANGELOG.md is updated with the changes to be released.

Prerequisites

  • Commits must follow Conventional Commits format
  • CHANGELOG.md should have an "Unreleased" section with pending changes
  • Required secrets must be configured in repository settings (see RELEASE.md for details)

Three Workflows Involved

The release process uses three separate workflows that should be triggered in order:

1. Release Library to Hex.pm (.github/workflows/release-lib-hexpm.yml)

This workflow:

  • Calculates the next version based on conventional commits
  • Updates mix.exs with the new version
  • Creates a git tag (e.g., v0.4.0)
  • Builds documentation and Hex package
  • Performs a dry-run build test to verify the package structure (Makefile, required files)
  • Publishes the package to Hex.pm
  • Triggered manually via Actions UI

Run this first - it creates the git tag needed by the other workflows. The dry-run test ensures the package can be compiled correctly before publishing.

2. Release CLI Binaries (.github/workflows/release-cli.yml)

This workflow:

  • Builds p11ex_cli binaries for Linux (amd64, arm64) and macOS (arm64)
  • Creates tar.gz archives of the binaries
  • Generates SHA256 checksums
  • Uploads release artifacts
  • Requires a version tag as input (must match a git tag from step 1)
  • Triggered manually via Actions UI

Run this second - after the git tag exists from step 1.

3. Create Codeberg Release (.github/workflows/release-lib-codeberg.yml)

This workflow:

  • Creates a release on Codeberg (Forgejo) using the Forgejo API
  • Uses the git tag created in step 1
  • Generates release notes referencing CHANGELOG.md
  • Provides installation instructions in the release description
  • Requires tag name and version as inputs
  • Triggered manually via Actions UI

Run this third - after the git tag exists from step 1.

Release Steps

  1. Update CHANGELOG.md

    • Move items from "Unreleased" section to a new version section
    • Follow the Keep a Changelog format
    • Commit and push the changelog update
  2. Trigger Library Release

    • Go to Actions → "Release p11ex library to Hex.pm"
    • Click "Run workflow"
    • The workflow will calculate version, update files, and publish
  3. Trigger CLI Release

    • Wait for library release to complete and tag to be created
    • Go to Actions → "Release p11ex-cli binaries"
    • Click "Run workflow"
    • Enter the version tag (e.g., 0.4.0)
    • Download the release artifacts from the workflow run
  4. Create GitHub/Codeberg Release (if applicable)

    • Create a release on the repository using the git tag
    • Upload the CLI binaries from the workflow artifacts
    • Add release notes from CHANGELOG.md

For detailed information about the release process, troubleshooting, and manual release procedures, see RELEASE.md.

Quick Reference

WorkflowTriggerInputOutput
release-lib-hexpm.ymlManualNoneHex.pm package, git tag
release-cli.ymlManualVersion tagCLI binaries, checksums
release-lib-codeberg.ymlManualTag name, versionCodeberg release

Note: The Docker workflows (.github/workflows/docker-base.yml and .github/workflows/docker-build.yml) build and maintain the test infrastructure images used by the release workflows. They run automatically on a schedule (twice weekly) or can be triggered manually if needed.