Use ssh-pkcs11-helper the Way OpenSSH Intends
Run ssh-pkcs11-helper on its own and it just sits there, because it is not a command line tool at all. It is the internal helper that ssh, ssh-agent and ssh-keygen launch behind the scenes whenever they need a key from a PKCS#11 token. This guide sticks to the commands that actually matter: confirming the helper is installed, pointing ssh -I at your provider library, and loading a token into an agent, all in about fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need the OpenSSH client package, a PKCS#11 provider library and access to a token if you want to test authentication. None of the examples below touch system files, agent configuration or token contents. Do not type a token PIN into a shared terminal or paste it into a script.
1. Check the installed package and helper
Start with ordinary, read-only checks. On this Ubuntu installation, the package is OpenSSH client 1:9.6p1-3ubuntu13.19, and the helper lives outside the normal command search path:
$ dpkg-query -W -f='${Package} ${Version}\n' openssh-client
openssh-client 1:9.6p1-3ubuntu13.19
$ dpkg -L openssh-client | grep '/ssh-pkcs11-helper$'
/usr/lib/openssh/ssh-pkcs11-helper
Checkpoint
The path and version can differ on another distribution. Use the output from your own machine in later troubleshooting rather than assuming /usr/lib/openssh is universal.
2. Do not launch the helper as a shell utility
The helper accepts only -v, which turns on diagnostic messages, and the manual says outright that it is not intended to be invoked directly. It speaks a private protocol expected by its OpenSSH callers, so running it by hand is not a useful token test: it will simply wait for protocol input that never comes.
Use the installed path only to confirm the package actually supplied it:
$ test -x /usr/lib/openssh/ssh-pkcs11-helper && echo 'helper is executable'
helper is executable
There is nothing to configure and no service to restart for this check. If the file is missing, reinstall or repair the package through your normal package-management process. Do not copy a helper binary in from another host.
3. Ask ssh to use a PKCS#11 provider
The user-facing entry point is the -I option on ssh. It selects the PKCS#11 shared library that ssh should use for authentication. Replace the placeholder with the provider path your token vendor or system administrator gave you:
$ PKCS11_PROVIDER='/path/to/vendor-pkcs11.so'
$ test -r "$PKCS11_PROVIDER" && echo 'provider is readable'
provider is readable
$ ssh -I "$PKCS11_PROVIDER" -vv [email protected]
That last command is a real connection attempt and may prompt for the token PIN or a host-key confirmation. Swap in a real test account and host for [email protected]. The -vv belongs to ssh; the helper gets extra verbosity automatically because its caller is in debug mode. Hit Ctrl-C if the destination is not the host you meant to test.
What you see next varies by provider and token, so look for PKCS#11 loading and key-offer lines in the debug output, then check the exit status of the whole attempt:
$ printf 'ssh exit status: %s\n' "$?"
ssh exit status: 0
Status 0 only means the SSH session ended cleanly, not that every key on the token was usable. A provider load error, an unavailable token and a rejected PIN are three different failures. Do not keep retrying a PIN blindly: tokens can lock themselves after too many bad attempts.
4. Use ssh-agent when several connections need the token
If an agent should hold the PKCS#11 keys for you, reach for ssh-add, not the helper. Its -s option adds keys straight from a PKCS#11 shared library:
$ eval "$(ssh-agent -s)"
$ ssh-add -s "$PKCS11_PROVIDER"
Enter passphrase for PKCS#11:
Card added: /path/to/vendor-pkcs11.so
$ ssh-add -L
Starting the agent changes your shell environment, and it may keep access to token-backed keys until it exits. Check the listed public keys before you trust them. If the provider prompts for a PIN, type it only into the trusted terminal you started it from.
When the temporary agent has done its job, remove its keys and stop it. Both commands below only affect the agent started in this shell, never the token itself:
$ ssh-add -D
All identities removed.
$ ssh-agent -k
Skip ssh-add -D on an agent shared with other sessions unless you genuinely mean to strip every identity from it. For a shared agent, track down the correct process and use the least disruptive cleanup you can.
5. Troubleshoot the boundary between caller and helper
- Helper missing. That usually means a damaged or incomplete OpenSSH client installation, not a token problem.
- Provider error. That concerns the shared library, not OpenSSH itself.
- Token or PIN error. That concerns the device or its access policy.
- Authentication failure. That can still come from the remote account, authorised keys or server configuration, even once the local side is fine.
Repeat the read-only checks first:
$ command -v ssh ssh-agent ssh-add
/usr/bin/ssh
/usr/bin/ssh-agent
/usr/bin/ssh-add
$ dpkg -L openssh-client | grep '/ssh-pkcs11-helper$'
/usr/lib/openssh/ssh-pkcs11-helper
Do not run the helper with -vvv directly. It supports at most three -v options, but only its caller decides when those diagnostics get passed through. Use ssh -vvv or the matching ssh-agent or ssh-keygen debug mode instead, and check logs for token identifiers or usernames before you share them with anyone.
Done means
- You confirmed the installed OpenSSH client version and the helper's path.
- You understand that
ssh-pkcs11-helperis an internal protocol helper, not an interactive utility. - You selected the provider with
ssh -Iorssh-add -s. - You tested it against an intended destination and inspected the caller's exit status.
- You avoided exposing a PIN and stopped a temporary agent once it was no longer needed.