mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-08-19 09:00:59 +00:00
samples: Add a script to create a TPM 1.2 intermediate CA
This (experimental) script uses GnuTLS tpmtool to create a TPM 1.2 intermediate CA that can sign a vTPM's EK and platform certificates. Add a man page for this tool. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
07c786d1a0
commit
05f4d55f1f
@ -13,6 +13,7 @@ man8_PODS = \
|
||||
swtpm_ioctl.pod \
|
||||
swtpm_setup.pod \
|
||||
swtpm_setup.conf.pod
|
||||
swtpm-create-tpmca.pod \
|
||||
swtpm-localca.pod \
|
||||
swtpm-localca.options.pod \
|
||||
swtpm-localca.conf.pod
|
||||
@ -25,6 +26,7 @@ man8_MANS = \
|
||||
swtpm_setup.8 \
|
||||
swtpm_setup.conf.8 \
|
||||
swtpm_setup.sh.8 \
|
||||
swtpm-create-tpmca.8 \
|
||||
swtpm-localca.8 \
|
||||
swtpm-localca.options.8 \
|
||||
swtpm-localca.conf.8
|
||||
|
||||
249
man/man8/swtpm-create-tpmca.8
Normal file
249
man/man8/swtpm-create-tpmca.8
Normal file
@ -0,0 +1,249 @@
|
||||
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
|
||||
.\"
|
||||
.\" Standard preamble:
|
||||
.\" ========================================================================
|
||||
.de Sp \" Vertical space (when we can't use .PP)
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
..
|
||||
.de Vb \" Begin verbatim text
|
||||
.ft CW
|
||||
.nf
|
||||
.ne \\$1
|
||||
..
|
||||
.de Ve \" End verbatim text
|
||||
.ft R
|
||||
.fi
|
||||
..
|
||||
.\" Set up some character translations and predefined strings. \*(-- will
|
||||
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
|
||||
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
|
||||
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
|
||||
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
|
||||
.\" nothing in troff, for use with C<>.
|
||||
.tr \(*W-
|
||||
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
|
||||
.ie n \{\
|
||||
. ds -- \(*W-
|
||||
. ds PI pi
|
||||
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
|
||||
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
|
||||
. ds L" ""
|
||||
. ds R" ""
|
||||
. ds C` ""
|
||||
. ds C' ""
|
||||
'br\}
|
||||
.el\{\
|
||||
. ds -- \|\(em\|
|
||||
. ds PI \(*p
|
||||
. ds L" ``
|
||||
. ds R" ''
|
||||
. ds C`
|
||||
. ds C'
|
||||
'br\}
|
||||
.\"
|
||||
.\" Escape single quotes in literal strings from groff's Unicode transform.
|
||||
.ie \n(.g .ds Aq \(aq
|
||||
.el .ds Aq '
|
||||
.\"
|
||||
.\" If the F register is >0, we'll generate index entries on stderr for
|
||||
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
|
||||
.\" entries marked with X<> in POD. Of course, you'll have to process the
|
||||
.\" output yourself in some meaningful fashion.
|
||||
.\"
|
||||
.\" Avoid warning from groff about undefined register 'F'.
|
||||
.de IX
|
||||
..
|
||||
.nr rF 0
|
||||
.if \n(.g .if rF .nr rF 1
|
||||
.if (\n(rF:(\n(.g==0)) \{\
|
||||
. if \nF \{\
|
||||
. de IX
|
||||
. tm Index:\\$1\t\\n%\t"\\$2"
|
||||
..
|
||||
. if !\nF==2 \{\
|
||||
. nr % 0
|
||||
. nr F 2
|
||||
. \}
|
||||
. \}
|
||||
.\}
|
||||
.rr rF
|
||||
.\"
|
||||
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
|
||||
.\" Fear. Run. Save yourself. No user-serviceable parts.
|
||||
. \" fudge factors for nroff and troff
|
||||
.if n \{\
|
||||
. ds #H 0
|
||||
. ds #V .8m
|
||||
. ds #F .3m
|
||||
. ds #[ \f1
|
||||
. ds #] \fP
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
|
||||
. ds #V .6m
|
||||
. ds #F 0
|
||||
. ds #[ \&
|
||||
. ds #] \&
|
||||
.\}
|
||||
. \" simple accents for nroff and troff
|
||||
.if n \{\
|
||||
. ds ' \&
|
||||
. ds ` \&
|
||||
. ds ^ \&
|
||||
. ds , \&
|
||||
. ds ~ ~
|
||||
. ds /
|
||||
.\}
|
||||
.if t \{\
|
||||
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
|
||||
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
|
||||
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
|
||||
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
|
||||
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
|
||||
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
|
||||
.\}
|
||||
. \" troff and (daisy-wheel) nroff accents
|
||||
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
|
||||
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
|
||||
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
|
||||
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
|
||||
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
|
||||
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
|
||||
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
|
||||
.ds ae a\h'-(\w'a'u*4/10)'e
|
||||
.ds Ae A\h'-(\w'A'u*4/10)'E
|
||||
. \" corrections for vroff
|
||||
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
|
||||
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
|
||||
. \" for low resolution devices (crt and lpr)
|
||||
.if \n(.H>23 .if \n(.V>19 \
|
||||
\{\
|
||||
. ds : e
|
||||
. ds 8 ss
|
||||
. ds o a
|
||||
. ds d- d\h'-1'\(ga
|
||||
. ds D- D\h'-1'\(hy
|
||||
. ds th \o'bp'
|
||||
. ds Th \o'LP'
|
||||
. ds ae ae
|
||||
. ds Ae AE
|
||||
.\}
|
||||
.rm #[ #] #H #V #F C
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "swtpm-create-tpmca 8"
|
||||
.TH swtpm-create-tpmca 8 "2018-10-15" "swtpm" ""
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
.nh
|
||||
.SH "NAME"
|
||||
swtpm\-create\-tpmca
|
||||
.SH "SYNOPSIS"
|
||||
.IX Header "SYNOPSIS"
|
||||
\&\fBswtpm-create-tpmca [\s-1OPTIONS\s0]\fR
|
||||
.SH "DESCRIPTION"
|
||||
.IX Header "DESCRIPTION"
|
||||
\&\fBswtpm-create-tpmca\fR is a tool to create a \s-1TPM 1.2\s0 based \s-1CA\s0 that
|
||||
can be used by \fBswtpm-localca\fR to sign \s-1EK\s0 and platform certificates.
|
||||
The \s-1CA\s0 uses a GnuTLS key to sign certificates. To do this,
|
||||
GnuTLS talks to the \s-1TPM 1.2\s0 using the \fBtcsd\fR (TrouSerS) daemon.
|
||||
.PP
|
||||
Note: This tool is experimental. See the section on known issues below.
|
||||
.PP
|
||||
The following options are supported:
|
||||
.IP "\fB\-\-dir dir\fR" 4
|
||||
.IX Item "--dir dir"
|
||||
The directory where the keys will be written to. An existing root \s-1CA\s0 with
|
||||
the files \fIswtpm\-localca\-rootca\-privkey.pem\fR and
|
||||
\&\fIswtpm\-localca\-rootca\-cert.pem\fR in this directory will be reused. If
|
||||
either one of these files does not exist, a new root \s-1CA\s0 will be created.
|
||||
.IP "\fB\-\-overwrite\fR" 4
|
||||
.IX Item "--overwrite"
|
||||
Overwrite the contents of the output directory.
|
||||
.IP "\fB\-\-register\fR" 4
|
||||
.IX Item "--register"
|
||||
Register the key with \s-1TCSD.\s0 For the key to be available for signing,
|
||||
the same user that created the \s-1TPM CA\s0 has to run the swtpm-localca
|
||||
later on. If this option is not passed, the private key is written
|
||||
into a file and can be used by others as well.
|
||||
.IP "\fB\-\-key\-password s\fR" 4
|
||||
.IX Item "--key-password s"
|
||||
The new signing key will get this password.
|
||||
.Sp
|
||||
Note: Due to a bug in GnuTLS certtool it may be necessary to use the
|
||||
same password for the signing key as for the \s-1SRK.\s0
|
||||
.IP "\fB\-\-srk\-password s\fR" 4
|
||||
.IX Item "--srk-password s"
|
||||
The \s-1TPM SRK\s0 password.
|
||||
.Sp
|
||||
Note: Since GnuTLS tpmtool does not support the 'well known' password
|
||||
of 20 zero bytes, the \s-1SRK\s0 password must be set.
|
||||
.IP "\fB\-\-outfile filename\fR" 4
|
||||
.IX Item "--outfile filename"
|
||||
The name of a file where to write the swtpm\-localca.conf configuration
|
||||
to.
|
||||
.IP "\fB\-\-owner owner\fR" 4
|
||||
.IX Item "--owner owner"
|
||||
The name or uid number of the owner who will own the directory and
|
||||
outfile file. This option only has an effect if this swtpm-create-tpmca
|
||||
is run by the root user.
|
||||
.IP "\fB\-\-group group\fR" 4
|
||||
.IX Item "--group group"
|
||||
The name or gid number of the group who will own the directory and
|
||||
outfile file. This option only has an effect if this swtpm-create-tpmca
|
||||
is run by the root user.
|
||||
.IP "\fB\-\-tss\-tcsd\-hostname\fR" 4
|
||||
.IX Item "--tss-tcsd-hostname"
|
||||
The hostname where tcsd is running on. The default hostname is 'localhost'.
|
||||
.IP "\fB\-tss\-tcsd\-port\fR" 4
|
||||
.IX Item "-tss-tcsd-port"
|
||||
The \s-1TCP\s0 port on which tcsd is listening for messages. The default port is
|
||||
30003.
|
||||
.IP "\fB\-help, \-h, \-?\fR" 4
|
||||
.IX Item "-help, -h, -?"
|
||||
Display the help screen and exit.
|
||||
.SH "EXAMPLE"
|
||||
.IX Header "EXAMPLE"
|
||||
The following example creates an intermediate \s-1TPM CA\s0 and writes the keys
|
||||
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
|
||||
.Vb 10
|
||||
\& #> sudo systemctl start tcsd
|
||||
\& #> sudo /usr/share/swtpm/swtpm\-create\-tpmca \e
|
||||
\& \-\-dir /var/lib/swtpm\-localca \e
|
||||
\& \-\-overwrite \e
|
||||
\& \-\-outfile /etc/swtpm\-localca.conf \e
|
||||
\& \-\-srk\-password password \e
|
||||
\& \-\-key\-password password \e
|
||||
\& \-\-group tss
|
||||
\& statedir = /var/lib/swtpm\-localca
|
||||
\& signingkey = tpmkey:file=/var/lib/swtpm\-localca/swtpm\-localca\-tpmca\-privkey.pem
|
||||
\& issuercert = /var/lib/swtpm\-localca/swtpm\-localca\-tpmca\-cert.pem
|
||||
\& certserial = /var/lib/swtpm\-localca/certserial
|
||||
\& TSS_TCSD_HOSTNAME = localhost
|
||||
\& TSS_TCSD_PORT = 30003
|
||||
\& signingkey_password = password
|
||||
\& parentkey_password = password
|
||||
.Ve
|
||||
.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
|
||||
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
|
||||
certificates since the \s-1TPM\s0 does not accept authenticated commands.
|
||||
.SH "SEE ALSO"
|
||||
.IX Header "SEE ALSO"
|
||||
\&\fBswtpm-localca\fR, \fBswtpm\-localca.conf\fR, \fBtcsd\fR
|
||||
.SH "REPORTING BUGS"
|
||||
.IX Header "REPORTING BUGS"
|
||||
Report bugs to Stefan Berger <stefanb@linux.ibm.com>
|
||||
129
man/man8/swtpm-create-tpmca.pod
Normal file
129
man/man8/swtpm-create-tpmca.pod
Normal file
@ -0,0 +1,129 @@
|
||||
=head1 NAME
|
||||
|
||||
swtpm-create-tpmca
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<swtpm-create-tpmca [OPTIONS]>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<swtpm-create-tpmca> is a tool to create a TPM 1.2 based CA that
|
||||
can be used by B<swtpm-localca> to sign EK and platform certificates.
|
||||
The CA uses a GnuTLS key to sign certificates. To do this,
|
||||
GnuTLS talks to the TPM 1.2 using the B<tcsd> (TrouSerS) daemon.
|
||||
|
||||
Note: This tool is experimental. See the section on known issues below.
|
||||
|
||||
The following options are supported:
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<--dir dir>
|
||||
|
||||
The directory where the keys will be written to. An existing root CA with
|
||||
the files I<swtpm-localca-rootca-privkey.pem> and
|
||||
I<swtpm-localca-rootca-cert.pem> in this directory will be reused. If
|
||||
either one of these files does not exist, a new root CA will be created.
|
||||
|
||||
=item B<--overwrite>
|
||||
|
||||
Overwrite the contents of the output directory.
|
||||
|
||||
=item B<--register>
|
||||
|
||||
Register the key with TCSD. For the key to be available for signing,
|
||||
the same user that created the TPM CA has to run the swtpm-localca
|
||||
later on. If this option is not passed, the private key is written
|
||||
into a file and can be used by others as well.
|
||||
|
||||
=item B<--key-password s>
|
||||
|
||||
The new signing key will get this password.
|
||||
|
||||
Note: Due to a bug in GnuTLS certtool it may be necessary to use the
|
||||
same password for the signing key as for the SRK.
|
||||
|
||||
=item B<--srk-password s>
|
||||
|
||||
The TPM SRK password.
|
||||
|
||||
Note: Since GnuTLS tpmtool does not support the 'well known' password
|
||||
of 20 zero bytes, the SRK password must be set.
|
||||
|
||||
=item B<--outfile filename>
|
||||
|
||||
The name of a file where to write the swtpm-localca.conf configuration
|
||||
to.
|
||||
|
||||
=item B<--owner owner>
|
||||
|
||||
The name or uid number of the owner who will own the directory and
|
||||
outfile file. This option only has an effect if this swtpm-create-tpmca
|
||||
is run by the root user.
|
||||
|
||||
=item B<--group group>
|
||||
|
||||
The name or gid number of the group who will own the directory and
|
||||
outfile file. This option only has an effect if this swtpm-create-tpmca
|
||||
is run by the root user.
|
||||
|
||||
=item B<--tss-tcsd-hostname>
|
||||
|
||||
The hostname where tcsd is running on. The default hostname is 'localhost'.
|
||||
|
||||
=item B<-tss-tcsd-port>
|
||||
|
||||
The TCP port on which tcsd is listening for messages. The default port is
|
||||
30003.
|
||||
|
||||
=item B<-help, -h, -?>
|
||||
|
||||
Display the help screen and exit.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLE
|
||||
|
||||
The following example creates an intermediate TPM CA and writes the keys
|
||||
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.
|
||||
|
||||
#> sudo systemctl start tcsd
|
||||
#> sudo /usr/share/swtpm/swtpm-create-tpmca \
|
||||
--dir /var/lib/swtpm-localca \
|
||||
--overwrite \
|
||||
--outfile /etc/swtpm-localca.conf \
|
||||
--srk-password password \
|
||||
--key-password password \
|
||||
--group tss
|
||||
statedir = /var/lib/swtpm-localca
|
||||
signingkey = tpmkey:file=/var/lib/swtpm-localca/swtpm-localca-tpmca-privkey.pem
|
||||
issuercert = /var/lib/swtpm-localca/swtpm-localca-tpmca-cert.pem
|
||||
certserial = /var/lib/swtpm-localca/certserial
|
||||
TSS_TCSD_HOSTNAME = localhost
|
||||
TSS_TCSD_PORT = 30003
|
||||
signingkey_password = password
|
||||
parentkey_password = password
|
||||
|
||||
=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
|
||||
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
|
||||
certificates since the TPM does not accept authenticated commands.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
B<swtpm-localca>, B<swtpm-localca.conf>, B<tcsd>
|
||||
|
||||
=head1 REPORTING BUGS
|
||||
|
||||
Report bugs to Stefan Berger <stefanb@linux.ibm.com>
|
||||
@ -8,6 +8,7 @@ samplesconfdir = $(datadir)/@PACKAGE@
|
||||
samplessysconfdir = $(sysconfdir)
|
||||
|
||||
samplesconf_SCRIPTS = \
|
||||
swtpm-create-tpmca \
|
||||
swtpm-localca
|
||||
|
||||
samplessysconf_DATA = \
|
||||
@ -21,6 +22,7 @@ install-data-local:
|
||||
fi
|
||||
|
||||
EXTRA_DIST= \
|
||||
swtpm-create-tpmca \
|
||||
swtpm-localca \
|
||||
swtpm-localca.conf \
|
||||
swtpm-localca.options
|
||||
|
||||
371
samples/swtpm-create-tpmca
Executable file
371
samples/swtpm-create-tpmca
Executable file
@ -0,0 +1,371 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
FLAG_OVERWRITE=1
|
||||
FLAG_REGISTER_KEY=2
|
||||
|
||||
TSS_TCSD_HOSTNAME_DEFAULT=localhost
|
||||
TSS_TCSD_PORT_DEFAULT=30003
|
||||
|
||||
logit()
|
||||
{
|
||||
if [ -z "$LOGFILE" ]; then
|
||||
echo "$@" >&1
|
||||
else
|
||||
echo "$@" >> $LOGFILE
|
||||
fi
|
||||
}
|
||||
|
||||
logerr()
|
||||
{
|
||||
if [ -z "$LOGFILE" ]; then
|
||||
echo "Error: $@" >&2
|
||||
else
|
||||
echo "Error: $@" >> $LOGFILE
|
||||
fi
|
||||
}
|
||||
|
||||
# Get the size of a file in bytes
|
||||
#
|
||||
# @1: filename
|
||||
function get_filesize()
|
||||
{
|
||||
if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then
|
||||
stat -c%s $1
|
||||
else
|
||||
# OpenBSD
|
||||
stat -f%z $1
|
||||
fi
|
||||
}
|
||||
|
||||
# Use expect for automating the interaction with the tpmtool
|
||||
#
|
||||
# @param 1...: parameters to pass to tpmtool command line
|
||||
#
|
||||
# TPM_SRK_PASSWORD and TPM_KEY_PASSWORD global variables are used
|
||||
# for the SRK and key passwords respectively.
|
||||
run_tpmtool() {
|
||||
local prg out
|
||||
|
||||
prg="spawn tpmtool $@
|
||||
expect {
|
||||
\"Enter SRK password:\" {
|
||||
send \"${TPM_SRK_PASSWORD}\n\"
|
||||
exp_continue
|
||||
}
|
||||
\"Enter key password:\" {
|
||||
send \"${TPM_KEY_PASSWORD}\n\"
|
||||
exp_continue
|
||||
}
|
||||
\"tpmkey:\" {
|
||||
send_user \"\n\"
|
||||
}
|
||||
eof {
|
||||
exit
|
||||
}
|
||||
}
|
||||
catch wait result
|
||||
exit [lindex \$result 3]
|
||||
"
|
||||
out=$(expect -c "${prg}")
|
||||
echo "${out}"
|
||||
} #run_tpmtool
|
||||
|
||||
create_localca_cert() {
|
||||
local flags=$1
|
||||
local dir="$2"
|
||||
local outfile="$3"
|
||||
local owner="$4"
|
||||
|
||||
local cakey=${dir}/swtpm-localca-rootca-privkey.pem
|
||||
local cacert=${dir}/swtpm-localca-rootca-cert.pem
|
||||
local tpmkey=${dir}/swtpm-localca-tpmca-privkey.pem
|
||||
local tpmpubkey=${dir}/swtpm-localca-tpmca-pubkey.pem
|
||||
local tpmca=${dir}/swtpm-localca-tpmca-cert.pem
|
||||
local template=${dir}/template
|
||||
local tpmkeyurl
|
||||
local msg output
|
||||
|
||||
if ! [ -r "${cakey}" ] || ! [ -r ${cacert} ]; then
|
||||
msg=$(${CERTTOOL} \
|
||||
--generate-privkey \
|
||||
--outfile ${cakey} \
|
||||
2>&1)
|
||||
[ $? -ne 0 ] && {
|
||||
logerr "Could not create root-CA key ${cakey}."
|
||||
logerr "${msg}"
|
||||
return 1
|
||||
}
|
||||
chmod 640 ${cakey}
|
||||
|
||||
echo "cn=swtpm-localca-rootca" > ${template}
|
||||
echo "ca" >> ${template}
|
||||
echo "cert_signing_key" >> ${template}
|
||||
echo "expiration_days = 3650" >> ${template}
|
||||
|
||||
msd=$(${CERTTOOL} \
|
||||
--generate-self-signed \
|
||||
--template ${template} \
|
||||
--outfile ${cacert} \
|
||||
--load-privkey ${cakey} \
|
||||
2>&1)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not create root CA."
|
||||
logerr "${msg}"
|
||||
rm -f ${cakey} ${template}
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
logit "Reusing existing root CA"
|
||||
fi
|
||||
|
||||
rm -f ${tpmkey} ${tpmpubkey} ${tpmca}
|
||||
|
||||
if [ $((flags & FLAG_REGISTER_KEY)) -ne 0 ]; then
|
||||
msg="$(run_tpmtool --generate-rsa --signing --register)"
|
||||
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}")"
|
||||
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
|
||||
|
||||
rm -f "${tpmpubkey}"
|
||||
msg=$(run_tpmtool --pubkey=${tpmkeyurl} --outfile "${tpmpubkey}")
|
||||
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
|
||||
|
||||
echo "cn=swtpm-localca" > ${template}
|
||||
echo "ca" >> ${template}
|
||||
echo "cert_signing_key" >> ${template}
|
||||
echo "expiration_days = 3650" >> ${template}
|
||||
|
||||
msg=$(GNUTLS_PIN=${TPM_SRK_PASSWORD} ${CERTTOOL} \
|
||||
--generate-certificate \
|
||||
--template ${template} \
|
||||
--outfile ${tpmca} \
|
||||
--load-ca-privkey ${cakey} \
|
||||
--load-ca-certificate ${cacert} \
|
||||
--load-privkey ${tpmkeyurl} \
|
||||
--load-pubkey ${tpmpubkey} \
|
||||
2>&1)
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not create TPM CA"
|
||||
logerr "${msg}"
|
||||
rm -f "${template}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
output="statedir = ${dir}
|
||||
signingkey = ${tpmkeyurl}
|
||||
issuercert = ${tpmca}
|
||||
certserial = ${dir}/certserial
|
||||
TSS_TCSD_HOSTNAME = ${TSS_TCSD_HOSTNAME}
|
||||
TSS_TCSD_PORT = ${TSS_TCSD_PORT}"
|
||||
|
||||
if [ -n "${TPM_KEY_PASSWORD}" ]; then
|
||||
output+="$(echo -e "\nsigningkey_password = ${TPM_KEY_PASSWORD}")"
|
||||
fi
|
||||
if [ -n "${TPM_SRK_PASSWORD}" ]; then
|
||||
output+="$(echo -e "\nparentkey_password = ${TPM_SRK_PASSWORD}")"
|
||||
fi
|
||||
|
||||
if [ -n "${outfile}" ]; then
|
||||
echo "${output}" > "${outfile}"
|
||||
chmod 640 "${outfile}"
|
||||
fi
|
||||
echo "${output}"
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
chown "${owner}":"${group}" ${dir}
|
||||
|
||||
pushd ${dir} &>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
chown "${owner}":"${group}" *
|
||||
popd &>/dev/null
|
||||
fi
|
||||
|
||||
if [ -n "${outfile}" ]; then
|
||||
chown "${owner}":"${group}" "${outfile}"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f ${template}
|
||||
|
||||
return 0
|
||||
} #create_localca_cert
|
||||
|
||||
usage() {
|
||||
cat << _EOF_
|
||||
Usage: $(basename $1) [options]
|
||||
|
||||
THIS SCRIPT IS EXPERIMENTAL
|
||||
|
||||
The following options are supported:
|
||||
|
||||
--dir directory Directory where to write the CA files into; must not exist
|
||||
unless --overwrite is passed
|
||||
--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
|
||||
--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)
|
||||
--srk-password s Password for the TPM's SRK;
|
||||
Note: the well known password of 20 0x0 is not supported
|
||||
by tpmtool
|
||||
--outfile file File to write the configuration to; if not passed it will be
|
||||
written to stdout only
|
||||
--owner owner The owner of the directory and the files; only set if this
|
||||
script is run as root; recommended to be 'tss'
|
||||
--group group The group owning the directory and the files;
|
||||
recommended to be 'tss'
|
||||
--tss-tcsd-hostname hostname
|
||||
The name of the host where tcsd (TrouSerS daemon) is running
|
||||
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}
|
||||
--help, -h, -? Display this help screen and exit
|
||||
|
||||
|
||||
_EOF_
|
||||
} #usage
|
||||
|
||||
main() {
|
||||
local flags=0
|
||||
local dir outfile owner group msg
|
||||
|
||||
CERTTOOL=certtool
|
||||
export TSS_TCSD_HOSTNAME=${TSS_TCSD_HOSTNAME_DEFAULT}
|
||||
export TSS_TCSD_PORT=${TSS_TCSD_PORT_DEFAULT}
|
||||
|
||||
while [ $# -ne 0 ]; do
|
||||
case "$1" in
|
||||
--dir)
|
||||
shift
|
||||
dir="$1"
|
||||
;;
|
||||
--overwrite)
|
||||
flags=$((flags | FLAG_OVERWRITE))
|
||||
;;
|
||||
--register)
|
||||
flags=$((flags | FLAG_REGISTER_KEY))
|
||||
;;
|
||||
--srk-password)
|
||||
shift
|
||||
TPM_SRK_PASSWORD="$1"
|
||||
;;
|
||||
--key-password)
|
||||
shift
|
||||
TPM_KEY_PASSWORD="$1"
|
||||
;;
|
||||
--outfile)
|
||||
shift
|
||||
outfile="$1"
|
||||
;;
|
||||
--owner)
|
||||
shift
|
||||
owner="$1"
|
||||
;;
|
||||
--group)
|
||||
shift
|
||||
group="$1"
|
||||
;;
|
||||
--tss-tcsd-hostname)
|
||||
shift
|
||||
TSS_TCSD_HOSTNAME="$1"
|
||||
;;
|
||||
--tss-tcsd-port)
|
||||
shift
|
||||
TSS_TCSD_PORT="$2"
|
||||
;;
|
||||
--help|-h|-?)
|
||||
usage "$0"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
logerr "Unsupported option $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [ -z "${dir}" ]; then
|
||||
logerr "Missing --dir option."
|
||||
return 1
|
||||
fi
|
||||
# strip trailing '/' from dir
|
||||
dir="$(echo "${dir}" | sed -n 's|[/]*$||p')"
|
||||
|
||||
if [ -d "${dir}" ] && [ $((flags & FLAG_OVERWRITE)) -eq 0 ]; then
|
||||
logerr "Refusing to overwrite existing directory ${dir}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -z "${TPM_KEY_PASSWORD}" ] && [ $((flags & FLAG_REGISTER_KEY)) -eq 0 ]; then
|
||||
logerr "Key password is required"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
if [ -n "${owner}" ]; then
|
||||
msg="$(id -u "${owner}" 2>&1)"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "User ${owner} cannot be used: ${msg}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
owner="root"
|
||||
fi
|
||||
if [ -n "${group}" ]; then
|
||||
msg="$(id -g "${group}" 2>&1)"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Group ${group} cannot be used: ${msg}"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
group="root"
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "${dir}"
|
||||
if [ $? -ne 0 ]; then
|
||||
logerr "Could not create directory ${dir}."
|
||||
return 1
|
||||
fi
|
||||
|
||||
create_localca_cert "${flags}" "${dir}" "${outfile}" "${owner}"
|
||||
return $?
|
||||
} #main
|
||||
|
||||
main "$@"
|
||||
exit $?
|
||||
Loading…
Reference in New Issue
Block a user