Skip to content

Commit 2a91d66

Browse files
committed
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]>
1 parent 504fd37 commit 2a91d66

File tree

4 files changed

+392
-0
lines changed

4 files changed

+392
-0
lines changed

tests/ca.conf

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
[ ca ]
2+
default_ca = CA_default
3+
4+
[ CA_default ]
5+
dir = REPLACE_ROOT_CA_DIR
6+
certs = $dir/certs
7+
crl_dir = $dir/crl
8+
new_certs_dir = $dir/certs
9+
database = $dir/index.txt
10+
serial = $dir/serial
11+
RANDFILE = $dir/.rand
12+
13+
private_key = $dir/private.pem
14+
certificate = $dir/cacert.pem
15+
16+
crlnumber = $dir/crl/crlnumber
17+
crl = $dir/crl/ca.crl.pem
18+
crl_extensions = crl_ext
19+
default_crl_days = 30
20+
21+
default_md = sha256
22+
23+
name_opt = ca_default
24+
cert_opt = ca_default
25+
default_days = 375
26+
preserve = no
27+
policy = policy_strict
28+
29+
[ CA_intermediate ]
30+
dir = REPLACE_INTERMEDIATE_CA_DIR
31+
certs = $dir/certs
32+
crl_dir = $dir/crl
33+
new_certs_dir = $dir/certs
34+
database = $dir/index.txt
35+
serial = $dir/serial
36+
RANDFILE = $dir/.rand
37+
38+
private_key = $dir/private.pem
39+
certificate = $dir/cacert.pem
40+
41+
crlnumber = $dir/crl/crlnumber
42+
crl = $dir/crl/intermediate.crl.pem
43+
crl_extensions = crl_ext
44+
default_crl_days = 30
45+
46+
default_md = sha256
47+
48+
name_opt = ca_default
49+
cert_opt = ca_default
50+
default_days = 375
51+
preserve = no
52+
policy = policy_loose
53+
unique_subject = no
54+
55+
[ policy_strict ]
56+
countryName = match
57+
stateOrProvinceName = match
58+
organizationName = match
59+
organizationalUnitName = optional
60+
commonName = optional
61+
emailAddress = optional
62+
63+
[ policy_loose ]
64+
countryName = match
65+
stateOrProvinceName = optional
66+
localityName = optional
67+
organizationName = optional
68+
organizationalUnitName = optional
69+
commonName = optional
70+
emailAddress = optional
71+
72+
[ req ]
73+
prompt = no
74+
default_bits = 2048
75+
distinguished_name = req_distinguished_name
76+
string_mask = utf8only
77+
78+
default_md = sha256
79+
80+
x509_extensions = v3_ca
81+
82+
[ req_distinguished_name ]
83+
C = US
84+
ST = MA
85+
L = Lexington
86+
O = Keylime Tests
87+
88+
[ v3_ca ]
89+
subjectKeyIdentifier = hash
90+
authorityKeyIdentifier = keyid:always,issuer
91+
basicConstraints = critical, CA:true
92+
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
93+
94+
[ v3_intermediate_ca ]
95+
subjectKeyIdentifier = hash
96+
authorityKeyIdentifier = keyid:always,issuer
97+
basicConstraints = critical, CA:true, pathlen:0
98+
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
99+
100+
[ server_cert ]
101+
# Extensions for server certificates (`man x509v3_config`).
102+
basicConstraints = CA:FALSE
103+
nsCertType = server
104+
nsComment = "OpenSSL Generated Server Certificate"
105+
subjectKeyIdentifier = hash
106+
authorityKeyIdentifier = keyid,issuer:always
107+
keyUsage = critical, digitalSignature, keyEncipherment
108+
extendedKeyUsage = serverAuth
109+
# These OIDs are taken from the SubjectAltName from section 8.1 of the TPM 2.0 Keys for Device Identity and Attestation
110+
# https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf
111+
subjectAltName=DER:306FA06D06082B06010505070804A061305F0605678105010204565354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

tests/generate-iak-idevid-certs.sh

+275
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#!/bin/bash
2+
3+
# Generate a test root CA and intermediate CA keys and certificates
4+
# Then, generate IAK and IDevID keys inside the TPM and certificates signed by
5+
# the interemediate CA
6+
7+
GIT_ROOT=$(git rev-parse --show-toplevel) || {
8+
echo "Please run this script from inside the rust-keylime repository tree"
9+
exit 1
10+
}
11+
12+
TESTS_DIR=${GIT_ROOT}/tests
13+
GIT_CA_CONF=${TESTS_DIR}/ca.conf
14+
CA_PWORD=keylime
15+
16+
# It is expected that the TCTI and TPM2TOOLS_TCTI environment variables are set
17+
# before running the script
18+
19+
if [[ -z "$TCTI" ]]; then
20+
echo "TCTI environment variable not set; using default /dev/tpmrm0"
21+
TCTI=device:/dev/tpmrm0
22+
fi
23+
24+
if [[ -z "$TPM2TOOLS_TCTI" ]]; then
25+
echo "TPM2TOOLS_TCTI environment variable not set; using default /dev/tpmrm0"
26+
TPM2TOOLS_TCTI=device:/dev/tpmrm0
27+
fi
28+
29+
if [[ -z "$TPM2OPENSSL_TCTI" ]]; then
30+
echo "TPM2OPENSSL_TCTI environment variable not set; using default /dev/tpmrm0"
31+
TPM2OPENSSL_TCTI=device:/dev/tpmrm0
32+
fi
33+
34+
# Check that tpm2-openssl provider is available
35+
if ! openssl list -provider tpm2 -providers; then
36+
echo "Please install the tpm2-openssl provider"
37+
exit 1
38+
fi
39+
40+
function usage {
41+
echo "Usage: $0 [--output OUTPUT_DIR][--pwd CA_PASSWORD]"
42+
exit 0
43+
}
44+
45+
while [[ $# -gt 0 ]]; do
46+
case $1 in
47+
-o|--output)
48+
shift
49+
if [[ $# -gt 0 ]]; then
50+
OUTPUTDIR="$1"
51+
shift
52+
else
53+
echo "Missing path to output directory"
54+
usage
55+
fi
56+
;;
57+
-p|--pwd)
58+
shift
59+
if [[ $# -gt 0 ]]; then
60+
CA_PWORD="$1"
61+
shift
62+
else
63+
echo "Missing password"
64+
usage
65+
fi
66+
;;
67+
*)
68+
# Ignore unknown options
69+
shift
70+
;;
71+
esac
72+
done
73+
74+
# If the output directory is not set, create a temporary directory to output the
75+
# certificates
76+
if [[ -z "$OUTPUTDIR" ]]; then
77+
TEMPDIR=$(mktemp -d)
78+
OUTPUTDIR="${TEMPDIR}/certs"
79+
mkdir -p "${OUTPUTDIR}"
80+
fi
81+
82+
echo "Writing the certificates to the directory ${OUTPUTDIR}"
83+
84+
# Generate IAK/IDevID CA certificates
85+
mkdir -p "${OUTPUTDIR}/root"
86+
87+
# Copy CA configuration to output directory
88+
CA_CONF=${OUTPUTDIR}/ca.conf
89+
cp "${GIT_CA_CONF}" "${OUTPUTDIR}/ca.conf"
90+
91+
ROOT_CA_DIR="${OUTPUTDIR}/root"
92+
INTERMEDIATE_CA_DIR="${OUTPUTDIR}/intermediate"
93+
94+
# Replace the output directory path accordingly
95+
sed -i "s|REPLACE_ROOT_CA_DIR|${ROOT_CA_DIR}|" "${CA_CONF}"
96+
sed -i "s|REPLACE_INTERMEDIATE_CA_DIR|${INTERMEDIATE_CA_DIR}|" "${CA_CONF}"
97+
98+
pushd "${OUTPUTDIR}" > /dev/null || exit 1
99+
mkdir -p root root/crl root/certs
100+
pushd root > /dev/null || exit 1
101+
touch index.txt
102+
echo 1000 > serial
103+
104+
# Create private key for root CA certificate
105+
openssl genrsa \
106+
-aes256 \
107+
-passout "pass:${CA_PWORD}" \
108+
-out private.pem 4096
109+
110+
# Create self-signed root CA certificate
111+
openssl req \
112+
-config "${CA_CONF}" \
113+
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime Test Root CA" \
114+
-key private.pem \
115+
-passin "pass:${CA_PWORD}" \
116+
-new \
117+
-x509 \
118+
-days 9999 \
119+
-sha384 \
120+
-extensions v3_ca \
121+
-out cacert.pem
122+
popd > /dev/null || exit 1
123+
124+
# Create intermediate CA keys and certificate
125+
mkdir -p intermediate
126+
pushd intermediate > /dev/null || exit 1
127+
mkdir certs csr crl
128+
touch index.txt
129+
echo 1000 > serial
130+
131+
# Create private keys for intermediary CA
132+
openssl genrsa \
133+
-aes256 \
134+
-passout "pass:${CA_PWORD}" \
135+
-out private.pem 4096
136+
137+
# Create CSR for the intermediate CA
138+
openssl req \
139+
-config "${CA_CONF}" \
140+
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime Test Intermediate CA" \
141+
-key private.pem \
142+
-passin "pass:${CA_PWORD}" \
143+
-new \
144+
-sha256 \
145+
-out csr/intermediate.csr.pem
146+
147+
# Create certs and cert chain for the intermediate CA
148+
openssl ca \
149+
-config "${CA_CONF}" \
150+
-extensions v3_intermediate_ca \
151+
-keyfile "${ROOT_CA_DIR}/private.pem" \
152+
-cert "${ROOT_CA_DIR}/cacert.pem" \
153+
-days 9998 \
154+
-notext \
155+
-md sha384 \
156+
-batch \
157+
-in csr/intermediate.csr.pem \
158+
-passin "pass:${CA_PWORD}" \
159+
-out cacert.pem
160+
popd > /dev/null || exit 1
161+
cat intermediate/cacert.pem root/cacert.pem \
162+
> cert-chain.pem
163+
popd > /dev/null || exit 1
164+
165+
mkdir "${OUTPUTDIR}/ikeys"
166+
pushd "${OUTPUTDIR}/ikeys" > /dev/null || exit 1
167+
168+
# The templates used in order to regenerate the IDevID and IAK keys are
169+
# taken from the TCG document "TPM 2.0 Keys for Device Identity and
170+
# Attestation:
171+
#
172+
# https://trustedcomputinggroup.org/wp-content/uploads/TPM-2p0-Keys-for-Device-Identity-and-Attestation_v1_r12_pub10082021.pdf
173+
#
174+
# The template H-1 is used here.
175+
#
176+
# The unique values piped in via xxd for the '-u -' parameter are 'IDevID' and
177+
# 'IAK' strings in hex, as defined in section 7.3.1
178+
#
179+
# The attributes (-a) and algorithms (-g, -G) are specified in 7.3.4.1 Table
180+
# 3 and 7.3.4.2 Table 4 respectively
181+
#
182+
# The policy values (-L) are specified in 7.3.6.6 Table 19
183+
184+
# Regenerate IDevID within TPM
185+
echo -n 494445564944 | xxd -r -p | tpm2_createprimary -C e \
186+
-g sha256 \
187+
-G rsa2048:null:null \
188+
-a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|adminwithpolicy|sign' \
189+
-L 'ad6b3a2284fd698a0710bf5cc1b9bdf15e2532e3f601fa4b93a6a8fa8de579ea' \
190+
-u - \
191+
-c idevid.ctx -o idevid.pub.pem
192+
193+
# Persist IDevID and save handle index
194+
tpm2_evictcontrol -c idevid.ctx | grep -o '0x.*$' > idevid.handle
195+
196+
# Create CSRs for the IDevID and sign with the intermediate CA
197+
openssl req \
198+
-config "${CA_CONF}" \
199+
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime IDevID" \
200+
-provider tpm2 \
201+
-provider default \
202+
-propquery '?provider=tpm2' \
203+
-new \
204+
-key "handle:$(cat idevid.handle)" \
205+
-out "${INTERMEDIATE_CA_DIR}/csr/idevid.csr.pem"
206+
207+
openssl ca \
208+
-config "${CA_CONF}" \
209+
-name CA_intermediate \
210+
-extensions server_cert \
211+
-days 999 \
212+
-notext \
213+
-passin "pass:${CA_PWORD}" \
214+
-batch -md sha384 \
215+
-in "${INTERMEDIATE_CA_DIR}/csr/idevid.csr.pem" \
216+
-out "${OUTPUTDIR}/idevid.cert.pem"
217+
218+
# Evict the persisted IDevID key using the handle and cleanup any transient
219+
# object
220+
tpm2_evictcontrol -c "$(cat idevid.handle)"
221+
tpm2_flushcontext -t -l -s
222+
223+
# Regenerate IAK within TPM
224+
echo -n 49414b | xxd -r -p | tpm2_createprimary -C e \
225+
-g sha256 \
226+
-G rsa2048:rsapss-sha256:null \
227+
-a 'fixedtpm|fixedparent|sensitivedataorigin|userwithauth|adminwithpolicy|sign|restricted' \
228+
-L '5437182326e414fca797d5f174615a1641f61255797c3a2b22c21d120b2d1e07' \
229+
-u - \
230+
-c iak.ctx -o iak.pub.pem
231+
232+
# Persist IAK and save handle index
233+
tpm2_evictcontrol -c iak.ctx | grep -o '0x.*$' > iak.handle
234+
235+
# Create CSRs for the IAK and sign with the intermediate CA
236+
openssl req \
237+
-config "${CA_CONF}" \
238+
-subj "/C=US/ST=MA/L=Lexington/O=Keylime Tests/CN=Keylime IAK" \
239+
-provider tpm2 \
240+
-provider default \
241+
-propquery '?provider=tpm2' \
242+
-new \
243+
-key "handle:$(cat iak.handle)" \
244+
-out "${INTERMEDIATE_CA_DIR}/csr/iak.csr.pem"
245+
246+
openssl ca \
247+
-config "${CA_CONF}" \
248+
-name CA_intermediate \
249+
-extensions server_cert -days 999 \
250+
-notext \
251+
-passin "pass:${CA_PWORD}" \
252+
-batch \
253+
-md sha384 \
254+
-in "${INTERMEDIATE_CA_DIR}/csr/iak.csr.pem" \
255+
-out "${OUTPUTDIR}/iak.cert.pem"
256+
257+
# Evict the persisted IAK key using the handle and cleanup any transient
258+
# object
259+
tpm2_evictcontrol -c "$(cat iak.handle)"
260+
tpm2_flushcontext -t -l -s
261+
262+
# Convert certs to DER
263+
openssl x509 \
264+
-inform PEM \
265+
-outform DER \
266+
-in "${OUTPUTDIR}/idevid.cert.pem" \
267+
-out "${OUTPUTDIR}/idevid.cert.der"
268+
269+
openssl x509 \
270+
-inform PEM \
271+
-outform DER \
272+
-in "${OUTPUTDIR}/iak.cert.pem" \
273+
-out "${OUTPUTDIR}/iak.cert.der"
274+
popd > /dev/null || exit 1
275+

0 commit comments

Comments
 (0)