'\" t .\" Title: ssh-tpm-agent .\" Author: [see the "AUTHOR(S)" section] .\" Generator: Asciidoctor 2.0.23 .\" Date: 2025-03-27 .\" Manual: ssh-tpm-agent manual .\" Source: ssh-tpm-agent .\" Language: English .\" .TH "SSH\-TPM\-AGENT" "1" "2025-03-27" "ssh\-tpm\-agent" "ssh\-tpm\-agent manual" .ie \n(.g .ds Aq \(aq .el .ds Aq ' .ss \n[.ss] 0 .nh .ad l .de URL \fI\\$2\fP <\\$1>\\$3 .. .als MTO URL .if \n[.g] \{\ . mso www.tmac . am URL . ad l . . . am MTO . ad l . . . LINKSTYLE blue R < > .\} .SH "NAME" ssh-tpm-agent \- ssh\-agent for TPM 2.0 keys .SH "SYNOPSIS" .sp \fBssh\-tpm\-agent\fP [\fIOPTIONS\fP] .sp \fBssh\-tpm\-agent\fP \fB\-\-print\-socket\fP .sp \fBssh\-tpm\-agent\fP \fB\-\-install\-user\-units\fP .SH "DESCRIPTION" .sp \fBssh\-tpm\-agent\fP is a program that created keys utilizing a Trusted Platform Module (TPM) to enable wrapped private keys for public key authentication. .SH "OPTIONS" .sp \fB\-l\fP \fIPATH\fP .RS 4 Path of the UNIX socket to open .sp Defaults to \fI$XDG_RUNTIME_DIR/ssh\-tpm\-agent.sock\fP. .RE .sp \fB\-A\fP \fIPATH\fP .RS 4 Fallback ssh\-agent sockets for additional key lookup. .RE .sp \fB\-\-print\-socket\fP .RS 4 Prints the socket to STDIN. .RE .sp \fB\-\-key\-dir\fP \fIPATH\fP .RS 4 Path of the directory to look for TPM sealed keys in. .sp Defaults to \fI~/.ssh\fP. .RE .sp \fB\-\-no\-load\fP .RS 4 Do not load TPM sealed keys from \fI~/.ssh\fP by default. .RE .sp \fB\-o, \-\-owner\-password\fP .RS 4 Ask for the owner password. .RE .sp \fB\-\-no\-cache\fP .RS 4 The agent will not cache key passwords. .RE .sp \fB\-\-hierarchy\fP \fIHIERARCHY\fP .RS 4 Preload hierarchy keys into the agent. .sp See \fBHierarchy Keys\fP for more information. .sp Available hierarchies: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} owner, o .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} endorsement, e .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} null, n .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} platform, p .RE .RE .sp \fB\-d\fP .RS 4 Enable debug logging. .RE .sp \fB\-\-install\-user\-units\fP .RS 4 Installs systemd system units and sshd configs for using ssh\-tpm\-agent as a hostkey agent. .RE .sp \fB\-\-swtpm\fP .RS 4 Stores keys inside a swtpm instance instead of the actual TPM. This is not a security feature and your keys are not stored securely. .sp Can also be enabled with the environment variable \fBSSH_TPM_AGENT_SWTPM\fP. .RE .SH "EXAMPLES" .SS "Normal agent usage" .sp \fBssh\-tpm\-agent\fP can be used as a dropin replacement to ssh\-agent and works the same way. .sp .if n .RS 4 .nf .fam C $ ssh\-tpm\-keygen # Add ~/.ssh/id_ecdsa.pub to your Github accounts $ ssh\-tpm\-agent & $ export SSH_AUTH_SOCK=$(ssh\-tpm\-agent \-\-print\-socket) $ ssh git@github.com .fam .fi .if n .RE .sp See \fBssh\-tpm\-keygen\fP(1) for keygen usage. .SS "Agent fallback support" .sp \fBssh\-tpm\-agent\fP supports fallback to different ssh\-agent. Agents can be added with the \fI\-A\fP switch. This will cause \fBssh\-tpm\-agent\fP to fan\-out to all available agents for keys. .sp This is practical if you have multiple keys from different agent implementations but want to rely on one socket. .sp .if n .RS 4 .nf .fam C # Start the usual ssh\-agent $ eval $(ssh\-agent) .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C # Create a strong RSA key $ ssh\-keygen \-t rsa \-b 4096 \-f id_rsa \-C ssh\-agent \&... The key fingerprint is: SHA256:zLSeyU/6NKHGEvyZLA866S1jGqwdwdAxRFff8Z2N1i0 ssh\-agent .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ ssh\-add id_rsa Identity added: id_rsa (ssh\-agent) .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C # Print looonnggg key $ ssh\-add \-L ssh\-rsa AAAAB3NzaC1yc[...]8TWynQ== ssh\-agent .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C # Create key on the TPM $ ssh\-tpm\-keygen \-C ssh\-tpm\-agent Generating a sealed public/private ecdsa key pair. Enter file in which to save the key (/home/user/.ssh/id_ecdsa): Enter passphrase (empty for no passphrase): Confirm passphrase: Your identification has been saved in /home/user/.ssh/id_ecdsa.tpm Your public key has been saved in /home/user/.ssh/id_ecdsa.pub The key fingerprint is: SHA256:PoQyuzOpEBLqT+xtP0dnvyBVL6UQTiQeCWN/EXIxPOo The key\*(Aqs randomart image is the color of television, tuned to a dead channel. .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C # Start ssh\-tpm\-agent with a proxy socket $ ssh\-tpm\-agent \-A "${SSH_AUTH_SOCK}" & .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ export SSH_AUTH_SOCK="$(ssh\-tpm\-agent \-\-print\-socket)" .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C # ssh\-tpm\-agent is proxying the keys from ssh\-agent $ ssh\-add \-L ssh\-rsa AAAAB3NzaC1yc[...]8TWynQ== ssh\-agent ecdsa\-sha2\-nistp256 AAAAE2VjZHNhLXNo[...]q4whro= ssh\-tpm\-agent .fam .fi .if n .RE .SS "Hostkeys usage" .sp \fBssh\-tpm\-agent\fP can also be used to serve host keys for an ssh server. \fBssh\-tpm\-hostkeys\fP has convenient flags to help install systemd configurations and services to the system. This will create a system socket for ssh\-tpm\-agent under \fI/var/tmp/ssh\-tpm\-agent.sock\fP. .sp .if n .RS 4 .nf .fam C $ sudo ssh\-tpm\-keygen \-A 2023/09/03 17:03:08 INFO Generating new ECDSA host key 2023/09/03 17:03:08 INFO Wrote /etc/ssh/ssh_tpm_host_ecdsa_key.tpm 2023/09/03 17:03:08 INFO Generating new RSA host key 2023/09/03 17:03:15 INFO Wrote /etc/ssh/ssh_tpm_host_rsa_key.tpm .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ sudo ssh\-tpm\-hostkeys \-\-install\-system\-units Installed /usr/lib/systemd/system/ssh\-tpm\-agent.service Installed /usr/lib/systemd/system/ssh\-tpm\-agent.socket Installed /usr/lib/systemd/system/ssh\-tpm\-genkeys.service Enable with: systemctl enable \-\-now ssh\-tpm\-agent.socket .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ sudo ssh\-tpm\-hostkeys \-\-install\-sshd\-config Installed /etc/ssh/sshd_config.d/10\-ssh\-tpm\-agent.conf Restart sshd: systemd restart sshd .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ systemctl enable \-\-now ssh\-tpm\-agent.socket $ systemd restart sshd .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ sudo ssh\-tpm\-hostkeys ecdsa\-sha2\-nistp256 AAAAE2V[...]YNwqWY0= root@localhost ssh\-rsa AAAAB3NzaC1ycA[...]N1Jg3fLQKSe7f root@localhost .fam .fi .if n .RE .sp .if n .RS 4 .nf .fam C $ ssh\-keyscan \-t ecdsa localhost # localhost:22 SSH\-2.0\-OpenSSH_9.4 localhost ecdsa\-sha2\-nistp256 AAAAE2V[...]YNwqWY0= .fam .fi .if n .RE .sp Alternatively one can omit the embedded install flags and just include a drop\-in configuration for sshd under /etc/ssh/sshd_config.d with the following content. .sp .if n .RS 4 .nf .fam C HostKeyAgent /var/tmp/ssh\-tpm\-agent.sock HostKey /etc/ssh/ssh_tpm_host_ecdsa_key.pub HostKey /etc/ssh/ssh_tpm_host_rsa_key.pub .fam .fi .if n .RE .SS "Hierarchy keys" .sp TPMs are capable of creating static keys utilizing the top\-level hierarchies. This enables the user to create keys that are available for the lifetime of the device, for the current owner of the device, or the current session of the device. These keys do not leave the TPM, like other keys created by \fBssh\-tpm\-keygen\fP, and can always be recreated. .sp These keys can be preloaded into \fBssh\-tpm\-agent\fP. .sp .if n .RS 4 .nf .fam C $ ssh\-tpm\-agent \-\-hierarchy owner & $ export SSH_AUTH_SOCK="$(ssh\-tpm\-agent \-\-print\-socket)" $ ssh\-add \-l 2048 SHA256:yt7A20tcRnzgaD2ATgAXSNWy9sP6wznysp3SkoK3Gj8 Owner hierarchy key (RSA) 256 SHA256:PmEsMeh/DwFP04iUaWLNeX4maMR6r1vfqw1BbbdFjIg Owner hierarchy key (ECDSA) .fam .fi .if n .RE .sp For usage with \f(CRsshd\fP the public part of these keys can be created by combining \fI\-A\fP with \fI\-\-hierarchy\fP. .sp .if n .RS 4 .nf .fam C $ ssh\-tpm\-keygen \-A \-\-hierarchy owner 2025/03/10 21:57:08 INFO Generating new hierarcy host key algorithm=RSA hierarchy=owner 2025/03/10 21:57:10 INFO Wrote public key filename=/etc/ssh/ssh_tpm_host_rsa_key.pub 2025/03/10 21:57:10 INFO Generating new hierarcy host key algorithm=ECDSA hierarchy=owner 2025/03/10 21:57:10 INFO Wrote public key filename=/etc/ssh/ssh_tpm_host_ecdsa_key.pub .fam .fi .if n .RE .sp These files can be used with \fIHostKey\fP as normal in \fIssh_config\fP. .sp The different key hierarchies have different properties and lifetimes. .sp \fIendorsement\fP hierarchy stores keys created for the lifetime of the device. This hierarchy should not change during the lifetime of the device. .sp \fIowner\fP hierarchy stores keys created for the device owner. These keys will be rotated when \fBtpm2_clear\fP(1) is issued on the platform, which should be done when the device gets a new owner. .sp \fInull\fP hierarchy stores keys created for the current session. The session should be a power cycle of the devices. .sp \fBNote:\fP This feature is \fIexperimental\fP. \fBssh\-tpm\-agent\fP keeps the TPM objects loaded while running. Some TPM devices run out of memory if you attempt to use the hierarchy keys with the usual keys created by \fBssh\-tpm\-keygen\fP. .SH "ENVIRONMENT" .sp \fBSSH_TPM_AUTH_SOCK\fP .RS 4 Identifies the path of a unix\-domain socket for communication with the agent. .sp Default to \fI/var/tmp/ssh\-tpm\-agent.sock\fP. .RE .sp \fBSSH_ASKPASS\fP .RS 4 If \fBssh\-tpm\-agent\fP, and other binaries, needs to read a password it will default to using the terminal if it can. If there is no terminal available it will fall back to calling the binary \fBSSH_ASKPASS\fP point at. .sp See \fBssh\fP(1) under \fBENVIRONMENT\fP for more information. .RE .sp \fBSSH_ASKPASS_REQUIRE\fP .RS 4 Allows control of the use of the askpass program. Valid values are: .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} \fBnever\fP ensures \fBssh\fP will never try to use the askpass program. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} \fBprefer\fP will prefer to use the askpass program. .RE .sp .RS 4 .ie n \{\ \h'-04'\(bu\h'+03'\c .\} .el \{\ . sp -1 . IP \(bu 2.3 .\} \fBforce\fP will ensure all passphrase inputs will be using the askpass program. .RE .sp See \fBssh\fP(1) under \fBENVIRONMENT\fP for more information. .RE .sp \fBSSH_TPM_AGENT_SWTPM\fP .RS 4 Specify if \fBssh\-tpm\-agent\fP should use the swtpm backend or not. Accepts any non\-empty value as true. .RE .sp \fBSSH_TPM_LANDLOCK\fP .RS 4 If set then \fBssh\-tpm\-agent\fP, and the other binaries, will enforce the landlock sandbox where applicable. .sp Disabled by default. .sp See \fBlandlock\fP(7) for more information. .RE .SH "FILES" .sp \fI~/ssh/id_rsa.tpm\fP, \fI~/ssh/id_ecdsa.tpm\fP .RS 4 Contains the ssh private keys used by \fBssh\-tpm\-agent\fP. They are TPM 2.0 TSS key files and securely wrapped by the TPM. They can be shared publicly as they can only be used by the TPM they where created on. However it is probably better to not do that. .RE .sp \fI~/ssh/id_rsa.pub\fP, \fI~/ssh/id_ecdsa.pub\fP .RS 4 Contains the ssh public keys. These can be shared publicly, and is the same format as the ones created by \fBssh\-keygen\fP(1). .RE .sp \fI/run/user/$UID/ssh\-tpm\-agent.sock\fP .RS 4 The default user \fBssh\-tpm\-agent\fP UNIX socket path. Used by induvidual users. .RE .sp \fI/var/tmp/ssh\-tpm\-agent.sock\fP .RS 4 The default system \fBssh\-tpm\-agent\fP UNIX socket path. Used for host keys and the system. .RE .SH "SEE ALSO" .sp \fBssh\-agent\fP(1), \fBssh\fP(1), \fBssh\-tpm\-keygen\fP(1), \fBssh\-keygen\fP(1) .SH "NOTES, STANDARDS AND OTHER" .sp .URL "https://www.hansenpartnership.com/draft\-bottomley\-tpm2\-keys.html" "ASN.1 Specification for TPM 2.0 Key Files" "" .sp .URL "https://linderud.dev/blog/store\-ssh\-keys\-inside\-the\-tpm\-ssh\-tpm\-agent/" "Store ssh keys inside the TPM: ssh\-tpm\-agent" ""