Bridging the airgap

Dirk-Willem van Gulik dirkx at
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.


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

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 
gpg2 --homedir . --export test at >

# 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.
	set `wc -c`
	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  | while read skip line
		if [ ! -z "$line" ]; then
			set $line
			for i in $*
				/bin/echo -n :$i

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

cat <<EOM > openssl.tmp 


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

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

More information about the Gnupg-devel mailing list