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