Files
s390-tools/genprotimg/samples/check_hostkeydoc
Marc Hartmayer 70f1dcd770 genprotimg/check_hostkeydoc: improve documentation
+ remove outdated comment that the revocation list checking is not implemented
 + improve usage example

Reviewed-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-07-24 13:01:09 +02:00

276 lines
6.1 KiB
Bash
Executable File

#!/bin/sh
#
# check_hostkeydoc - Verify an IBM Secure Execution host key document
#
# Sample script to verify that a host key document is genuine by
# verifying the issuer, the validity date and the signature.
# Optionally verify the full trust chain using a CA certficate.
#
# Sample invocation:
#
# ./check_hostkeydoc HKD1234.crt ibm-z-host-key-signing.crt -c DigiCertCA.crt -r ibm-z-host-key.crl
#
# Copyright IBM Corp. 2020
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
# Allocate temporary files
ISSUER_PUBKEY_FILE=$(mktemp)
SIGNATURE_FILE=$(mktemp)
BODY_FILE=$(mktemp)
ISSUER_DN_FILE=$(mktemp)
SUBJECT_DN_FILE=$(mktemp)
DEF_ISSUER_DN_FILE=$(mktemp)
CRL_SERIAL_FILE=$(mktemp)
# Cleanup on exit
cleanup()
{
rm -f $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE \
$ISSUER_DN_FILE $SUBJECT_DN_FILE $DEF_ISSUER_DN_FILE \
$CRL_SERIAL_FILE
}
trap cleanup EXIT
# Enhanced error checking for bash
if [ -n "${BASH}" ]
then
set -o posix
set -o pipefail
set -o nounset
fi
set -e
# Usage
usage()
{
cat <<-EOF
Usage: `basename $1` host-key-doc signing-key-cert [-c CA-cert] [-r CRL]
Verify an IBM Secure Execution host key document against
a signing key.
Note that in order to have the full trust chain verified
it is necessary to provide the issueing CA's certificate.
EOF
}
check_verify_chain()
{
# Verify certificate chain in case a CA certificate file/bundle
# was specified on the command line.
if [ $# = 1 ]
then
cat >&2 <<-EOF
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
No CA certificate specified! Skipping trust chain verification.
Make sure that '$1' is a valid certificate.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
EOF
else
openssl verify -crl_download -crl_check $2 &&
openssl verify -crl_download -crl_check -untrusted $2 $1 ||
exit 1
fi
}
extract_pubkey()
{
openssl x509 -in $1 -pubkey -noout > $2
}
extract_signature()
{
# Assuming that the last field is the signature
SIGOFFSET=$(openssl asn1parse -in $1 | tail -1 | cut -d : -f 1)
openssl asn1parse -in $1 -out $2 -strparse $SIGOFFSET -noout
}
extract_body()
{
# Assuming that the first field is the full cert body
SIGOFFSET=$(openssl asn1parse -in $1 | head -2 | tail -1 | cut -d : -f 1)
openssl asn1parse -in $1 -out $2 -strparse $SIGOFFSET -noout
}
verify_signature()
{
# Assuming that the signature algorithm is SHA512 with RSA
openssl sha512 -verify $1 -signature $2 $3
}
canonical_dn()
{
OBJTYPE=$1
OBJ=$2
DNTYPE=$3
OUTPUT=$4
openssl $OBJTYPE -in $OBJ -$DNTYPE -noout -nameopt multiline \
| sort | grep -v $DNTYPE= > $OUTPUT
}
default_issuer()
{
cat <<-EOF
commonName = International Business Machines Corporation
countryName = US
localityName = Poughkeepsie
organizationalUnitName = IBM Z Host Key Signing Service
organizationName = International Business Machines Corporation
stateOrProvinceName = New York
EOF
}
verify_issuer_files()
{
default_issuer > $DEF_ISSUER_DN_FILE
if ! diff $ISSUER_DN_FILE $DEF_ISSUER_DN_FILE
then
echo Incorrect default issuer >&2 && exit 1
fi
if diff $ISSUER_DN_FILE $SUBJECT_DN_FILE
then
echo Issuer verification OK
else
echo Issuer verification failed >&2 && exit 1
fi
}
cert_time()
{
DATE=$(openssl x509 -in $1 -$2 -noout | sed "s/^.*=//")
date -d "$DATE" +%s
}
crl_time()
{
DATE=$(openssl crl -in $1 -$2 -noout | sed "s/^.*=//")
date -d "$DATE" +%s
}
verify_dates()
{
START="$1"
END="$2"
MSG="${3:-Certificate}"
NOW=$(date +%s)
if [ $START -le $NOW -a $NOW -le $END ]
then
echo "${MSG} dates are OK"
else
echo "${MSG} date verification failed" >&2 && exit 1
fi
}
crl_serials()
{
openssl crl -in $1 -text -noout | \
grep "Serial Number" > $CRL_SERIAL_FILE
}
check_serial()
{
CERT_SERIAL=$(openssl x509 -in $1 -noout -serial | cut -d = -f 2)
grep -q $CERT_SERIAL $CRL_SERIAL_FILE
}
check_file()
{
[ $# = 0 ] ||
[ -e "$1" ] ||
(echo "File '$1' not found" >&2 && exit 1)
}
# check args
CRL_FILE=
CA_FILE=
args=$(getopt -qu "r:c:h" $*)
if [ $? = 0 ]
then
set -- $args
while [ $1 != "" ]
do
case $1 in
-r) CRL_FILE=$2; shift 2;;
-c) CA_FILE=$2; shift 2;;
-h) usage $0; exit 0;;
--) shift; break;;
esac
done
else
usage $0 >&2
exit 1
fi
if [ $# -ne 2 ]
then
usage $0 >&2
exit 1
fi
HKD_FILE=$1
HKSK_FILE=$2
# Check whether all specified files exist
check_file $HKD_FILE
check_file $HKSK_FILE
check_file $CA_FILE
check_file $CRL_FILE
# Check trust chain
check_verify_chain $HKSK_FILE $CA_FILE
# Verify host key document signature
echo -n "Checking host key document signature: "
extract_pubkey $HKSK_FILE $ISSUER_PUBKEY_FILE &&
extract_signature $HKD_FILE $SIGNATURE_FILE &&
extract_body $HKD_FILE $BODY_FILE &&
verify_signature $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE ||
exit 1
# Verify the issuer
canonical_dn x509 $HKD_FILE issuer $ISSUER_DN_FILE
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
verify_issuer_files
# Verify dates
verify_dates $(cert_time $HKD_FILE startdate) $(cert_time $HKD_FILE enddate)
# Check CRL if specified
if [ -n "$CRL_FILE" ]
then
echo -n "Checking CRL signature: "
extract_signature $CRL_FILE $SIGNATURE_FILE &&
extract_body $CRL_FILE $BODY_FILE &&
verify_signature $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE ||
exit 1
echo -n "CRL "
canonical_dn crl $CRL_FILE issuer $ISSUER_DN_FILE
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
verify_issuer_files
verify_dates $(crl_time $CRL_FILE lastupdate) $(crl_time $CRL_FILE nextupdate) 'CRL'
crl_serials $CRL_FILE
check_serial $HKD_FILE &&
echo "Certificate is revoked, do not use it anymore!" >&2 &&
exit 1
fi
# We made it
echo All checks reqested for \'$HKD_FILE\' were successful