Cryptographic key access in the cloud
Gimme the Key
Cryptographic keys are usually stored on the hard disk, a smart card, a hardware security module (HSM), or a USB token. Applications that typically use such cryptographic keys are SSH, GnuPG, and crypto frameworks like OpenSSL, NSS, or GnuTLS.
Agent Forwarding
To begin, I'll take a look at SSH. If a user wants to log on to a remote computer by way of public key authentication, the user's public key must be available on the remote computer, usually provided with the help of the ssh-copy-id
application. Of course, the user's private key does not leave the local computer, but what happens if the user needs to move on from the remote computer, for example, because it is only a kind of jump host from which you can then log on to other systems in the back end?
Access to the user's private SSH key is required, then, on the remote computer, which is what ssh-agent
can deliver. Any private SSH key can be passed to this agent by ssh-add
, which then stores the key in memory. If access to one of these keys is necessary, the agent can be addressed through a socket file. The name of this file can be found in the SSH_AUTH_SOCK
variable:
# echo "$SSH_AUTH_SOCK" /tmp/ssh-j3OzPSWatFUl/agent.2395
Agent forwarding allows remote computers to access these agents. When establishing a connection over SSH, you can use the -A
option. Alternatively, the option can be stored in the SSH configuration file; the option here is ForwardAgent
, which is set to no
by default. If you activate forwarding by changing no
to yes
, all keys known by the SSH agent are displayed after logging in on a remote computer and calling ssh-add -l
. Now you can establish another SSH connection by public key-based authentication simply by accessing the key material of the SSH agent.
The situation is similar with forwarding a GnuPG agent socket so that access to the private GnuPG key also works from a remote computer. Here, however, you have to list explicitly the socket you want to forward in the ~/.ssh/config
SSH configuration file:
Host *.example.com RemoteForward /home/User/.gnupg/S.gpg-agent /home/User/.gnupg/S.gpg-agent.extra
The local ~/.gnupg/gpg-agent.conf
file also has to contain the name of this "special" socket:
extra-socket /home/User/.gnupg/S.gpg-agent.extra If a connection is then established to one of the hosts from the <I>example.com<I> domain, these hosts can access the private key from the local GnuPG keychain. However, on the remote system, the public key must already be part of the keychain.
PKCS#11 Forwarding
Far less well known is that remote access to the key material of public key cryptography standard (PKCS)#11 cards is also possible. These can be classic smart cards or the somewhat more modern USB variants, such as the YubiKey [1] or Nitrokey [2]. These cards are addressed through a PKCS#11 interface, for which you can find various drivers. The best known representatives are CoolKey [3] and OpenSC [4].
In the following example on a Fedora system, I show that accessing a smart card token via a forwarded PKCS#11 socket is possible from remote systems. I assume that a smart card already exists and has been provisioned. OpenSC should be used as the PKCS#11 driver. The reader I use is an OMNIKEY 3121.
Some preparations have to be made on the systems involved, such as installing the following packages from the Fedora repository:
# dnf install p11-kit p11-kit-server gnutls-utils libp11
Now, p11tool
from the gnutls-utils
package displays all tokens of the smart card:
# p11tool --list-tokens [...] Token 3: URL:pkcs11:model=PKCS%2315;manufacturer=EXAMPLE%20COM;serial=10104303570;token=Signature%20PIN%11%2233%20PKI%11Card%00 [...]
Such a token can now be "passed on" to any system. The p11-kit-server
package provides a module named p11-kit-client.so
that can be used to address the token via this socket. To create the socket, call p11-kit
with the URL of the token, given above, and the PKCS#11 driver:
# p11-kit server --provider /usr/lib64/pkcs11/opensc-pkcs11.so"pkcs11:model=PKCS%2315;manufacturer=EXAMPLE%20COM;serial=10104303570;token=Signature%20PIN%11%2233 PKI%11Card%00" P11_KIT_SERVER_ADDRESS=unix:path=/run/user/1000/p11-kit/pkcs11-21564 P11_KIT_SERVER_PID=21564
As can be seen from the variable P11_KIT_SERVER_ ADDRESS
, the socket file is located within the run-time directory of user /run/user//p11-kit
. Before forwarding the socket, two things must first be ensured:
- The run-time directory of the remote user has been identified.
- The subdirectory used by
p11-kit-client.so
has been created – preferably automatically.
You can identify the run-time directory of a user on a remote system with:
# ssh tscherf@tiffy systemd-path user-runtime /run/user/1000
Activating the system service p11-kit-client
on the remote system creates the required p11-kit
directory within the run-time directory for the user:
# systemctl --user enable --now p11-kit-client.service
The directory is now available:
# ls -ld /run/user/1000/p11-kit drwxr-xr-x. 2 tscherf tscherf 60 Mar 5 11:28 /run/user/1000/p11-kit
Finally, the PKCS#11 socket can be forwarded. The following example uses ssh
at the command line, but you could also add an appropriate entry to the SSH configuration file, ~/.ssh/config
:
# ssh -R /run/user/1000/p11-kit/pkcs11:/run/user/1000/p11-kit/pkcs11-21564 tscherf@tiffy
If no error occurred, the socket should now be available on the remote system:
# ll /run/user/1000/p11-kit/ total 0 srw------- 1 tscherf tscherf 0 Mar 5 11:36 pkcs11
Access to the smart card token should now also be possible. For access, the p11-kit-client.so
module mentioned earlier is required:
# p11tool --provider /usr/lib64/pkcs11/p11-kit-client.so--list-tokens Token 0: URL:pkcs11:model=PKCS%2315;manufacturer=EXAMPLE%20COM;serial=10104303570;token=Signature%20PIN%11%2233%20PKI%11Card%00 [...]
For access to the token from the different crypto frameworks to work, as well, the frameworks must of course know that the p11-kit-client.so
module is necessary. The following changes are required for OpenSSL:
# mkdir .config/pkcs11/modules/ # echo "module:/usr/lib64/pkcs11/p11-kit-client.so" >.config/pkcs11/modules/p11-kit-client.module
Then the token can also be accessed via OpenSSL and the engine_pkcs11
module. For the NSS framework, you need to integrate the p11-kit-client.so
module with the use of modutil
:
# modutil -dbdir /etc/pki/nssdb -add p11-kit-client -libfile /usr/lib64/pkcs11/p11-kit-client.so
A new entry is then displayed between the other modules:
# modutil -dbdir /etc/pki/nssdb -list [...] 3. p11-kit-client library name: /usr/lib64/pkcs11/p11-kit-client.so uri: pkcs11:library-manufacturer=OpenSC%20Project;library-description=OpenSC%20smartcard%20framework;library-version=0.17 slot: 1 slot attached status: loaded
Now you can simply pass the new PKCS#11 module with the ssh
command,
# ssh -I /usr/lib64/pkcs11/p11-kit-client.so tscherf@kermit
if you need the forwarded token to authenticate an SSH connection.
Conclusions
Sensitive key material should not be copied between systems. As shown in this article, far more elegant and secure methods exist for accessing keys remotely, such as a smart card.
Infos
- YubiKey: https://www.yubico.com/products/yubikey-hardware/
- Nitrokey: https://www.nitrokey.com
- CoolKey: https://access.redhat.com/articles/3034441
- OpenSC Git repository: https://github.com/OpenSC/OpenSC/wiki
Buy this article as PDF
(incl. VAT)