Coder Social home page Coder Social logo

pivy's Introduction

pivy

Simple-to-use PIV client for Linux and OSX. Includes the tools pivy-tool, pivy-agent, pivy-box and pivy-zfs.

About

This is an implementation of a simple PIV client for desktop Linux and OSX with minimal dependencies. It contains a pivy-tool binary which can conduct basic operations using PIV cards, and the pivy-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).

"PIV cards" notably includes Yubico Yubikey devices such as the NEO and Yubikey4, which can store up to 24 keys by using the "retired key" slots (which this agent supports).

This project re-uses most of the agent and protocol parsing code from OpenSSH, where it’s been pretty thoroughly battle-hardened.

Using pivy-agent

Using the PIV agent is identical to running the normal ssh-agent command, with the exception that pivy-agent requires a -g argument specifying the GUID of the PIV card to attach to, and you don’t have to use ssh-add to load any keys. You can also give a -K argument with the public key of the "Card Authentication" slot (9E) for extra security.

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

$ pivy-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 so that it can unlock the card to use the key. I can do this either by starting the agent with an environment variable SSH_ASKPASS set (in which case I will get a graphical prompt for the PIN), or by using the command ssh-add -X:

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

The PIV PIN is stored in memory only with special guard pages allocated either side of it and marked non-swappable. On Linux the memory area is also marked as non-dumpable so that it does not appear in core files.

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).

The agent will also forget the PIN automatically if the PIV card is unavailable for more than a few minutes, or if unusual conditions occur (e.g. an attacker tries to plug in a device with the same GUID that fails the 9E signature test).

Note that it’s perfectly fine to leave the pivy-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 will need to enter your PIN again). You can even start the agent without the PIV card present at all.

One useful way to use the pivy-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.

Connection confirm mode

You can also start the pivy-agent with mode -C, which indicates that it should prompt for confirmation (by running the program specified in the SSH_CONFIRM environment variable).

Unlike the regular ssh-agent, pivy-agent only prompts for confirmation once per connection to the agent, and only for connections which are forwarded via SSH agent forwarding (unless you give the option twice, as -CC, in which case every connection is confirmed). This makes the option more suitable for regular use: local programs don’t necessarily need prompting, and programs which make repeated use of your keys to perform operations will only pop up one prompt.

The SSH_CONFIRM environment variable can be given as a path to the zenity tool if desired — pivy-agent will generate appropriate arguments itself.

If you use agent forwarding (ssh -A), use of this mode is highly recommended.

GUI prompts

pivy-agent supports the same SSH_ASKPASS environment variable and interface that ssh-add does for presenting a GUI prompt for the PIN if desired.

If the environment variable SSH_NOTIFY_SEND is set to a path to a command which acts like notify-send (takes two arguments, title and message), then pivy-agent will also run that command whenever it believes a touch confirmation may be required.

Using pivy-tool

The pivy-tool program can perform a variety of operations against PIV tokens on the system, including simply listing the available tokens and their state:

$ pivy-tool list
      card: 562A20E4
    device: Yubico YubiKey OTP+FIDO+CCID 00 00
     chuid: ok
      guid: 562A20E42ED0E5813C530ED7FE75BE92
    fasc-n: 00000000000000000000000000000000000000000000000000
    expiry: 2050-01-01
    yubico: implements YubicoPIV extensions (v5.1.2)
    serial: 9073851
      auth: PIN*
     slots:
           ID   TYPE    BITS  CERTIFICATE
           9e   ECDSA   256   /title=piv-card-auth/CN=562A20E42ED0E5813C530ED7FE75BE92
           9a   ECDSA   256   /title=piv-auth/CN=562A20E42ED0E5813C530ED7FE75BE92
           9c   RSA     2048  /title=piv-sign/CN=562A20E42ED0E5813C530ED7FE75BE92
           9d   ECDSA   256   /title=piv-key-mgmt/CN=562A20E42ED0E5813C530ED7FE75BE92

You can see a short summary of the commands available by running pivy-tool without any arguments:

$ pivy-tool
pivy-tool: operation required
usage: pivy-tool [options] <operation>
Available operations:
  list                   Lists PIV tokens present
  pubkey <slot>          Outputs a public key in SSH format
  cert <slot>            Outputs DER certificate from slot

  init                   Writes GUID and card capabilities
                         (used to init a new Yubico PIV)
  setup                  Quick setup procedure for new YubiKey
                         (does init + generate + change-pin +
                         change-puk + set-admin)
  generate <slot>        Generate a new private key and a
                         self-signed cert
  import <slot>          Accept a SSH private key on stdin
                         and import it to a Yubikey (generates
                         a self-signed cert to go with it)
  change-pin             Changes the PIV PIN
  change-puk             Changes the PIV PUK
  reset-pin              Resets the PIN using the PUK
  factory-reset          Factory reset the PIV applet on a
                         Yubikey, once the PIN and PUK are both
                         locked (max retries used)
  set-admin <hex|@file>  Sets the admin 3DES key

  sign <slot>            Signs data on stdin
  ecdh <slot>            Do ECDH with pubkey on stdin
  auth <slot>            Does a round-trip signature test to
                         verify that the pubkey on stdin
                         matches the one in the slot
  attest <slot>          (Yubikey only) Output attestation cert
                         and chain for a given slot.

  box [slot]             Encrypts stdin data with an ECDH box
  unbox                  Decrypts stdin data with an ECDH box
                         Chooses token and slot automatically
  box-info               Prints metadata about a box from stdin
...

I recommend that new users run the pivy-tool setup command — it will initialise the PIV applet and then generate a standard set of basic keys which will suit most users.

The setup command will prompt you to set a PIN and PUK, as well as generating keys. The PIV PIN and PUK are both secret strings of 6-8 ASCII characters which are used to protect access to your device. In the PIV spec, these strings are required to be numeric (consisting only of digits 0 through 9), but many PIV devices such as YubiKeys will allow a much wider variety of characters.

The PIN is what you will normally use to authenticate to your device and unlock the use of private keys. By default, 5 invalid attempts to validate the PIN are allowed before it becomes locked. The PUK is intended as a fall-back if the PIN is forgotten, and can be used to reset it when locked. If you supply the PUK incorrectly 3 times (by default), then the card/device becomes locked down and will generally destroy its private keys.

It’s fine for personal use to set the PIN and PUK to the same value. The PUK is best used in an organisational context where devices are being provisioned for users centrally — it can be securely stored rather than given to the user and used to help unlock devices when PINs have been forgotten.

In a PIV device/card, your keys are stored in a fixed set of "slots", which are known by their numbered slot IDs.

The different key "slots" (9a, 9c, 9d and 9e) have different assigned purposes in the PIV spec, but YubiKeys and a lot of compatible devices are not very strict in enforcing these.

If you want detailed information about how the slots are intended to be used, you should consult NIST SP 800-73-4 (the PIV standard), but I will attempt a short summary here:

  • 9E: Card Authentication Key (often styled as "CAK"). This key is intended to authenticate only the device/card, not the person who owns it. It defaults to not requiring any authentication to use (no PIN, no touch confirmation on YubiKeys). In pivy-agent, for example, this slot is used to check that the device it’s talking to is actually the device it’s supposed to be (and not an attacker replacement with the same ID) before giving it the user’s PIN.

  • 9A: PIV Authentication Key. This is the main key used to authenticate the owner of the card/device. It’s protected by the PIN by default. You should use this key as your primary option for signature authentication (e.g. this is the key you should add to .ssh/authorized_keys or GitHub).

  • 9C: Signature Key. This key is intended for use signing documents or certificates. Since this purpose is not as common as authentication amongst users of pivy, it also serves duty as a backup authentication key. If you need to SSH or auth to a system that does not support EC keys, this key is an RSA key so that you can use it as a fallback for the 9A key. It requires a PIN by default, like 9A.

  • 9D: Key Management Key. This key is intended for use only to derive symmetric keys to encrypt/decrypt data. It’s a matter of some controversy in the cryptography community whether it’s entirely safe to use the same EC key both for signing and key derivation (ECDH), so I would recommend you avoid signing arbitrary data with your 9D key (don’t use it for regular authentication). See the next section for more information about using this key to encrypt data at rest. Requires both PIN and touch confirmation (on YubiKeys).

As well as these 4 basic slots, there are also the "Retired Key Management" slots, 82 through 95. These are intended for rolling old previously-used 9D keys into so that you can continue to decrypt data protected by them on a new device. However, as usual, YubiKeys do not enforce this usage, and these slots can be used for anything you like.

If you need to import an existing key into your YubiKey, I would recommend using one of these retired slots rather than placing it in one of the "main 4".

Note that using the pivy-agent for SSH authentication becomes more complex when you have more than 4 keys available — most SSH servers default to MaxAuthTries 6 in their configuration, and each key counts as a "try", so if you connect with an agent that contains 6 keys, no other auth methods can be attempted (so you will never fall back to trying password/interactive auth). If needed, you can work around this with the IdentitesOnly SSH configuration option.

Eboxes and pivy-box

The pivy-box command provides facilities for managing encrypted data storage using EC keys. It’s particularly notable for its approach to "recovery" to handle the situation where your PIV token is lost or damaged.

In short, an ebox generated by pivy-box can be unlocked either by a primary PIV token, or by a set of N/M recovery PIV tokens. For example, you can have a primary device you use to unlock an encrypted disk, and then if that device fails, fall back to using any 3 out of a set of 5 recovery devices instead.

During recovery the devices being used don’t have to be physically connected to the machine performing recovery, either — a system of encrypted challenge-response messages (which you can copy-paste) can be used instead to make use of a token at a remote location.

Eboxes are designed to be small enough to fit in a LUKS token JSON slot or ZFS filesystem property so that they are colocated with the encrypted data.

The ebox primitive is based on the crypto_box in libnacl/libsodium (after which it was named). PIV doesn’t support Curve25519 today, though, so we use EC keys on the standard NIST P curves instead. ChaCha20+Poly1305 is still the default cipher and MAC combination used. GF^256 Shamir secret sharing is used to achieve the N/M property during recovery.

Templates

Since the N/M recovery setup can involve a lot of typing (entering information about 5+ tokens), pivy-box lets you save just the metadata about which tokens you want to use for your recovery setup in a "template" file. These are managed by the pivy-box tpl family of commands:

$ pivy-box tpl
pivy-box: operation required
pivy-box tpl <op>:
  create                Create a new template
  edit                  Edit an existing template
  show                  Pretty-print a template to stdout

$ pivy-box tpl show -h
show: invalid option -- 'h'
usage: pivy-box tpl show [-r] [tpl]

Pretty-prints a template to stdout showing details of
devices and configuration.

Options:
  -r         raw input, don't base64-decode stdin

If no [tpl] or -f given, expects template input on stdin.

$ pivy-box tpl show backup
-- template --
version: 1
configuration:
  type: recovery
  required: 2 parts
  part:
    guid: E6FB45BDE5146C5B21FCB9409524B98C
    name: xk1
    key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY...
  part:
    guid: 051CD9B2177EB12374C798BB3462793E
    name: xk2
    key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY...
  part:
    guid: D19BE1E0660AECFF0A9AF617540AFFB7
    name: xk3
    key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY...

The pivy-box tpl create and tpl edit commands also include an interactive menu-driven editor so you can make changes later:

$ pivy-box tpl edit -i backup
-- Editing template --
Select a configuration to edit:
  [1] recovery: any 2 of: E6FB45BD (xk1), 051CD9B2 (xk2), D19BE1E0 (xk3)

Commands:
  [+] add new configuration
  [-] remove a configuration
  [w] write and exit
Choice? 1
-- Editing recovery config 1 --
Select a part to edit:
  [1] E6FB45BD (xk1)
  [2] 051CD9B2 (xk2)
  [3] D19BE1E0 (xk3)

Commands:
  [n] 2 parts required to recover data (change)
  [+] add new part/device
  [-] remove a part
  [x] finish and return
Choice? +
GUID (in hex)? 562A20E42ED0E5813C530ED7FE75BE92
Key? ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoY...
-- Editing part 4 --
Read-only attributes:
  GUID: 562A20E42ED0E5813C530ED7FE75BE92
  Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoY...

Select an attribute to change:
  [n] Name: (null)
  [c] Card Auth Key: (none set)

Commands:
  [x] finish and return
Choice? n
Name for part? xk4
-- Editing part 4 --
Read-only attributes:
  GUID: 562A20E42ED0E5813C530ED7FE75BE92
  Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoY...

Select an attribute to change:
  [n] Name: xk4
  [c] Card Auth Key: (none set)

Commands:
  [x] finish and return
Choice? x
-- Editing recovery config 1 --
Select a part to edit:
  [1] E6FB45BD (xk1)
  [2] 051CD9B2 (xk2)
  [3] D19BE1E0 (xk3)
  [4] 562A20E4 (xk4)

Commands:
  [n] 2 parts required to recover data (change)
  [+] add new part/device
  [-] remove a part
  [x] finish and return
Choice? x
-- Editing template --
Select a configuration to edit:
  [1] recovery: any 2 of: E6FB45BD (xk1), 051CD9B2 (xk2), D19BE1E0 (xk3), 562A20E4 (xk4)

Commands:
  [+] add new configuration
  [-] remove a configuration
  [w] write and exit
Choice? w

Of course, editing a template does not automatically re-encrypt any eboxes you have already created from it. There is a re-encrypt command available under key and stream though to help you update to a new template.

Types of eboxes

There are two different types of ebox supported:

  • A "key" ebox for storing small amounts of key material or other fixed-length data (e.g. disk encryption master keys); and

  • A "stream" ebox which can handle large amounts of data without buffering it all into memory, and can also be used in a seekable form.

In both types, no data is ever output by the pivy-box command from decryption unless it has passed MAC validation (i.e. all forms available are authenticated encryption).

ZFS encryption

An example of using a "key" ebox with ZFS encryption:

$ pivy-box tpl create foobar ...
$ pivy-box key generate foobar -l 32 > /tmp/newkey.ebox
$ pivy-box key unlock -R < /tmp/newkey.ebox | \
    zfs create \
    -o encryption=on -o keyformat=raw \
    -o local:ebox="$(cat /tmp/newkey.ebox | tr -d '\n')" \
    pool/filesystem
$ rm /tmp/newkey.ebox

$ zfs get -Ho value local:ebox pool/filesystem | \
    pivy-box key unlock -R | \
    zfs load-key pool/filesystem

The pivy-zfs tool wraps these steps up into single commands:

$ pivy-box tpl create foobar ...
$ pivy-zfs -t foobar zfs-create pool/filesystem

$ pivy-zfs unlock pool/filesystem

The pivy-zfs unlock command also will prompt you to add a new primary token if you finish recovery successfully, which also makes it preferable to scripting the zfs load-key command yourself.

LUKS/cryptsetup

With LUKS/cryptsetup we can store the ebox data in a LUKS2 JSON token slot. The pivy-luks tool handles formatting and unlocking LUKS2 partitions with the raw volume key encoded directly in the ebox and no passphrase keyslot:

$ pivy-box tpl create foobar ...
$ pivy-luks format -t foobar /dev/sdx2

$ pivy-luks unlock /dev/sdx2 volname

Other cryptsetup commands work on a pivy-luks partition as normal:

$ cryptsetup luksDump /dev/sdx2
LUKS header information
Version:        2
Epoch:          3
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           c0b8d772-5418-4460-81c5-a5abe20b85fa
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)

Data segments:
  0: crypt
  offset: 16777216 [bytes]
  length: (whole device)
  cipher: aes-xts-plain64
  sector: 4096 [bytes]

Keyslots:
Tokens:
  1: ebox
Digests:
  0: pbkdf2
  Hash:       sha256
  Iterations: 226376
  Salt:       fe 5a 67 a7 05 95 e5 06 61 be c5 aa 06 48 ca 97
              2a fb c5 eb 0d 42 a1 83 bd 39 61 fb a8 2f 0b bb
  Digest:     8a 45 6b d0 2c cb 5d b2 51 25 db 3e fd 3a 6f fb
              e2 db 7a de c4 66 85 46 30 05 41 0e e8 eb 8d 3e

Note that the resulting LUKS header has no keyslots (so there is no passphrase that will unlock the volume key for this partition, only the ebox).

Recovery and challenge-response

When pivy-box key unlock or pivy-box stream decrypt run and cannot locate a "primary" token on the system that matches the box they are decrypting, they enter an interactive recovery mode on the terminal.

First, recovery mode will prompt you to select the configuration and parts you want to use for the recovery:

-- Recovery mode --
Select a configuration to use for recovery:
  [1] recovery: any 2 of: E6FB45BD (xk1), 051CD9B2 (xk2), D19BE1E0 (xk3)

Commands:
Choice? 1
-- Recovery config 1 --
Select 2 parts to use for recovery
  [1] E6FB45BD (xk1)
  [2] 051CD9B2 (xk2)
  [3] D19BE1E0 (xk3)

Commands:
Choice? 1
-- Select recovery method for part 1 --
GUID: E6FB45BDE5146C5B21FCB9409524B98C
Name: xk1
Public key (9d): ecdsa-sha2-nistp256 AAAAE2VjZHNhL...
  [x] Do not use*
  [l] Use locally (directly attached to this machine)
  [r] Use remotely (via challenge-response)

Commands:
Choice? r
-- Recovery config 1 --
Select 2 parts to use for recovery
  [1] E6FB45BD (xk1)* [remote/challenge-response]
  [2] 051CD9B2 (xk2)
  [3] D19BE1E0 (xk3)

Commands:
Choice? 2
-- Select recovery method for part 2 --
GUID: 051CD9B2177EB12374C798BB3462793E
Name: xk2
Public key (9d): ecdsa-sha2-nistp256 AAAAE2VjZHN...
  [x] Do not use*
  [l] Use locally (directly attached to this machine)
  [r] Use remotely (via challenge-response)

Commands:
Choice? r
-- Recovery config 1 --
Select 2 parts to use for recovery
  [1] E6FB45BD (xk1)* [remote/challenge-response]
  [2] 051CD9B2 (xk2)* [remote/challenge-response]
  [3] D19BE1E0 (xk3)
  [r] begin recovery

Commands:
Choice?

Once sufficient parts have been selected, you can choose the "Begin recovery" option. This will first try to locate any devices you’ve chosen for "local" recovery, prompting for insertion as you go. Then it will proceed to generate challenges for remote recovery:

-- Begin challenge for remote device E6FB45BD (xk1) --
sMUCARDm+0W95RRsWyH8uUCVJLmMnRFjaGFjaGEyMC1wb2x5MTMwNQZzaGE1MTIQF
ddAc+h16xsXZY9+WCgrBghuaXN0cDI1NiED4yZnwmPVfm0RlixV34blQg+mbRnF+G
sLlhyGZojhd5YhA5Cbbob/i306qUbZpULvj9kmErWLvjVsyIiQC4ifpxM+AAAAAQB
0JgTe6DAfCdO+dfs0uJvfjStT5w2bxdVJPcP3GR+BoL4yc2ETsa15vF1ST/I0lKGV
FFEy/n0MsPZb03iOxbBN40nTXVQZtaSnjpNwinegzFGf6+kq1Tj8Kvgd8N5q3YRJx
J71hjgrH/lwFvSSUN3Njy8UWHDmhl9I2FHxzCUStFN/+G5Ihf5/KGyfDIzcWABcD4
wh1wBraCdIgkTftKQQDcb5dHEvtlLeronpS4YfRaqdLRgQdnznFQxV/QnACU2CTD8
olkWzgXy/kypkN97FhoJ3wltmnRSWInLTZ5WIzdTz6NkDdf61VsDcaCovcubGkVMu
E090O8nuzFSdtObH
-- End challenge for remote device E6FB45BD (xk1) --

VERIFICATION WORDS for E6FB45BD (xk1): apple leadership sacred breakfast

-- Begin challenge for remote device 051CD9B2 (xk2) --
sMUCARAFHNmyF36xI3THmLs0Ynk+nRFjaGFjaGEyMC1wb2x5MTMwNQZzaGE1MTIQq
xtt1txRzfWNpA2VotX1jQhuaXN0cDI1NiEC+lfqlhWdzpHFqVvRrE6tYls71VNZcm
ORxoIYnF9ORU4h...
-- End challenge for remote device 051CD9B2 (xk2) --

VERIFICATION WORDS for 051CD9B2 (xk2): jewellery academic powder syndicate


Remaining responses required:
  * E6FB45BD (xk1)
  * 051CD9B2 (xk2)

-- Enter response followed by newline --
>

These base64-encoded challenge tokens are encrypted so that only the target device can process them or retrieve any sensitive information. They do not, however, have any means to authenticate the sending machine on their own, which is the purpose of the "verification words".

As a result, you should transport the verification words separately to the challenge itself — e.g. send the challenge over IRC or email, but send the verification words over Signal or read them over the phone.

The challenge does include additional information that can be verified to try to reduce the risk of replay as well, which will be displayed on the remote machine.

An example of responding to a challenge:

$ pivy-box challenge respond
sMUCARAFHNmyF36xI3THmLs0Ynk+nRFjaGFjaGEyMC1wb2x5MTMwNQZzaGE1MTIQq
xtt1txRzfWNpA2VotX1jQhuaXN0cDI1NiEC+lfqlhWdzpHFqVvRrE6tYls71VNZcm
ORxoIYnF9ORU4...
^D
Enter PIV PIN for token 051CD9B2:
-- Challenge --
Purpose                recovery of at-rest encryption keys
Description            Recovering pivy-box data for part 051CD9B2 (xk2)
Hostname               myra
Generated at           2019-04-12 12:43:39 (local time)

VERIFICATION WORDS     jewellery academic powder syndicate

Please check that these verification words match the original source via a
separate communications channel to the one used to transport the challenge
itself.

If these details are correct and you wish to respond, type 'YES': YES
-- Begin response --
sMUCAAAAEWNoYWNoYTIwLXBvbHkxMzA1BnNoYTUxMhALNQm7HuVbyMrjFMNjZjsNC
G5pc3RwMjU2IQOqjFsNsLv8hotnZopkrjC2SDSSmMkXgQCK6kg78iev1yECfHZbB6
dopyOImq3B1uLxj+LeTvry9IEN2YX9xKjk/OkAAAAAOLmaw9nVj0cSaAV21FbbIJv
zpFBZBsZkiztabo7moHUEcXSeQ5v/0JDK1zuCQm3dg8mlPMkdu03o
-- End response --

Responses to a challenge are not replayable, so they do not need separate verification words.

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.

If you’re using ArchLinux, we have a pivy package in the AUR which will compile and install the binaries for you.

If you’re compiling yourself, clone this repository and use make to build the binaries:

$ git clone https://github.com/arekinath/pivy-agent
$ cd pivy-agent
$ make

You can then run make install (as root or with sudo) to install the agent into /opt/pivy. The Makefile also supports prefix=/…​ to use a different prefix rather than /opt/pivy, and DESTDIR= to stage the installation.

The make setup invocation can be used to set up a user systemd service to start it automatically at login. It 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 setup
Enter a GUID to use for pivy-agent: 995E171383029CDA0D9CDBDBAD580813

install -d /home/alex/.config/pivy-agent
install .dist/default_config /home/alex/.config/pivy-agent/default
systemctl --user enable [email protected]
systemctl --user start [email protected]

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

Installing on Mac OSX

Installing on OSX is even easier, as we have pre-built binary package installers which both install the binaries and set up a user launchd service to run the pivy-agent for you.

You can find the latest binary installer on the releases page.

After installing the program itself, the installer will prompt you to insert a YubiKey or other PIV token using a dialog box. Then it will generate a user launchd service to run the agent for you, and add lines to /etc/profile to default to using it in place of the Keychain agent.

The pivy- programs will also be added to your PATH, so they should be accessible from any terminal. You’ll find them in /opt/pivy if you need them for any other reason.

Differences to Linux

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

Compiling on Mac OSX

Rather than depend on homebrew or MacPorts or another similar system, we 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 pivy-agent.

The commands you will need to run are as follows:

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

## Build libressl and then pivy-agent
$ make -j4

## Generate a .pkg (will be output in macosx/pivy-version.pkg)
$ sudo make package
...

pivy's People

Contributors

aiotter avatar arekinath avatar botovq avatar fstelzer avatar jasonbking avatar jmatthew avatar pfmooney avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pivy's Issues

pivy-box should not fail when PCSC cannot find a reader

Without a Yubikey connected, and without an SSH agent available, the program exits rather than entering the recovery menu:

$ pivy-box stream decrypt some.ebox >some.plain.txt
pivy-box: 'stream decrypt' command failed
  Caused by PCSCError: SCardListReaders failed: -2146435026 (Cannot find a smart card reader.)
    in piv_find() at piv.c:1268

Build Issue on Debian 'Buster' (10)

After installing the libraries:

$ sudo apt install libbsd-dev libbsd0 freebsd-glue libpcsclite-dev libpcsclite1

And the following for good luck ..
$ sudo apt install libeditline-dev libedit2 libedit-dev libeditline0

I ran a make

cc -pthread -I/usr/include/PCSC -I/home/ian/Projects/pivy/libressl/include  -I/usr/include/editline -isystem /usr/include/bsd -DLIBBSD_OVERLAY -fstack-protector-all -fwrapv -fPIC -D_FORTIFY_SOURCE=2 -Wall -O2 -g -m64 -D_GNU_SOURCE -std=gnu99 -o 

sss/randombytes.o -c sss/randombytes.c
sss/randombytes.c: In function ‘randombytes’:
sss/randombytes.c:177:11: note: #pragma message: Using getrandom system call
#  pragma message("Using getrandom system call")
           ^~~~~~~
cc -m64 -o pivy-box pivy-box.o ebox.o ebox-cmd.o piv.o tlv.o debug.o bunyan.o errf.o utils.o libssh/sshbuf.o libssh/sshkey.o libssh/ssh-ed25519.o libssh/ssh-ecdsa.o libssh/ssh-rsa.o libssh/cipher.o libssh/digest-openssl.o libssh/bcrypt-pbkdf.o libssh/blowfish.o libssh/rsa.o libssh/base64.o libssh/atomicio.o libssh/hmac.o libssh/authfd.o ed25519/ed25519.o ed25519/fe25519.o ed25519/ge25519.o ed25519/sc25519.o ed25519/hash.o ed25519/blocks.o chapoly/chacha.o chapoly/poly1305.o sss/hazmat.o sss/randombytes.o -lpcsclite /home/ian/Projects/pivy/libressl/crypto/.libs/libcrypto.a -pthread -lz -ledit -lbsd

Make builds pivy-agent, pivy-box and pivy-tool but I was wondering about the #pragma warning in sss/randombytes.c and was it an issue? (after all the security of any crypto system relies on entropy)

pivy-tool segfaults when initializing Yubikey on MacOS M1

I am trying to run pivy-tool on MacOS on an M1 SoC and am running into the following segfault:

arjen@mbp pivy % lldb ./pivy-tool
(lldb) target create "./pivy-tool"
Current executable set to '/Users/arjen/oxidecomputer/pivy/pivy-tool' (arm64).
(lldb) run init
Process 87019 launched: '/Users/arjen/oxidecomputer/pivy/pivy-tool' (arm64)
Process 87019 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x3f)
    frame #0: 0x0000000181caea9c libsystem_platform.dylib`_platform_strcmp + 12
libsystem_platform.dylib`:
->  0x181caea9c <+12>: ldrb   w5, [x1], #0x1
    0x181caeaa0 <+16>: subs   x3, x4, x5
    0x181caeaa4 <+20>: ccmp   w4, #0x0, #0x4, eq
    0x181caeaa8 <+24>: b.ne   0x181caea90               ; <+0>
Target 0: (pivy-tool) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x3f)
  * frame #0: 0x0000000181caea9c libsystem_platform.dylib`_platform_strcmp + 12
    frame #1: 0x000000010002917c pivy-tool`errf_caused_by(e=0x0000000000000033, name="DeviceOutOfMemoryError") at errf.c:265:7 [opt]
    frame #2: 0x0000000100006680 pivy-tool`cmd_init at pivy-tool.c:1088:6 [opt]
    frame #3: 0x0000000100004d5c pivy-tool`main(argc=2, argv=0x000000016fdff460) at pivy-tool.c:3044:9 [opt]
    frame #4: 0x00000001819010e0 dyld`start + 2360
(lldb) register read
General Purpose Registers:
        x0 = 0x00000001001efce2  "eviceOutOfMemoryError"
        x1 = 0x000000000000003f
        x2 = 0x0000000000000002
        x3 = 0x0000000000000044
        x4 = 0x0000000000000044
        x5 = 0x0000000000000000
        x6 = 0x0000000004000100
        x7 = 0x0000000000000000
        x8 = 0xc3a89c20274c002b
        x9 = 0xc3a89c20274c002b
       x10 = 0x0100000100000000 (0x0000000100000000) pivy-tool`_mh_execute_header
       x11 = 0x000000100003fa23
       x12 = 0x708c3d9f02040204
       x13 = 0x0002000110000400
       x14 = 0x0000000200001000
       x15 = 0x00020000100003d8
       x16 = 0x0000000181caea90  libsystem_platform.dylib`_platform_strcmp
       x17 = 0x00000001dc301e38  (void *)0x0000000181cb1650: _platform_memmove
       x18 = 0x0000000000000000
       x19 = 0x00000001001efce1  "DeviceOutOfMemoryError"
       x20 = 0x0000000000000033
       x21 = 0x0000600002dfc000
       x22 = 0x000000016fdfeff8
       x23 = 0x00000001001efab7  "PermissionError"
       x24 = 0x00000001001efcd3  "ArgumentError"
       x25 = 0x000000010022e000  X509V3_str_reasons + 216
       x26 = 0x0000000100228000  optstring
       x27 = 0x0000000100228000  optstring
       x28 = 0x0000000100228000  optstring
        fp = 0x000000016fdff030
        lr = 0x000000010002917c  pivy-tool`errf_caused_by + 56 at errf.c:265:7
        sp = 0x000000016fdff010
        pc = 0x0000000181caea9c  libsystem_platform.dylib`_platform_strcmp + 12
      cpsr = 0x00001000

Looking at the pc this seems to be an invalid data fetch.

I tried running the x86_64 version of the binary and get further into unwinding the exception, but it seems to print the some memory, the contents of the PATH variable and then some more (stack or heap?) memory (censored on purpose) and then segfaults as well:

arjen@mbp ~ % env /usr/bin/arch -x86_64 /opt/pivy/bin/pivy-tool init
pivy-tool: error occurred while executing 'init'
  Caused by cmd_init: failed to write to card
    in cmd_init() at pivy-tool.c:1097
  Caused by :
    in () at :2
  Caused by <dirty memory from what looks a prior process here>
    in :<PATH variable contents>:<partial data from something else>
zsh: segmentation fault  env /usr/bin/arch -x86_64 /opt/pivy/bin/pivy-tool init

Anything I can/should try to provide more debug info?

Edit: this behavior happens with both the 0.11.2 release and main.

Why LibreSSL?

Why do you bundle LibreSSL? Can it be at least linked dynamically with system-provided LibreSSL?

Nitrokey 3: pivtool change-puk: Segmentation fault

Hi,

as described in issue #45, I am trying to set-up a Nitrokey 3.
This issue looks different than the aforementioned one:

Changing the PIN seems to work...

$ ./pivy-tool change-pin
Enter current PIV PIN (2B671D88): 
Enter new PIV PIN (2B671D88): 
Confirm new PIV PIN (2B671D88): 

...but changing the PUK results in a segmentation fault:

$ ./pivy-tool change-puk
Enter current PUK (2B671D88): 
Enter new PUK (2B671D88): 
pivy-tool: PIN must be 4-8 characters
Enter current PUK (2B671D88): 
Enter new PUK (2B671D88): 
Confirm new PUK (2B671D88): 
Segmentation fault

I tried different numbers of characters, alphanumeric charset, only digits, but the problem persists.
Any suggestions?

Cheers, Matthias

Pin/Touch policy for imported keys

I am using a Yubikey 5 with imported piv certs/keys (Created via a corporate CMS and backed up). Therefore these keys don't have an attestation cert. The key still has Pin & Touch policies for every key (usually the cached touch policy).
Without the attestation cert pivy-agent is unable to get this information about the policies from the yubikey and afaik it is not possible to do so in any other way.
Would it be possible to add configuration so I'm able to manually specify the policies per slot?
At the moment I always have to remember to touch the key when some operation hangs and the touch notification would be nice :)
If you're open to the idea I'd try writing a patch for it. I haven't looked into it deeply yet so not sure how difficult it would be.
I think the pin policy does not need configuration since the card will ask for the login if necessary, so the config could just be something like:
-T 9a:always,9c:cached

Edit: Other agents just use a timeout (100ms or similar) for key operations and just assume a touch is necessary if its triggered. This feels kinda wrong to me though...

Support multiple key in same agent

Is it possible to have the agent support multiple keys with different guids?
I have 2 yubikeys with the same certificate loaded in both and like to be able to use them interchangeably.
Right now I have to either have 2 agents running or restart it with the correct guid when changing key.

pivy-agent: add mode not to keep the PIN in memory

PIV tokens can be configured to only require the PIN once in a session. Assuming pivy-agent keeps the PIV session open, it doesn't need to keep the PIN in memory in that case. It would be nice to have a mode for pivy-agent not to keep the PIN.

The main difference in UX is that plugging the token out and back in would require providing the PIN again.

chuid with a deprecated field in yubikey

Hi,
I recently received a "new" yubikey 5 nano with already imported piv certs (corporate CA).
When running pivy-tool -d list this new key produces:
error = InvalidDataError: PIV device 'Yubico YubiKey FIDO+CCID 00 00' returned invalid or unsupported payload
in piv_read_chuid() at piv.c:1112
Caused by PIVTagError: Invalid tag 0x3d in PIV CHUID response
in piv_chuid_decode() at piv.c:7300

Tag 0x3d is a deprecated field and not even listed anymore in the latest PIV spec. An older one (https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-73-2.pdf) still has it.
When i hack piv.c:7305:piv_chuid_decode() to just skip the tag I can successfully run the list command and get all the infos displayed. pivy-agent also seems to work just fine then.
I don't know why the key has this deprecated field (it's probably not regenerated when importing certs) but do you think adding it to the parser (and dropping its content) would hurt?

I'm attaching a pull request with my extremely simple patch.

pivy-agent dumps core on ssh-add -X (from time to time)

during ssh-add -X (pin entering) either it hanged or sth happened during/after entering pin (to unlock yubikey rsa keys) and pivy-agent crashed with core dumped.

[459301.127769] pivy-agent[1116]: segfault at 0 ip 00007ef5c95982a2 sp 00007ffc90911bc0 error 4 in libc.so.6[7ef5c954a000+176000]
[459301.127783] Code: 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 41 57 41 56 41 55 41 54 49 89 f4 55 4c 0f af e2 53 48 83 ec 18 4d 85 e4 0f 84 8f 00 00 00 <8b> 01 49 89 fe 48 89 f5 49 89 d5 48 89 cb 25 00 80 00 00 75 34 64

Retired key slots not shown on Yubikey 5

I have a Yubikey 5 with ECC keys/certs in the first two retired key slots in addition to 9a and 9d. pivy doesn't see them for some reason, but they work fine with Yubico tools (ykman/yubico-piv-tool/ykcs11/Windows minidriver). Any suggestions on how I could debug this?

Update: after some debugging, it looks like piv_read_keyhist gets SW_FILE_NOT_FOUND from the card. Trying to fetch the key history object (id 0x5fc10c) with yubico-piv-tool also fails. From OpenSC/OpenSC#847 it sounds like the key history object should be written when certs/keys are imported and the Yubico tools don't bother to do this? (I imported my keys/certs with either ykman or yubico-piv-tool originally.)

Output from pivy-tool list:

[2020-07-28T08:53:46.474Z] DEBUG: reading CHUID file
[2020-07-28T08:53:46.480Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x3d
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x30
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x34
[2020-07-28T08:53:46.480Z] TRACE: read guid: guid = << 20 B5 36 81 60 7D DC DC 25 3D BB FD C7 9E D4 0F >>
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x35
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x3e
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0xfe
[2020-07-28T08:53:46.487Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x4, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x14
[2020-07-28T08:53:46.487Z] TRACE: reading discov tlv tag: tag = 0x4f
[2020-07-28T08:53:46.487Z] TRACE: reading discov tlv tag: tag = 0x5f2f
[2020-07-28T08:53:46.487Z] TRACE: policy in discov: policy = 0x4000
[2020-07-28T08:53:46.494Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6a82, sw_name = "FILE_NOT_FOUND", lr = 0x0
[2020-07-28T08:53:46.501Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xfd, ins_name = "YKPIV_GET_VER", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x3
[2020-07-28T08:53:46.508Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xf8, ins_name = "YKPIV_GET_SERIAL", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x4
[2020-07-28T08:53:46.524Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xa4, ins_name = "SELECT", p1 = 0x4, p2 = 0x0, lc = 0xc, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x13
[2020-07-28T08:53:46.524Z] DEBUG: reading cert file: slot = 0x9e, cdata = << 5C 03 5F C1 01 >>
[2020-07-28T08:53:46.531Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6a82, sw_name = "FILE_NOT_FOUND", lr = 0x0
[2020-07-28T08:53:46.531Z] DEBUG: reading cert file: slot = 0x9a, cdata = << 5C 03 5F C1 05 >>
[2020-07-28T08:53:46.537Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.544Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.551Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.558Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x61c2, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.565Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0xc2, sw = 0x9000, sw_name = "NO_ERROR", lr = 0xc2
[2020-07-28T08:53:46.567Z] DEBUG: reading cert file: slot = 0x9c, cdata = << 5C 03 5F C1 0A >>
[2020-07-28T08:53:46.572Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6a82, sw_name = "FILE_NOT_FOUND", lr = 0x0
[2020-07-28T08:53:46.572Z] DEBUG: reading cert file: slot = 0x9d, cdata = << 5C 03 5F C1 0B >>
[2020-07-28T08:53:46.579Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.586Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.593Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6180, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.599Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x80, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x80
      card: 20B53681
    device: Yubico YubiKey OTP+FIDO+CCID 00 00
     chuid: ok
      guid: 20B53681607DDCDC253DBBFDC79ED40F
    fasc-n: D4E739DA739CED39CE739D836858210842108421C84210C3EB
    expiry: 2030-01-01
    yubico: implements YubicoPIV extensions (v5.2.4)
    serial: 12062930
      auth: PIN*
     slots:
           ID   TYPE    BITS  CERTIFICATE                   
           9a   RSA     2048  /CN=foo
           9d   RSA     2048  /CN=vuori 

Output from ykman piv info:

PIN tries remaining: 3
CHUID:	3019d4e739da739ced39ce739d836858210842108421c84210c3eb341020b53681607ddcdc253dbbfdc79ed40f350832303330303130313e00fe00
CCC: 	f015a000000116ff02d1cb0959ff0a839df15d5a3fd9fef10121f20121f300f40100f50110f600f700fa00fb00fc00fd00fe00
Slot 82:
	Algorithm:	ECCP256
	Subject DN:	CN=baz
	Issuer DN:	CN=baz
	Serial:		444783330304390453669788152270965554531954112175
	Fingerprint:	a86319c3c04b2f77702cb9d04ee8aa3996ed33970c0ff09ccc6b6072fc7f4538
	Not before:	2020-03-10 22:03:07
	Not after:	2030-03-08 22:03:07
Slot 83:
	Algorithm:	ECCP256
	Subject DN:	CN=bar
	Issuer DN:	CN=bar
	Serial:		575996940829270239521168697105327364973293330045
	Fingerprint:	74102817194098850b39ca691dd98650cd77e082c401b6940747c5f51ad19e4f
	Not before:	2020-05-15 10:43:15
	Not after:	2030-05-13 10:43:15
Slot 9a:
	Algorithm:	RSA2048
	Subject DN:	CN=foo
	Issuer DN:	x
	Serial:		14
	Fingerprint:	3a8d19e5f2cd6457726af0ba9a1b511dba1dbc153988ab1a050e646711cc2ccc
	Not before:	2020-03-09 21:40:07
	Not after:	2022-03-09 21:40:07
Slot 9d:
	Algorithm:	RSA2048
	Subject DN:	CN=vuori
	Issuer DN:	CN=vuori
	Serial:		11361296214394234510
	Fingerprint:	fb1a9953f75c33eae446780ae86914dd85297f43cac08c530a88a7b37b87d85e
	Not before:	2017-06-19 10:51:17
	Not after:	2117-05-26 10:51:17

error messages on last pin use could be more explicit

While attempting to work through and reset things I got into a situation where it was not using up the last pin attempt trying to protect me from myself, which is quite kind. The error message is of the form:

$ pivy-tool sign 9a
asdf
Enter PIV PIN for token 5D7E5122: 
pivy-tool: insufficient PIN retries remaining (1 left)

When this was happening I didn't realize that the pin I was entering was being ignored and the operation was aborted. I realize I should have probably put that together with the insufficient PIN retries remaining. It may help to mention the use of -f or to be a little more explicit that we're not attempting to do anything with this.

pivy-agent: use ssh-askpass to obtain the PIN

It's unfortunate that one needs to remember to provide the PIN with ssh-add -X at every reboot. If ssh-askpass is available, pivy-agent could use it to obtain the PIN from the user while the signing request is pending.

(I also assume there is no way for the agent to ask the client to provide a passphrase when a signature was requested, otherwise pivy-agent should definitely do that.)

Setup should allow setting touch policy

Attempting to pass -t never before and after the setup command does not seem to currently work

❯ pivy-tool setup -t never > /dev/null 2>&1

~
❯ echo $?
2

~
❯ pivy-tool -t never setup
Generating standard keys...
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZ7hlm46JyPCjWxOs3jXVALwFFZBJikcLQhhfPQyP2NfQO6O7ctM/NEDPFNjr4ynUudaR8O6XAjrclBBz3wO2k= PIV_slot_9E@52580CC47F3B90D6666253564EBE60CD
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFXb6l/qdnmjwI7shjFae4sF6niZKCsKpRM0pBwhMAtpu9O4JtNp+fAd0UZgH8kEqKnXM1khHf/v6r6uyNNmPHA= PIV_slot_9A@52580CC47F3B90D6666253564EBE60CD
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDunnGREo0c7Qb8pKtMyrBF/bFwFKjGKKk66hMAQwgR0e5pNNPcV8ae6rCGCkuftRkqeI11obzITX2kX8xjbdGgAgDPbTHKYVNl91tCkBhyZOkKiQKNMGlF1d/yI13xV3xryhB9Q68EEpgZNLxqCPn8SGLia/nvodqEYnCxneN2Xx+QXA++WmRsdhUB2FL877u6+Lnes9bU/WiJI7IQT7D7xeU2Y63HOZCggOistEeB2cV+SJ6sf6tcL9A2ru8PyJqW3R3DhLq+pGNovilaT40KYnC5v7PNHOvMz5nLWZ0LHZ68rb86M+eDwGIiIQ8EEze4nKMF/Sn/0vz3V7Q8cI0B PIV_slot_9C@52580CC47F3B90D6666253564EBE60CD
Using touch button confirmation for 9D key
Please touch YubiKey when it is flashing
Touch button confirmation may be required.

pivy-tool setup should reject unexpected arguments

$ pivy-tool setup --help
pivy-tool: invalid option -- '-'
pivy-tool: invalid option -- 'h'
pivy-tool: invalid option -- 'e'
pivy-tool: invalid option -- 'l'
Initializing CCC and CHUID files...
24FE845F922459CE34CA803F8B384DED
Generating standard keys...
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL6rSly7baeTsgLRXUjH6gTpaV2BNDIzSQRmZRZIE08Q0kpI3vxWJ1rham2jFlqtdGV6Axe47519o3CeZRXBGVg= PIV_slot_9E@24FE845F922459CE34CA803F8B384DED
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNJ8p4cgJshkaKb5W3QY0nVq2klVeHec5I/0xjcnYviqc7kqyuw9DfKe+TqJ+bkDaInzLtRRatfZBjiF/J2WIfA= PIV_slot_9A@24FE845F922459CE34CA803F8B384DED

pivy-agent: super weird SIGSEGV on Linux

I updated my pivy installation from the arekinath/pivy fork for the first time in the while. After running make distclean followed by make, pivy-tool et al. were working, but pivy-agent would crash as soon as something connected to it.

The reason turns out to be the weirdest in recent memory: prepare_poll() calls recallocarray() (which is linked from libressl compat according to gdb) with *npfdp = 0, which calls calloc(1, 8) (ultimately __libc_calloc) as expected… but the pointer returned is garbage and accessing it leads to SIGSEGV. The pointer value is usually around 0x557afc90 which is far from where one would expect. Calling calloc() from gdb returns pointers around 0x5555557af860, so it feels like there's some kind of stack/register misalignment or prototype mixup going on here.

This happens on Ubuntu 20.04 with the default gcc (9.4.0) and gcc-10 and generally the default system libraries that you get from apt.

git bisect shows that the offending commit is f73d2a7610badec71c3006e7273a3a2d1d13a225: clean up openssh, start on piv-ca module. OpenSSH also has a copy of the OpenBSD compat functions, but the resulting libssh.a doesn't include recallocarray (only xrecallocarray).

I didn't try it, but I suppose the easy fix to pivy-agent would be to use glibc reallocarray, but that might leave problems lurking in the external libraries that try to use recallocarray. Disabling LTO and changing all optimization settings to -O0 had no effect wrt ultimately crashing.

Easy workaround: go back to v0.8.0.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.