mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-08-08 18:46:56 +00:00
samples: Extend script to create a CA using a TPM 2 for signing
Extend the script that creates a CA that uses a TPM 2 for signing. For this we have to create tokens using the TPM 2 pkcs11 module's tpm2_ptool and can then use the p11tool for creating keys. Add a test case that requires a running tpm2-abrmd and tpm2_ptool. Eventually the test case should (try to) start its own tpm2-abrmd and talk to swtpm directly but the tcti module to do that isn't available as a package, yet. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
eb9cfa963a
commit
f30e202df6
@ -1,4 +1,4 @@
|
||||
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
|
||||
.\" Automatically generated by Pod::Man 4.12 (Pod::Simple 3.39)
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
@ -133,7 +133,7 @@
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "swtpm-create-tpmca 8"
|
||||
.TH swtpm-create-tpmca 8 "2018-10-17" "swtpm" ""
|
||||
.TH swtpm-create-tpmca 8 "2020-04-14" "swtpm" ""
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
@ -209,6 +209,19 @@ The hostname where tcsd is running on. The default hostname is 'localhost'.
|
||||
.IX Item "-tss-tcsd-port"
|
||||
The \s-1TCP\s0 port on which tcsd is listening for messages. The default port is
|
||||
30003.
|
||||
.IP "\fB\-\-tpm2\fR" 4
|
||||
.IX Item "--tpm2"
|
||||
The \s-1TPM\s0 to use for signing the certificates is a \s-1TPM 2\s0 and Intel's \s-1TSS\s0 stack
|
||||
must be running (tpm2\-abrmd) along with its \s-1PKCS11\s0 module.
|
||||
The \s-1TPM 2 PKCS11\s0 module must have been initialized using the tpm2_ptool.
|
||||
.Sp
|
||||
The environment variables \s-1SWTPM_PKCS11_PIN\s0 and \s-1SWTPM_PKCS11_SO_PIN\s0 should be
|
||||
set to hold the PINs. If \s-1SWTPM_PKCS11_PIN\s0 is not set then the default \s-1PIN\s0
|
||||
\&'swtpm\-tpmca' will be used. \s-1SWTPM_PKCS11_SO_PIN\s0 is needed for creating the
|
||||
token and must be explicitly set as an environment variable.
|
||||
.IP "\fB\-\-pid pimary-object-id\fR" 4
|
||||
.IX Item "--pid pimary-object-id"
|
||||
The primary object id that the tpm2_ptool returns upon 'init'.
|
||||
.IP "\fB\-help, \-h, \-?\fR" 4
|
||||
.IX Item "-help, -h, -?"
|
||||
Display the help screen and exit.
|
||||
@ -219,6 +232,9 @@ into /var/lib/swtpm\-localca and the swtpm-localca configuration to
|
||||
/etc/swtpm\-localca.conf. It can then be used for signing certificates of
|
||||
newly created \fBswtpm\fR TPMs.
|
||||
.PP
|
||||
If the host's \s-1TPM\s0 is a \s-1TPM 1.2,\s0 we need to start the tcsd first and can
|
||||
then create the \s-1TPM\s0 key and \s-1TPM CA\s0 certificate:
|
||||
.PP
|
||||
.Vb 10
|
||||
\& #> sudo systemctl start tcsd
|
||||
\& #> sudo /usr/share/swtpm/swtpm\-create\-tpmca \e
|
||||
@ -237,17 +253,57 @@ newly created \fBswtpm\fR TPMs.
|
||||
\& signingkey_password = password
|
||||
\& parentkey_password = password
|
||||
.Ve
|
||||
.PP
|
||||
Alternatively, if the host's \s-1TPM\s0 is a \s-1TPM 2\s0 and Intel's \s-1TPM 2\s0 stack is
|
||||
installed, we need to start tpm2\-abrmd first and can then create the \s-1TPM\s0 key
|
||||
and \s-1TPM CA\s0 certificate:
|
||||
.PP
|
||||
.Vb 10
|
||||
\& #> sudo systemctl start tpm2\-abrmd
|
||||
\& #> tpm2_ptool init
|
||||
\& action: Created
|
||||
\& id: 1 # this is the \-\-pid parameter below
|
||||
\& #> sudo SWTPM_PKCS11_PIN="mypin 123" SWTPM_PKCS11_SO_PIN=123 /usr/share/swtpm/swtpm\-create\-tpmca \e
|
||||
\& \-\-dir /var/lib/swtpm\-localca \e
|
||||
\& \-\-overwrite \e
|
||||
\& \-\-outfile /etc/swtpm\-localca.conf \e
|
||||
\& \-\-group tss \e
|
||||
\& \-\-tpm2 \e
|
||||
\& \-\-pid 1
|
||||
\& statedir = /var/lib/swtpm\-localca
|
||||
\& signingkey = pkcs11:model=SW%20%20%20TPM\e;manufacturer=IBM\e;serial=0000000000000000\e;token=swtpm\-tpmca\-1\e;id=%31\e;object=swtpm\-tpmca\-key\e;type=private
|
||||
\& issuercert = /var/lib/swtpm\-localca/swtpm\-localca\-tpmca\-cert.pem
|
||||
\& certserial = /var/lib/swtpm\-localca/certserial
|
||||
\& SWTPM_PKCS11_PIN = mypin 123
|
||||
.Ve
|
||||
.PP
|
||||
Note: This also works for non-root users by adapting the \-\-dir and \-\-outfile
|
||||
parameters here and below by changing the \-\-dir parameter and adding a \-\-config
|
||||
parameter.
|
||||
.PP
|
||||
To test either one of the above \s-1TPM\s0 CAs, run the following command:
|
||||
.PP
|
||||
.Vb 5
|
||||
\& #> /usr/share/swtpm/swtpm\-localca \e
|
||||
\& \-\-type ek \-\-ek x=11,y=13 \e
|
||||
\& \-\-dir /tmp \-\-vmid test \-\-tpm2 \e
|
||||
\& \-\-tpm\-spec\-family 2.0 \-\-tpm\-spec\-revision 146 \-\-tpm\-spec\-level 00 \e
|
||||
\& \-\-tpm\-model swtpm \-\-tpm\-version 20170101 \-\-tpm\-manufacturer IBM
|
||||
.Ve
|
||||
.PP
|
||||
The \-\-tpm2 in this command indicates that the \s-1TPM\s0 for which the certificate
|
||||
is created is a \s-1TPM 2.\s0
|
||||
.SH "KNOWN ISSUES"
|
||||
.IX Header "KNOWN ISSUES"
|
||||
The interaction of GnuTLS certtool with the \s-1TPM TCSD\s0 daemon may cause so
|
||||
many \s-1TPM\s0 (key) authentication failures, that the \s-1TPM\s0 refuses to accept any
|
||||
many \s-1TPM\s0 (key) authentication failures that the \s-1TPM\s0 refuses to accept any
|
||||
more authenticated commands until the \s-1TPM\s0's owner sends it the
|
||||
TPM_ORD_ResetLockValue command. The reason for this is that certtool first
|
||||
tries to use 20 zero bytes for the \s-1SRK\s0 password and only then prompts for
|
||||
and uses the required \s-1SRK\s0 password. The GnuTLS tpmtool does not support 20
|
||||
zero bytes for the \s-1SRK\s0 password, so forces the usage of a 'real' password.
|
||||
.PP
|
||||
The effect of the authentication failues may be that the \s-1TPM CA\s0 cannot sign
|
||||
The effect of the authentication failures may be that the \s-1TPM CA\s0 cannot sign
|
||||
certificates since the \s-1TPM\s0 does not accept authenticated commands.
|
||||
.SH "SEE ALSO"
|
||||
.IX Header "SEE ALSO"
|
||||
|
||||
@ -85,6 +85,21 @@ The hostname where tcsd is running on. The default hostname is 'localhost'.
|
||||
The TCP port on which tcsd is listening for messages. The default port is
|
||||
30003.
|
||||
|
||||
=item B<--tpm2>
|
||||
|
||||
The TPM to use for signing the certificates is a TPM 2 and Intel's TSS stack
|
||||
must be running (tpm2-abrmd) along with its PKCS11 module.
|
||||
The TPM 2 PKCS11 module must have been initialized using the tpm2_ptool.
|
||||
|
||||
The environment variables SWTPM_PKCS11_PIN and SWTPM_PKCS11_SO_PIN should be
|
||||
set to hold the PINs. If SWTPM_PKCS11_PIN is not set then the default PIN
|
||||
'swtpm-tpmca' will be used. SWTPM_PKCS11_SO_PIN is needed for creating the
|
||||
token and must be explicitly set as an environment variable.
|
||||
|
||||
=item B<--pid pimary-object-id>
|
||||
|
||||
The primary object id that the tpm2_ptool returns upon 'init'.
|
||||
|
||||
=item B<-help, -h, -?>
|
||||
|
||||
Display the help screen and exit.
|
||||
@ -98,6 +113,9 @@ into /var/lib/swtpm-localca and the swtpm-localca configuration to
|
||||
/etc/swtpm-localca.conf. It can then be used for signing certificates of
|
||||
newly created B<swtpm> TPMs.
|
||||
|
||||
If the host's TPM is a TPM 1.2, we need to start the tcsd first and can
|
||||
then create the TPM key and TPM CA certificate:
|
||||
|
||||
#> sudo systemctl start tcsd
|
||||
#> sudo /usr/share/swtpm/swtpm-create-tpmca \
|
||||
--dir /var/lib/swtpm-localca \
|
||||
@ -115,17 +133,54 @@ newly created B<swtpm> TPMs.
|
||||
signingkey_password = password
|
||||
parentkey_password = password
|
||||
|
||||
|
||||
Alternatively, if the host's TPM is a TPM 2 and Intel's TPM 2 stack is
|
||||
installed, we need to start tpm2-abrmd first and can then create the TPM key
|
||||
and TPM CA certificate:
|
||||
|
||||
#> sudo systemctl start tpm2-abrmd
|
||||
#> tpm2_ptool init
|
||||
action: Created
|
||||
id: 1 # this is the --pid parameter below
|
||||
#> sudo SWTPM_PKCS11_PIN="mypin 123" SWTPM_PKCS11_SO_PIN=123 /usr/share/swtpm/swtpm-create-tpmca \
|
||||
--dir /var/lib/swtpm-localca \
|
||||
--overwrite \
|
||||
--outfile /etc/swtpm-localca.conf \
|
||||
--group tss \
|
||||
--tpm2 \
|
||||
--pid 1
|
||||
statedir = /var/lib/swtpm-localca
|
||||
signingkey = pkcs11:model=SW%20%20%20TPM\;manufacturer=IBM\;serial=0000000000000000\;token=swtpm-tpmca-1\;id=%31\;object=swtpm-tpmca-key\;type=private
|
||||
issuercert = /var/lib/swtpm-localca/swtpm-localca-tpmca-cert.pem
|
||||
certserial = /var/lib/swtpm-localca/certserial
|
||||
SWTPM_PKCS11_PIN = mypin 123
|
||||
|
||||
Note: This also works for non-root users by adapting the --dir and --outfile
|
||||
parameters here and below by changing the --dir parameter and adding a --config
|
||||
parameter.
|
||||
|
||||
To test either one of the above TPM CAs, run the following command:
|
||||
|
||||
#> /usr/share/swtpm/swtpm-localca \
|
||||
--type ek --ek x=11,y=13 \
|
||||
--dir /tmp --vmid test --tpm2 \
|
||||
--tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \
|
||||
--tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM
|
||||
|
||||
The --tpm2 in this command indicates that the TPM for which the certificate
|
||||
is created is a TPM 2.
|
||||
|
||||
=head1 KNOWN ISSUES
|
||||
|
||||
The interaction of GnuTLS certtool with the TPM TCSD daemon may cause so
|
||||
many TPM (key) authentication failures, that the TPM refuses to accept any
|
||||
many TPM (key) authentication failures that the TPM refuses to accept any
|
||||
more authenticated commands until the TPM's owner sends it the
|
||||
TPM_ORD_ResetLockValue command. The reason for this is that certtool first
|
||||
tries to use 20 zero bytes for the SRK password and only then prompts for
|
||||
and uses the required SRK password. The GnuTLS tpmtool does not support 20
|
||||
zero bytes for the SRK password, so forces the usage of a 'real' password.
|
||||
|
||||
The effect of the authentication failues may be that the TPM CA cannot sign
|
||||
The effect of the authentication failures may be that the TPM CA cannot sign
|
||||
certificates since the TPM does not accept authenticated commands.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
@ -4,6 +4,7 @@ FLAG_OVERWRITE=1
|
||||
FLAG_REGISTER_KEY=2
|
||||
FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN=4
|
||||
FLAG_SRK_WELL_KNOWN=8
|
||||
FLAG_TPM2=16
|
||||
|
||||
TSS_TCSD_HOSTNAME_DEFAULT=localhost
|
||||
TSS_TCSD_PORT_DEFAULT=30003
|
||||
@ -39,6 +40,14 @@ function get_filesize()
|
||||
fi
|
||||
}
|
||||
|
||||
# Create a config value by escaping the proper characters
|
||||
#
|
||||
# @param 1: The string to escape
|
||||
function escape_pkcs11_url()
|
||||
{
|
||||
echo "$1" | sed 's/;/\\;/g'
|
||||
}
|
||||
|
||||
# Use expect for automating the interaction with the tpmtool
|
||||
#
|
||||
# @param 1...: parameters to pass to tpmtool command line
|
||||
@ -79,6 +88,7 @@ create_localca_cert() {
|
||||
local dir="$2"
|
||||
local outfile="$3"
|
||||
local owner="$4"
|
||||
local pid="$5" # TPM2 parameter
|
||||
|
||||
local cakey=${dir}/swtpm-localca-rootca-privkey.pem
|
||||
local cacert=${dir}/swtpm-localca-rootca-cert.pem
|
||||
@ -86,7 +96,7 @@ create_localca_cert() {
|
||||
local tpmpubkey=${dir}/swtpm-localca-tpmca-pubkey.pem
|
||||
local tpmca=${dir}/swtpm-localca-tpmca-cert.pem
|
||||
local template=${dir}/template
|
||||
local tpmkeyurl params
|
||||
local tpmkeyurl
|
||||
local msg output
|
||||
|
||||
if ! [ -r "${cakey}" ] || ! [ -r "${cacert}" ]; then
|
||||
@ -126,52 +136,147 @@ create_localca_cert() {
|
||||
|
||||
rm -f "${tpmkey}" "${tpmpubkey}" "${tpmca}"
|
||||
|
||||
if [ $((flags & FLAG_SRK_WELL_KNOWN)) -ne 0 ]; then
|
||||
unset GNUTLS_PIN
|
||||
params="--srk-well-known"
|
||||
else
|
||||
export GNUTLS_PIN=${TPM_SRK_PASSWORD}
|
||||
fi
|
||||
if [ $((flags & FLAG_TPM2)) -ne 0 ]; then
|
||||
local tokenurl tpmkeyurl
|
||||
local token="swtpm-tpmca-${pid}"
|
||||
local label="${token}" # must be same
|
||||
local keylabel="swtpm-tpmca-key"
|
||||
local userpin="${SWTPM_PKCS11_PIN:-swtpm-tpmca}"
|
||||
|
||||
if [ $((flags & FLAG_REGISTER_KEY)) -ne 0 ]; then
|
||||
msg="$(run_tpmtool --generate-rsa --signing --register ${params})"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not generate registered signing key with tpmtool"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
tokenurl=$(p11tool --list-tokens 2>&1 | \
|
||||
grep -E ";token=${token}\$" | \
|
||||
sed -n "s/.*URL: //p")
|
||||
if [ -z "${tokenurl}" ]; then
|
||||
if [ -z "${SWTPM_PKCS11_SO_PIN}" ]; then
|
||||
logerr "The env. variable SWTPM_PKCS11_SO_PIN must be set to create token ${label}."
|
||||
return 1
|
||||
fi
|
||||
msg=$(tpm2_ptool addtoken \
|
||||
--pid "${pid}" \
|
||||
--sopin "${SWTPM_PKCS11_SO_PIN}" \
|
||||
--userpin "${userpin}" \
|
||||
--label "${label}" 2>&1)
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Error: Could not create pkcs11 token"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
tokenurl=$(p11tool --list-tokens 2>&1 | \
|
||||
grep -E ";token=${token}\$" | \
|
||||
sed -n "s/.*URL: //p")
|
||||
if [ -z "${tokenurl}" ]; then
|
||||
logerr "Error: Could not get token URL for token '${token}'"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
msg=$(tpm2_ptool config \
|
||||
--key tcti \
|
||||
--value tabrmd \
|
||||
--label "${label}")
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Error: Could not set config value for tcti key"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
export GNUTLS_PIN="${userpin}"
|
||||
# GNUTLS_SO_PIN not needed at this point
|
||||
|
||||
msg="$(p11tool --login --list-keys "${tokenurl}" 2>&1)"
|
||||
if [ $? -eq 0 ]; then
|
||||
tpmkeyurl=$(echo "${msg}" | \
|
||||
grep ";object=${keylabel}" | \
|
||||
sed -n "s/.*URL: //p")
|
||||
fi
|
||||
tpmkeyurl=$(echo "${msg}" | sed -n 's/\(tpmkey:uuid=[^;]*\);.*/\1/p')
|
||||
if [ -z "${tpmkeyurl}" ]; then
|
||||
logerr "Could not parse tpmkey URL"
|
||||
msg=$(tpm2_ptool addkey \
|
||||
"--label=${label}" \
|
||||
"--userpin=${userpin}" \
|
||||
--algorithm=rsa2048 \
|
||||
"--key-label=${keylabel}" \
|
||||
--id 1 2>&1)
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Error: Could not create create key under pkcs11 token ${token}"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
msg="$(p11tool --login --list-keys "${tokenurl}" 2>&1)"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Error: Could not get TPM key URL for ${tokenurl}"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
tpmkeyurl=$(echo "${msg}" | \
|
||||
grep ";object=${keylabel}" | \
|
||||
sed -n "s/.*URL: //p")
|
||||
if [ -z "${tpmkeyurl}" ]; then
|
||||
logerr "Error: Could not get TPM key URL for ${tokenurl}"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
rm -f "${tpmpubkey}"
|
||||
|
||||
msg=$(p11tool --export-pubkey "${tpmkeyurl}" --login --outfile "${tpmpubkey}" 2>&1)
|
||||
if [ $? -ne 0 ] || \
|
||||
[ ! -r "${tpmpubkey}" ] || [ $(get_filesize "${tpmpubkey}") -eq 0 ]; then
|
||||
logerr "Error: Could not get TPM public key"
|
||||
logerr "${msg}"
|
||||
rm -f "${tpmkey}" "${tpmpubkey}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
rm -f "${tpmkey}"
|
||||
msg="$(run_tpmtool --generate-rsa --signing --outfile \"${tpmkey}\" ${params})"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not create signing key with tpmtool"
|
||||
logerr "${msg}"
|
||||
rm -f "${tpmkey}"
|
||||
return 1
|
||||
fi
|
||||
if [ ! -r "${tpmkey}" ] || [ $(get_filesize "${tpmkey}") -eq 0 ]; then
|
||||
logerr "The TPM key file ${tpmkey} was not written properly"
|
||||
rm -f "${tpmkey}"
|
||||
return 1
|
||||
fi
|
||||
chmod 640 "${tpmkey}"
|
||||
tpmkeyurl="tpmkey:file=${tpmkey}"
|
||||
fi
|
||||
local params=""
|
||||
|
||||
rm -f "${tpmpubkey}"
|
||||
msg=$(run_tpmtool "--pubkey=${tpmkeyurl}" --outfile \"${tpmpubkey}\" ${params})
|
||||
if [ $? -ne 0 ] || \
|
||||
[ ! -r "${tpmpubkey}" ] || [ $(get_filesize "${tpmpubkey}") -eq 0 ]; then
|
||||
logerr "Error: Could not get TPM public key"
|
||||
logerr "${msg}"
|
||||
rm -f "${tpmkey}" "${tpmpubkey}"
|
||||
return 1
|
||||
if [ $((flags & FLAG_SRK_WELL_KNOWN)) -ne 0 ]; then
|
||||
unset GNUTLS_PIN
|
||||
params="--srk-well-known"
|
||||
else
|
||||
export GNUTLS_PIN="${TPM_SRK_PASSWORD}"
|
||||
fi
|
||||
|
||||
if [ $((flags & FLAG_REGISTER_KEY)) -ne 0 ]; then
|
||||
msg="$(run_tpmtool --generate-rsa --signing --register ${params})"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not generate registered signing key with tpmtool"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
tpmkeyurl=$(echo "${msg}" | sed -n 's/\(tpmkey:uuid=[^;]*\);.*/\1/p')
|
||||
if [ -z "${tpmkeyurl}" ]; then
|
||||
logerr "Could not parse tpmkey URL"
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
rm -f "${tpmkey}"
|
||||
msg="$(run_tpmtool --generate-rsa --signing --outfile \"${tpmkey}\" ${params})"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not create signing key with tpmtool"
|
||||
logerr "${msg}"
|
||||
rm -f "${tpmkey}"
|
||||
return 1
|
||||
fi
|
||||
if [ ! -r "${tpmkey}" ] || [ $(get_filesize "${tpmkey}") -eq 0 ]; then
|
||||
logerr "The TPM key file ${tpmkey} was not written properly"
|
||||
logerr "${msg}"
|
||||
rm -f "${tpmkey}"
|
||||
return 1
|
||||
fi
|
||||
chmod 640 "${tpmkey}"
|
||||
tpmkeyurl="tpmkey:file=${tpmkey}"
|
||||
fi
|
||||
|
||||
rm -f "${tpmpubkey}"
|
||||
msg=$(run_tpmtool "--pubkey=${tpmkeyurl}" --outfile \"${tpmpubkey}\" ${params})
|
||||
if [ $? -ne 0 ] || \
|
||||
[ ! -r "${tpmpubkey}" ] || [ $(get_filesize "${tpmpubkey}") -eq 0 ]; then
|
||||
logerr "Error: Could not get TPM public key"
|
||||
logerr "${msg}"
|
||||
rm -f "${tpmkey}" "${tpmpubkey}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "cn=swtpm-localca" > "${template}"
|
||||
@ -197,12 +302,17 @@ create_localca_cert() {
|
||||
fi
|
||||
|
||||
output="statedir = ${dir}
|
||||
signingkey = ${tpmkeyurl}
|
||||
signingkey = $(escape_pkcs11_url ${tpmkeyurl})
|
||||
issuercert = ${tpmca}
|
||||
certserial = ${dir}/certserial
|
||||
TSS_TCSD_HOSTNAME = ${TSS_TCSD_HOSTNAME}
|
||||
TSS_TCSD_PORT = ${TSS_TCSD_PORT}"
|
||||
certserial = ${dir}/certserial"
|
||||
|
||||
if [ $((flags & FLAG_TPM2)) -eq 0 ]; then
|
||||
output+="$(echo -e "\nTSS_TCSD_HOSTNAME = ${TSS_TCSD_HOSTNAME}")"
|
||||
output+="$(echo -e "\nTSS_TCSD_PORT = ${TSS_TCSD_PORT}")"
|
||||
else
|
||||
output+="$(echo -e "\nSWTPM_PKCS11_PIN = ${SWTPM_PKCS11_PIN}")"
|
||||
# output+="$(echo -e "\nSWTPM_PKCS11_SO_PIN = ${SWTPM_PKCS11_SO_PIN}")"
|
||||
fi
|
||||
if [ -n "${TPM_KEY_PASSWORD}" ]; then
|
||||
output+="$(echo -e "\nsigningkey_password = ${TPM_KEY_PASSWORD}")"
|
||||
fi
|
||||
@ -259,7 +369,8 @@ The following options are supported:
|
||||
--overwrite Overwrite any data in an existing directory; tries to
|
||||
reuse a root CA if one is found there
|
||||
--register Create a registered TPM 1.2 key rather than a file that
|
||||
contains the key
|
||||
contains the key; this option has no effect if --tpm2 is
|
||||
used
|
||||
--key-password s Password for the newly created TPM key; required if
|
||||
--register is not passed
|
||||
Note: use the same as the --srk-password (bug in certtool)
|
||||
@ -275,6 +386,9 @@ The following options are supported:
|
||||
on; default is '${TSS_TCSD_HOSTNAME_DEFAULT}'
|
||||
--tss-tcsd-port p The TCP port on which tcsd is listening for connections;
|
||||
default is ${TSS_TCSD_PORT_DEFAULT}
|
||||
--tpm2 Setup a CA that uses a TPM 2.0
|
||||
--pid <pid> Pimary object Id used by tpm2_ptool; only valid if --tpm2
|
||||
is used
|
||||
--help, -h, -? Display this help screen and exit
|
||||
|
||||
|
||||
@ -297,7 +411,7 @@ tpmtool_supports_srk_well_known()
|
||||
|
||||
main() {
|
||||
local flags=0
|
||||
local dir outfile owner group msg
|
||||
local dir outfile owner group msg pid
|
||||
|
||||
if tpmtool_supports_srk_well_known; then
|
||||
flags=$((flags | FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN | FLAG_SRK_WELL_KNOWN))
|
||||
@ -348,6 +462,13 @@ main() {
|
||||
shift
|
||||
TSS_TCSD_PORT="$1"
|
||||
;;
|
||||
--tpm2)
|
||||
flags=$((flags | FLAG_TPM2))
|
||||
;;
|
||||
--pid)
|
||||
shift
|
||||
pid="$1"
|
||||
;;
|
||||
--help|-h|-?)
|
||||
usage "$0" "${flags}"
|
||||
exit 0
|
||||
@ -371,17 +492,24 @@ main() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "${TPM_SRK_PASSWORD}" ] && \
|
||||
if [ -z "${TPM_SRK_PASSWORD}" ] && [ $((flags & FLAG_TPM2)) -eq 0 ] &&
|
||||
[ $((flags & FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN)) -eq 0 ]; then
|
||||
logerr "SRK password must be provided"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "${TPM_KEY_PASSWORD}" ] && [ $((flags & FLAG_REGISTER_KEY)) -eq 0 ]; then
|
||||
if [ -z "${TPM_KEY_PASSWORD}" ] && \
|
||||
[ $((flags & FLAG_REGISTER_KEY)) -eq 0 ] && \
|
||||
[ $((flags & FLAG_TPM2)) -eq 0 ]; then
|
||||
logerr "Key password is required"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ $((flags & FLAG_TPM2)) -ne 0 ] && [ -z "${pid}" ]; then
|
||||
logerr "--pid is required for TPM 2"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
if [ -n "${owner}" ]; then
|
||||
msg="$(id -u "${owner}" 2>&1)"
|
||||
@ -409,7 +537,7 @@ main() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
create_localca_cert "${flags}" "${dir}" "${outfile}" "${owner}"
|
||||
create_localca_cert "${flags}" "${dir}" "${outfile}" "${owner}" "${pid}"
|
||||
return $?
|
||||
} #main
|
||||
|
||||
|
||||
@ -78,6 +78,7 @@ if WITH_GNUTLS
|
||||
TESTS += \
|
||||
test_swtpm_cert \
|
||||
test_tpm2_parameters \
|
||||
test_tpm2_samples_create_tpmca \
|
||||
test_tpm2_samples_swtpm_localca \
|
||||
test_tpm2_samples_swtpm_localca_pkcs11 \
|
||||
test_tpm2_swtpm_cert \
|
||||
|
||||
206
tests/test_tpm2_samples_create_tpmca
Executable file
206
tests/test_tpm2_samples_create_tpmca
Executable file
@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env bash
|
||||
#set -x
|
||||
|
||||
# For the license, see the LICENSE file in the root directory.
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "Need to be root to run this test."
|
||||
exit 77
|
||||
fi
|
||||
|
||||
# tpm2_ptool may not be packaged everywhere ...
|
||||
if [ -z "$(type -P tpm2_ptool)" ]; then
|
||||
echo "Could not find tpmtool in PATH"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
if [ -z "$(tpm2_ptool | grep ",config,")" ]; then
|
||||
echo "tpm2_ptool does not support the config command"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
msg=$(systemctl status tpm2-abrmd 2>&1)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "tpm2-abrmd must be running"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
ROOT=${abs_top_builddir:-$(dirname "$0")/..}
|
||||
TESTDIR=${abs_top_testdir:=$(dirname "$0")}
|
||||
SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..}
|
||||
|
||||
SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup
|
||||
SWTPM_CREATE_TPMCA=${SRCDIR}/samples/swtpm-create-tpmca
|
||||
SWTPM_LOCALCA=${SRCDIR}/samples/swtpm-localca
|
||||
SWTPM=${ROOT}/src/swtpm/swtpm
|
||||
SWTPM_IOCTL=${ROOT}/src/swtpm_ioctl/swtpm_ioctl
|
||||
|
||||
SWTPM_INTERFACE=socket+socket
|
||||
SWTPM_SERVER_NAME=localhost
|
||||
SWTPM_SERVER_PORT=65434
|
||||
SWTPM_CTRL_PORT=65435
|
||||
|
||||
workdir=$(mktemp -d)
|
||||
|
||||
SWTPM_LOCALCA_DIR="${workdir}/my localca"
|
||||
SWTPM_LOCALCA_CONF="${workdir}/my localca/swtpm-localca.conf"
|
||||
|
||||
PID="" # primary object id returned by tpm2_ptool
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
if [ -n "${PID}" ]; then
|
||||
echo "y" | tpm2_ptool destroy ${PID} &>/dev/null
|
||||
fi
|
||||
rm -rf "${workdir}"
|
||||
}
|
||||
|
||||
trap "cleanup" SIGTERM EXIT
|
||||
source ${TESTDIR}/common
|
||||
|
||||
case "$(uname -s)" in
|
||||
Darwin)
|
||||
CERTTOOL=gnutls-certtool;;
|
||||
*)
|
||||
CERTTOOL=certtool;;
|
||||
esac
|
||||
|
||||
PATH=${ROOT}/src/swtpm_bios:${ROOT}/src/swtpm_cert:${PATH}
|
||||
|
||||
# Run the tests
|
||||
# @param1: The vTPM for which the certificate is created is a TPM 2
|
||||
function run_test() {
|
||||
local vtpm_is_tpm2="$1"
|
||||
|
||||
local tmp params certinfo regex regexs fil i skip
|
||||
|
||||
rm -rf "${workdir}"/*
|
||||
|
||||
cat <<_EOF_ > "${workdir}/swtpm_setup.conf"
|
||||
create_certs_tool=${SWTPM_LOCALCA}
|
||||
create_certs_tool_config=${workdir}/swtpm-localca.conf
|
||||
create_certs_tool_options=/dev/null
|
||||
_EOF_
|
||||
|
||||
tmp="$(tpm2_ptool init 2>&1)"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "tpm2_ptool init failed:"
|
||||
echo "${tmp}"
|
||||
exit 1
|
||||
fi
|
||||
PID="$(echo "${tmp}" | grep -E "^id:" |cut -d ":" -f2 | tr -d " ")"
|
||||
if [ -z "${PID}" ]; then
|
||||
echo "Could not grep the pid from the tpm2_ptool output"
|
||||
echo "${tmp}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp="$(SWTPM_PKCS11_PIN="mypin 123" SWTPM_PKCS11_SO_PIN="123" ${SWTPM_CREATE_TPMCA} \
|
||||
--dir "${SWTPM_LOCALCA_DIR}" \
|
||||
--overwrite \
|
||||
--outfile "${SWTPM_LOCALCA_CONF}" \
|
||||
--group tss \
|
||||
--tpm2 \
|
||||
--pid "${PID}")"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: Could not create TPM CA"
|
||||
echo "${tmp}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for fil in \
|
||||
swtpm-localca-rootca-cert.pem \
|
||||
swtpm-localca-rootca-privkey.pem \
|
||||
swtpm-localca-tpmca-cert.pem \
|
||||
swtpm-localca-tpmca-pubkey.pem; do
|
||||
if [ ! -r "${SWTPM_LOCALCA_DIR}/${fil}" ]; then
|
||||
echo "Error: TPM CA tool did not create file ${fil}."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for regex in \
|
||||
"^statedir = " \
|
||||
"^signingkey = " \
|
||||
"^issuercert = " \
|
||||
"^certserial = " \
|
||||
"^SWTPM_PKCS11_PIN = mypin 123"; do
|
||||
if [ -n "${regex}" ] && \
|
||||
[ -z "$(grep -E "${regex}" "${SWTPM_LOCALCA_CONF}")" ]; then
|
||||
echo "Error: Could not find regex '${line}' in CA config file."
|
||||
cat "${SWTPM_LOCALCA_CONF}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
params=""
|
||||
if [ ${vtpm_is_tpm2} -ne 0 ]; then
|
||||
params="--tpm2"
|
||||
skip=0
|
||||
else
|
||||
skip=7 # header in cert
|
||||
fi
|
||||
|
||||
# make sure we can actually sign with this new certificate
|
||||
${SWTPM_LOCALCA} \
|
||||
--type ek \
|
||||
--ek x=739192d8f1004283957a7b1568d610b41c637ccc114aadcac4908c20456468fa,y=59f63ac06f8011f6fdd1460c6bc8e3e0a2d090d4fc188c7e04870e06795ce8ae \
|
||||
--dir "${workdir}" --vmid test \
|
||||
${params} \
|
||||
--tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \
|
||||
--tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM \
|
||||
--configfile "${SWTPM_LOCALCA_CONF}" \
|
||||
--optsfile /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: The CA could not sign with the new certificate"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "${workdir}/ek.cert" ]; then
|
||||
echo "Error: The CA did not produce a certificate"
|
||||
exit 1
|
||||
fi
|
||||
# cert was for example 541 bytes long
|
||||
if [ $(get_filesize "${workdir}/ek.cert") -lt 500 ]; then
|
||||
echo "Error: The certificate's size is dubious"
|
||||
ls -l "${workdir}/ek.cert"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check the contents of the certificate
|
||||
certinfo=$(dd "if=${workdir}/ek.cert" bs=1 "skip=$skip" status=none | \
|
||||
"$CERTTOOL" -i --inder)
|
||||
regexs=('^[[:space:]]+2.23.133.8.1$'
|
||||
'^[[:space:]]+directoryName:.*(,)?2.23.133.2.3=.*'
|
||||
'^[[:space:]]+directoryName:.*(,)?2.23.133.2.2=.*'
|
||||
'^[[:space:]]+directoryName:.*(,)?2.23.133.2.1=.*'
|
||||
'^[[:space:]]+Certificate Authority \(CA\): FALSE$'
|
||||
'^[[:space:]]+Unknown extension 2.5.29.9 \(not critical\):$'
|
||||
'^[[:space:]]+Hexdump: 3019301706056781050210310e300c0c03322e3002010002020092$')
|
||||
if [ ${vtpm_is_tpm2} -ne 0 ]; then
|
||||
# TPM 2.0; due to ecc: Key agreement
|
||||
regexs+=('^[[:space:]]+Key agreement\.$'
|
||||
'^[[:space:]]+Signature Algorithm: RSA-SHA256$')
|
||||
else
|
||||
regexs+=('^[[:space:]]+Key encipherment\.$'
|
||||
'^[[:space:]]+Signature Algorithm: RSA-SHA1$')
|
||||
fi
|
||||
|
||||
for ((i=0; i < ${#regexs}; i++)); do \
|
||||
if [ -n "${regexs[$i]}" ] && \
|
||||
[ -z "$(echo "${certinfo}" | grep -E "${regexs[$i]}")" ]; then
|
||||
echo "Error: Could not match regex '${regexs[$i]}' with certificate info:"
|
||||
echo "${certinfo}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
} # run_test
|
||||
|
||||
run_test 1
|
||||
echo "Test 1: OK"
|
||||
|
||||
run_test 0
|
||||
echo "Test 2: OK"
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in New Issue
Block a user