-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: Add script to generate IAK and IDevID certificates
The script generates a test root CA and intermediate CA keys and certificates. The output directory can be set via the --output option, and the CA password with the --pwd option. If an output directory is not set, a temporary directory is created and the certificates are placed there. Then, the script generates the IDevID and IAK keys inside the TPM and respective certificates. The script requires the tpm2-openssl provider to access the keys inside the TPM. It is recommended to set the TCTI, TPM2TOOLS_TCTI, and TPM2OPENSSL_TCTI environment variables to set which TPM to use when running the script. If these variables are not set, the default value `device:/dev/tpmrm0` is used instead. This also modifies the tests/setup_swtpm.sh and tests/run.sh to configure the TPM2OPENSSL_TCTI to use the swtpm with the tpm2-openssl provider. Signed-off-by: Anderson Toshiyuki Sasaki <[email protected]>
- Loading branch information
Showing
4 changed files
with
392 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
[ ca ] | ||
default_ca = CA_default | ||
|
||
[ CA_default ] | ||
dir = REPLACE_ROOT_CA_DIR | ||
certs = $dir/certs | ||
crl_dir = $dir/crl | ||
new_certs_dir = $dir/certs | ||
database = $dir/index.txt | ||
serial = $dir/serial | ||
RANDFILE = $dir/.rand | ||
|
||
private_key = $dir/private.pem | ||
certificate = $dir/cacert.pem | ||
|
||
crlnumber = $dir/crl/crlnumber | ||
crl = $dir/crl/ca.crl.pem | ||
crl_extensions = crl_ext | ||
default_crl_days = 30 | ||
|
||
default_md = sha256 | ||
|
||
name_opt = ca_default | ||
cert_opt = ca_default | ||
default_days = 375 | ||
preserve = no | ||
policy = policy_strict | ||
|
||
[ CA_intermediate ] | ||
dir = REPLACE_INTERMEDIATE_CA_DIR | ||
certs = $dir/certs | ||
crl_dir = $dir/crl | ||
new_certs_dir = $dir/certs | ||
database = $dir/index.txt | ||
serial = $dir/serial | ||
RANDFILE = $dir/.rand | ||
|
||
private_key = $dir/private.pem | ||
certificate = $dir/cacert.pem | ||
|
||
crlnumber = $dir/crl/crlnumber | ||
crl = $dir/crl/intermediate.crl.pem | ||
crl_extensions = crl_ext | ||
default_crl_days = 30 | ||
|
||
default_md = sha256 | ||
|
||
name_opt = ca_default | ||
cert_opt = ca_default | ||
default_days = 375 | ||
preserve = no | ||
policy = policy_loose | ||
unique_subject = no | ||
|
||
[ policy_strict ] | ||
countryName = match | ||
stateOrProvinceName = match | ||
organizationName = match | ||
organizationalUnitName = optional | ||
commonName = optional | ||
emailAddress = optional | ||
|
||
[ policy_loose ] | ||
countryName = match | ||
stateOrProvinceName = optional | ||
localityName = optional | ||
organizationName = optional | ||
organizationalUnitName = optional | ||
commonName = optional | ||
emailAddress = optional | ||
|
||
[ req ] | ||
prompt = no | ||
default_bits = 2048 | ||
distinguished_name = req_distinguished_name | ||
string_mask = utf8only | ||
|
||
default_md = sha256 | ||
|
||
x509_extensions = v3_ca | ||
|
||
[ req_distinguished_name ] | ||
C = US | ||
ST = MA | ||
L = Lexington | ||
O = Keylime Tests | ||
|
||
[ v3_ca ] | ||
subjectKeyIdentifier = hash | ||
authorityKeyIdentifier = keyid:always,issuer | ||
basicConstraints = critical, CA:true | ||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign | ||
|
||
[ v3_intermediate_ca ] | ||
subjectKeyIdentifier = hash | ||
authorityKeyIdentifier = keyid:always,issuer | ||
basicConstraints = critical, CA:true, pathlen:0 | ||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign | ||
|
||
[ server_cert ] | ||
# Extensions for server certificates (`man x509v3_config`). | ||
basicConstraints = CA:FALSE | ||
nsCertType = server | ||
nsComment = "OpenSSL Generated Server Certificate" | ||
subjectKeyIdentifier = hash | ||
authorityKeyIdentifier = keyid,issuer:always | ||
keyUsage = critical, digitalSignature, keyEncipherment | ||
extendedKeyUsage = serverAuth | ||
# These OIDs are taken from the SubjectAltName from section 8.1 of the TPM 2.0 Keys for Device Identity and Attestation | ||
# https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf | ||
subjectAltName=DER:306FA06D06082B06010505070804A061305F0605678105010204565354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
#!/bin/bash | ||
|
||
# Generate a test root CA and intermediate CA keys and certificates | ||
# Then, generate IAK and IDevID keys inside the TPM and certificates signed by | ||
# the interemediate CA | ||
|
||
GIT_ROOT=$(git rev-parse --show-toplevel) | ||
if [[ $? -ne 0 ]]; then | ||
echo "Please run this script from inside the rust-keylime repository tree" | ||
fi | ||
|
||
TESTS_DIR=${GIT_ROOT}/tests | ||
GIT_CA_CONF=${TESTS_DIR}/ca.conf | ||
CA_PWD=keylime | ||
|
||
# It is expected that the TCTI and TPM2TOOLS_TCTI environment variables are set | ||
# before running the script | ||
|
||
if [[ -z "$TCTI" ]]; then | ||
echo "TCTI environment variable not set; using default /dev/tpmrm0" | ||
TCTI=device:/dev/tpmrm0 | ||
fi | ||
|
||
if [[ -z "$TPM2TOOLS_TCTI" ]]; then | ||
echo "TPM2TOOLS_TCTI environment variable not set; using default /dev/tpmrm0" | ||
TPM2TOOLS_TCTI=device:/dev/tpmrm0 | ||
fi | ||
|
||
if [[ -z "$TPM2OPENSSL_TCTI" ]]; then | ||
echo "TPM2OPENSSL_TCTI environment variable not set; using default /dev/tpmrm0" | ||
TPM2OPENSSL_TCTI=device:/dev/tpmrm0 | ||
fi | ||
|
||
# Check that tpm2-openssl provider is available | ||
if ! openssl list -provider tpm2 -providers; then | ||
echo "Please install the tpm2-openssl provider" | ||
exit 1 | ||
fi | ||
|
||
function usage { | ||
echo "Usage: $0 [--output OUTPUT_DIR][--pwd CA_PASSWORD]" | ||
exit 0 | ||
} | ||
|
||
while [[ $# -gt 0 ]]; do | ||
case $1 in | ||
-o|--output) | ||
shift | ||
if [[ $# -gt 0 ]]; then | ||
OUTPUTDIR="$1" | ||
shift | ||
else | ||
echo "Missing path to output directory" | ||
usage | ||
fi | ||
;; | ||
-p|--pwd) | ||
shift | ||
if [[ $# -gt 0 ]]; then | ||
CA_PWD="$1" | ||
shift | ||
else | ||
echo "Missing password" | ||
usage | ||
fi | ||
;; | ||
*) | ||
# Ignore unknown options | ||
shift | ||
;; | ||
esac | ||
done | ||
|
||
# If the output directory is not set, create a temporary directory to output the | ||
# certificates | ||
if [[ -z "$OUTPUTDIR" ]]; then | ||
TEMPDIR=$(mktemp -d) | ||
OUTPUTDIR="${TEMPDIR}/certs" | ||
mkdir -p ${OUTPUTDIR} | ||
fi | ||
|
||
echo "Writing the certificates to the directory ${OUTPUTDIR}" | ||
|
||
# Generate IAK/IDevID CA certificates | ||
mkdir -p ${OUTPUTDIR}/root | ||
|
||
# Copy CA configuration to output directory | ||
CA_CONF=${OUTPUTDIR}/ca.conf | ||
cp ${GIT_CA_CONF} ${OUTPUTDIR}/ca.conf | ||
|
||
ROOT_CA_DIR=${OUTPUTDIR}/root | ||
INTERMEDIATE_CA_DIR=${OUTPUTDIR}/intermediate | ||
|
||
# Replace the output directory path accordingly | ||
sed -i "s|REPLACE_ROOT_CA_DIR|${ROOT_CA_DIR}|" ${CA_CONF} | ||
sed -i "s|REPLACE_INTERMEDIATE_CA_DIR|${INTERMEDIATE_CA_DIR}|" ${CA_CONF} | ||
|
||
pushd ${OUTPUTDIR} | ||
mkdir -p root root/crl root/certs | ||
pushd root | ||
touch index.txt | ||
echo 1000 > serial | ||
|
||
# Create private key for root CA certificate | ||
openssl genrsa \ | ||
-aes256 \ | ||
-passout pass:${CA_PWORD} \ | ||
-out private.pem 4096 | ||
|
||
# Create self-signed root CA certificate | ||
openssl req \ | ||
-config ${CA_CONF} \ | ||
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime Test Root CA" \ | ||
-key private.pem \ | ||
-passin pass:${CA_PWORD} \ | ||
-new \ | ||
-x509 \ | ||
-days 9999 \ | ||
-sha384 \ | ||
-extensions v3_ca \ | ||
-out cacert.pem | ||
popd | ||
|
||
# Create intermediate CA keys and certificate | ||
mkdir -p intermediate | ||
pushd intermediate | ||
mkdir certs csr crl | ||
touch index.txt | ||
echo 1000 > serial | ||
|
||
# Create private keys for intermediary CA | ||
openssl genrsa \ | ||
-aes256 \ | ||
-passout pass:${CA_PWORD} \ | ||
-out private.pem 4096 | ||
|
||
# Create CSR for the intermediate CA | ||
openssl req \ | ||
-config ${CA_CONF} \ | ||
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime Test Intermediate CA" \ | ||
-key private.pem \ | ||
-passin pass:${CA_PWORD} \ | ||
-new \ | ||
-sha256 \ | ||
-out csr/intermediate.csr.pem | ||
|
||
# Create certs and cert chain for the intermediate CA | ||
openssl ca \ | ||
-config ${CA_CONF} \ | ||
-extensions v3_intermediate_ca \ | ||
-keyfile ${ROOT_CA_DIR}/private.pem \ | ||
-cert ${ROOT_CA_DIR}/cacert.pem \ | ||
-days 9998 \ | ||
-notext \ | ||
-md sha384 \ | ||
-batch \ | ||
-in csr/intermediate.csr.pem \ | ||
-passin pass:${CA_PWORD} \ | ||
-out cacert.pem | ||
popd | ||
cat intermediate/cacert.pem root/cacert.pem \ | ||
> cert-chain.pem | ||
popd | ||
|
||
mkdir ${OUTPUTDIR}/ikeys | ||
pushd ${OUTPUTDIR}/ikeys | ||
|
||
# The templates used in order to regenerate the IDevID and IAK keys are | ||
# taken from the TCG document "TPM 2.0 Keys for Device Identity and | ||
# Attestation: | ||
# | ||
# https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf | ||
# | ||
# The template H-1 is used here. | ||
# | ||
# The unique values piped in via xxd for the '-u -' parameter are 'IDevID' and | ||
# 'IAK' strings in hex, as defined in section 7.3.1 | ||
# | ||
# The attributes (-a) and algorithms (-g, -G) are specified in 7.3.4.1 Table | ||
# 3 and 7.3.4.2 Table 4 respectively | ||
# | ||
# The policy values (-L) are specified in 7.3.6.6 Table 19 | ||
|
||
# Regenerate IDevID within TPM | ||
echo -n 494445564944 | xxd -r -p | tpm2_createprimary -C e \ | ||
-g sha256 \ | ||
-G rsa2048:null:null \ | ||
-a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|adminwithpolicy|sign' \ | ||
-L 'ad6b3a2284fd698a0710bf5cc1b9bdf15e2532e3f601fa4b93a6a8fa8de579ea' \ | ||
-u - \ | ||
-c idevid.ctx -o idevid.pub.pem | ||
|
||
# Persist IDevID and save handle index | ||
tpm2_evictcontrol -c idevid.ctx | grep -o '0x.*$' > idevid.handle | ||
|
||
# Create CSRs for the IDevID and sign with the intermediate CA | ||
openssl req \ | ||
-config ${CA_CONF} \ | ||
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime IDevID" \ | ||
-provider tpm2 \ | ||
-provider default \ | ||
-propquery '?provider=tpm2' \ | ||
-new \ | ||
-key handle:$(cat idevid.handle) \ | ||
-out ${INTERMEDIATE_CA_DIR}/csr/idevid.csr.pem | ||
|
||
openssl ca \ | ||
-config ${CA_CONF} \ | ||
-name CA_intermediate \ | ||
-extensions server_cert \ | ||
-days 999 \ | ||
-notext \ | ||
-passin pass:${CA_PWORD} \ | ||
-batch -md sha384 \ | ||
-in ${INTERMEDIATE_CA_DIR}/csr/idevid.csr.pem \ | ||
-out ${OUTPUTDIR}/idevid.cert.pem | ||
|
||
# Evict the persisted IDevID key using the handle and cleanup any transient | ||
# object | ||
tpm2_evictcontrol -c $(cat idevid.handle) | ||
tpm2_flushcontext -t -l -s | ||
|
||
# Regenerate IAK within TPM | ||
echo -n 49414b | xxd -r -p | tpm2_createprimary -C e \ | ||
-g sha256 \ | ||
-G rsa2048:rsapss-sha256:null \ | ||
-a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|adminwithpolicy|sign|restricted' \ | ||
-L '5437182326e414fca797d5f174615a1641f61255797c3a2b22c21d120b2d1e07' \ | ||
-u - \ | ||
-c iak.ctx -o iak.pub.pem | ||
|
||
# Persist IAK and save handle index | ||
tpm2_evictcontrol -c iak.ctx | grep -o '0x.*$' > iak.handle | ||
|
||
# Create CSRs for the IAK and sign with the intermediate CA | ||
openssl req \ | ||
-config ${CA_CONF} \ | ||
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime IAK" \ | ||
-provider tpm2 \ | ||
-provider default \ | ||
-propquery '?provider=tpm2' \ | ||
-new \ | ||
-key handle:$(cat iak.handle) \ | ||
-out ${INTERMEDIATE_CA_DIR}/csr/iak.csr.pem | ||
|
||
openssl ca \ | ||
-config ${CA_CONF} \ | ||
-name CA_intermediate \ | ||
-extensions server_cert -days 999 \ | ||
-notext \ | ||
-passin pass:${CA_PWORD} \ | ||
-batch \ | ||
-md sha384 \ | ||
-in ${INTERMEDIATE_CA_DIR}/csr/iak.csr.pem \ | ||
-out ${OUTPUTDIR}/iak.cert.pem | ||
|
||
# Evict the persisted IAK key using the handle and cleanup any transient | ||
# object | ||
tpm2_evictcontrol -c $(cat iak.handle) | ||
tpm2_flushcontext -t -l -s | ||
|
||
# Convert certs to DER | ||
openssl x509 \ | ||
-inform PEM \ | ||
-outform DER \ | ||
-in ${OUTPUTDIR}/idevid.cert.pem \ | ||
-out ${OUTPUTDIR}/idevid.cert.der | ||
|
||
openssl x509 \ | ||
-inform PEM \ | ||
-outform DER \ | ||
-in ${OUTPUTDIR}/iak.cert.pem \ | ||
-out ${OUTPUTDIR}/iak.cert.der | ||
popd | ||
|
Oops, something went wrong.