Skip to content

pfmooney/pivy

Repository files navigation

piv-agent

About

This is an implementation of a simple PIV client for desktop Linux and OSX with minimal dependencies. It contains a piv-tool binary which can conduct basic operations using PIV cards, and the piv-agent, which implements the SSH agent protocol as a drop-in replacement for the OpenSSH ssh-agent command (except that the keys it contains are always on a PIV card).

Using the agent

Using the PIV agent is identical to running the normal ssh-agent command, with the exception that piv-agent requires a -g argument specifying the GUID of the PIV card to attach to.

For example, the GUID of my PIV card is 995E171383029CDA0D9CDBDBAD580813 (if you don’t know your GUID, the piv-tool command can display it). I can use the following command to start the piv-agent against my card:

$ piv-agent -g 995E171383029CDA0D9CDBDBAD580813 bash
$ ssh-add -l
256 SHA256:PJ6ucGKUqlQhiJdArDaF65+AVImg8SVq77vL6nVE/ME PIV_slot_9C /CN=Digital Signature (ECDSA)
256 SHA256:U86TVxP/gxVk4CQibIWit3Q+/5i4aZuXa2NALIahjww PIV_slot_9E /CN=Card Authentication (ECDSA)

I can now use the 9E Card Authentication key with ssh or any other tools that use speak the OpenSSH agent protocol (e.g. the Joyent manta and triton tools). If I try to use the 9C Digital Signature key right now though, I will get an error like this:

$ ssh user@host
sign_and_send_pubkey: signing failed: agent refused operation
user@host: Permission denied (publickey).

To use the 9C key I will have to give my PIV PIN to the agent using the ssh-add -X command, so that it can unlock the card to use the key.

$ ssh-add -X
Enter lock password:
Agent unlocked.
$ ssh user@host
Last login: Wed Mar 28 21:56:11 2018 from laptop
[user@host ~]$

You can make the agent forget the PIN by using the ssh-add -x command to "lock" it. You can supply any password you like (including an empty string) for the "lock" command. The command ssh-add -D can also be used, and will not prompt for a password (useful from scripts).

Note that it’s perfectly fine to leave the piv-agent running and remove your PIV card: the agent will just return errors on any attempt to use it until you insert your card again. You can even start the agent without the PIV card present at all.

One useful way to use the piv-agent is to set up a systemd unit file for it to run whenever you log in, and adjust your shell profile to use it as your normal SSH agent. Then your PIV keys are automatically ready for use in any shell.

Installing on Linux

On Linux you will need to have a compiler and basic build tools and headers installed, as well as the libraries pcsclite and libbsd (and their -dev packages if your distro does those). Some musl based distros will also require installing libedit.

Then, clone this repository and use make to build the binaries:

$ git clone https://github.com/arekinath/piv-agent
$ cd piv-agent
$ make
$ ./piv-tool list
      card: 995E1713
    device: Yubico Yubikey NEO OTP+U2F+CCID 02 00
     chuid: ok
      guid: 995E171383029CDA0D9CDBDBAD580813
     owner: 00000000000000000000000000000000
    expiry: 2030-01-01
     slots:
           ID   TYPE    BITS  CERTIFICATE
           9c   ECDSA   256   /CN=Digital Signature
           9e   ECDSA   256   /CN=Card Authentication

You can run make install to install the agent into /opt/piv-agent and set up a user systemd service to start it automatically at login. The make install command will also print out lines to add to your .profile or .bashrc to make sure the agent is automatically available in all your shells (while still preferring a forwarded SSH agent if you SSH into your machine later).

$ make install
Enter a GUID to use for piv-agent: 995E171383029CDA0D9CDBDBAD580813

sudo install -o root -g wheel -m 0755 -d /opt/piv-agent/bin
Password:
sudo install -o root -g wheel -m 0755 piv-agent piv-tool  /opt/piv-agent/bin
install -d /home/alex/.config/systemd/user
install .dist/piv-agent.service /home/alex/.config/systemd/user
systemctl --user enable piv-agent.service
systemctl --user start piv-agent.service

Add the following lines to your .profile or .bashrc:
  export PATH=/opt/piv-agent/bin:$PATH
  if [[ ! -e "$SSH_AUTH_SOCK" || "$SSH_AUTH_SOCK" == *"/keyring/"* ]]; then
    export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
  fi

Installing on OSX

Compiling on OSX is even easier. Rather than depend on homebrew or MacPorts or another similar system, we simply build libressl-portable in a subdirectory and statically link the binaries against it. The Makefile in this repository will handle it all for you.

Note there is no need to install PCSClite or OpenSC or any of the related tools or libraries on OSX — the PCSC framework built into the operating system itself works fine for piv-agent.

The commands you will need to run are as follows:

## Clone the piv-agent repository
$ git clone https://github.com/arekinath/piv-agent
$ cd piv-agent

## Build libressl and then piv-agent
$ make -j4
$ ./piv-tool list
      card: 995E1713
    device: Yubico Yubikey NEO OTP+U2F+CCID 02 00
     chuid: ok
      guid: 995E171383029CDA0D9CDBDBAD580813
     owner: 00000000000000000000000000000000
    expiry: 2030-01-01
     slots:
           ID   TYPE    BITS  CERTIFICATE
           9c   ECDSA   256   /CN=Digital Signature
           9e   ECDSA   256   /CN=Card Authentication

## Install in /opt/piv-agent and add a launchd service for the agent
$ make install
Enter a GUID to use for piv-agent: 995E171383029CDA0D9CDBDBAD580813

sudo install -o root -g wheel -m 0755 -d /opt/piv-agent/bin
Password:
sudo install -o root -g wheel -m 0755 piv-agent piv-tool  /opt/piv-agent/bin
install .dist/net.cooperi.piv-agent.plist /Users/alex/Library/LaunchAgents
launchctl load /Users/alex/Library/LaunchAgents/net.cooperi.piv-agent.plist
/Users/alex/Library/LaunchAgents/net.cooperi.piv-agent.plist: service already loaded
launchctl start net.cooperi.piv-agent

Add the following lines to your .profile or .bashrc:
  export PATH=/opt/piv-agent/bin:$PATH
  if [[ ! -e "$SSH_AUTH_SOCK" || "$SSH_AUTH_SOCK" == *"launchd"* ]]; then
    source $HOME/.ssh/agent.env >/dev/null
  fi

There is one known issue on OSX currently: the PCSC framework does not work after calling fork(), which forces the piv-agent code to not be able to run in the background (this means using piv-agent bash to start a shell doesn’t work, for example). The best way to use it on OSX is set up as a launchd service.

Like on Linux, there is a make install target that will set up a launchd service for the piv-agent for you and advise you on what to add to .profile to make it available in all new shells.

About

PIV SSH agent

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 97.8%
  • Makefile 1.1%
  • C++ 1.1%