Bridging the airgap

Dirk-Willem van Gulik dirkx at webweaving.org
Sun Aug 6 19:53:14 CEST 2017


Peter, Werber,

As per the IRC discussion - below is a slightly hacked testscript of ours that allows you to abuse a suitable chipcart or yubico PGP card with x509 functionality to `bridge' an airgap during generation where one *also* wants the public key to be transported of the secure initial generation (or renewal of the expiry of the subkeys) by means of a smartcart itself (which you sort of axiomatically need to be able to trust they airgap).

I've stripped the test case down somewhat - i.e. the bit that initialises the PGP applet, generates the master and 3 subkeys, moves them to smart cards, etc, etc.

Dw.

# Reset the card or key; and let it generate a public/private key
# pair (as some do not allow the loading of a (ca or signed cert)
# without it containing a private key.
#
#TMPDIR=${TMPDIR:-/tmp}
DIR="${TMPDIR}/test-y-0012.$$"

mkdir -p "$DIR" || exit 1
(
set -e
cd "$DIR"
chmod 700 .

# Reset the card and generate a small public/private pair.
# Then export a CSR we can import again signed.
#
# We do this as some cards do *not* accept (import) an x509 which is
# not related to their own public key (and only acccept the CA key in
# a later slot if you work your way up the chain from leaf to top).
#
yubico-piv-tool -a reset
yubico-piv-tool -s 9a -A ECCP256 -a generate > pub.pem
yubico-piv-tool -s 9a -S '/CN=foo/' -P 123456 -a verify -a request < pub.pem > pub.csr

# Generate a defaultish public/private test pair.
#
gpg2 --homedir . --batch --passphrase 123456 --quick-generate-key  test at test.com 
gpg2 --homedir . --export test at test.com > gpg.pub.raw

# We create a raw OCTED string (sequence of 8 bit values)
# of a given lengt. For length we need long form - as 
# it will be over 127 bytes. We sort of cheat and assume 
# that 4 bytes will always cut it.
#
OIDVAL=$(
	set `wc -c gpg.pub.raw`
	S=$(printf "%08x" $2 | sed -e 's/\(..\)/:\1/g')

	# Octed string (raw 8 bit bytes), of given length.
	#
	/bin/echo -n DER:04:84$S

	od -t x1  gpg.pub.raw  | while read skip line
	do 
		if [ ! -z "$line" ]; then
			set $line
			for i in $*
			do
				/bin/echo -n :$i
			done
		fi
	done
)

# We need to provide the OIDs for each of our private
# extensions.
#
cat <<EOM > oids
1.3.6.1.4.1.2692.99.1   geo		Location (WGS84)
1.3.6.1.4.1.2692.99.1.1 geoLa		Latitude (WGS84)
1.3.6.1.4.1.2692.99.1.2 geoLon		Longitude (WGS84)
1.3.6.1.4.1.2692.99.3   imgSHA1		SHA1 of the image
1.3.6.1.4.1.2692.99.4   imgURL		URL of the image
1.3.6.1.4.1.2692.99.5   screenURL	URL of a medical DICOM screen
1.3.6.1.4.1.2692.99.6   rawPGP 		raw (byte) PGP public key file.
2.16.528.1.1003.1.3.2.4.1.1	uziZorgverlenerCA	UZI-register, Zorgverlener CA, Royal Kingdom of the Netherlands
EOM

cat <<EOM > openssl.tmp 
[default]
oid_file=oids

[gpgraw]
1.3.6.1.4.1.2692.99.6=$OIDVAL
EOM

# Create myself a miniature CA.
openssl req -new -x509 -out ca.pem -subj /CN=moi/ -nodes

# And use that to sign the CSR; and give the signed cert
# an extension with our PGP public key.
#
openssl x509 -req -in pub.csr -CA ca.pem -CAkey privkey.pem -set_serial 01 \
	-outform DER -out pub.der \
	-extfile openssl.tmp -extensions gpgraw


yubico-piv-tool -s 9a -a import-certificate -K DER < pub.der

# Now fake an removal of the smart card for 5 seconds. Specifically 
# for platforms like OSX that can cache things.
#
set `lsusb | grep Yu | head -1`
usbpowerctrl $3 down
sleep 5
usbpowerctrl $3 up
# Extract again

# As we have se the Serial to '01' -- we know what to ask for here.
pkcs15-tool  --read-certificate 01 | openssl asn1parse -oids oids  | grep HEX 

# ... and pipe it back into GPG.
)
E=$?

rm -rf "${DIR}"
exit $E








More information about the Gnupg-devel mailing list