#!/bin/sh

# This uses the public/private keys on a PIV device, like a CAC or Yubikey.
# It requires a use-entered PIN.

[ "$#" -ne 2 ] && echo "cluster_passphrase_command usage: $0 \"%d\" %R" 1>&2 && exit 1

DIR="$1"
FD="$2"

# PIV slot 3 is the "Key Management" slot
PIV_SLOT='0:3'

# File containing the passphrased encrypted with the PIV_SLOT's public key
KEY_FILE="$DIR/pivpass.key"

MSG='Enter PIV PIN:'


stty -echo <&"$FD"

# Create a passphrased encrypted with the PIV_SLOT's public key?
if [ ! -e "$KEY_FILE" ]
then	echo 1>&"$FD"
	echo -n "$MSG" 1>&"$FD"

	# The 'postgres' operating system user must have permission to
	# access the PIV device.

	openssl rand -hex 32 |
	xxd -plain -cols 999 |
	# 'engine "pkcs11" set.' message confuses prompting
	if ! openssl rsautl -engine pkcs11 -keyform engine -encrypt \
		-inkey "$PIV_SLOT" -passin fd:"$FD" -out "$KEY_FILE" 2>&1
	then	stty echo <&"$FD"
		exit 1
	fi | grep -v 'engine "pkcs11" set\.'

	echo 1>&"$FD"

	# Warn the user to save the passphrase in a safe place
	cat 1>&"$FD" <<END

WARNING:  The PIV can be locked and require a reset if too many PIN
attempts fail.  It is recommended to run this command manually and save
the passphrase in a secure location for possible recovery.
END

fi

echo 1>&"$FD"
echo -n "$MSG" 1>&"$FD"

# Decrypt the passphrased encrypted with the PIV_SLOT's public key
if ! openssl rsautl -engine pkcs11 -keyform engine -decrypt \
	-inkey "$PIV_SLOT" -passin fd:"$FD" -in "$KEY_FILE" 2>&1
then	stty echo <&"$FD"
	exit 1
fi | grep -v 'engine "pkcs11" set\.'

echo 1>&"$FD"

stty echo <&"$FD"

exit 0
