merging swtpm-tools into this project

This commit is contained in:
Stefan Berger 2014-12-05 13:43:21 -05:00
parent 6fc8fb9f4c
commit e46a2b6686
68 changed files with 7184 additions and 10 deletions

7
.gitignore vendored
View File

@ -35,3 +35,10 @@ Makefile
/src/swtpm/swtpm
/src/swtpm/swtpm.h
/src/swtpm/swtpm_cuse
/src/swtpm_bios/swtpm_bios
/src/swtpm_cert/swtpm_cert
/src/swtpm_ioctl/swtpm_ioctl
/src/swtpm_setup/swtpm_setup
/test-driver
tests/*.log
tests/*.trs

View File

@ -5,9 +5,12 @@
#
SUBDIRS = \
etc \
include \
man \
samples \
src \
man
tests
ACLOCAL_AMFLAGS = -I m4

View File

@ -42,7 +42,6 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_LIBTOOL
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([foreign 1.6])
@ -72,6 +71,14 @@ elif test "$DEBUG" == "yes"; then
CFLAGS="$CFLAGS -O0 -g -DDEBUG"
fi
AC_HEADER_STDC
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
GLIB_CFLAGS=$(pkg-config --cflags glib-2.0)
if test $? -ne 0; then
AC_MSG_ERROR("Is glib-2.0 installed? -- could not get cflags")
@ -110,6 +117,11 @@ AC_PROG_INSTALL
#AM_GNU_GETTEXT_VERSION([0.15])
#AM_GNU_GETTEXT([external])
AC_PATH_PROG([TPM_NVDEFINE], tpm_nvdefine)
if test "x$TPM_NVDEFINE" == "x"; then
AC_MSG_ERROR([NVRAM area tools are need: tpm-tools package])
fi
AC_CHECK_LIB([tpms], [TPMLIB_MainInit], [],
[AC_MSG_ERROR([TPM library not found: libtpms.so])])
AC_CHECK_HEADER(libtpms/tpm_library.h, [], \
@ -124,28 +136,69 @@ AC_CHECK_HEADER(cuse_lowlevel.h, [], \
[AC_MSG_ERROR([FUSE library header not found: fuse/cuse_lowlevel.h])])
CFLAGS="$saved_CFLAGS"
AC_HEADER_STDC
AC_C_CONST
AC_C_INLINE
if test "x$with_gnutls" != "xno"; then
GNUTLS_LDFLAGS=$(pkg-config --libs gnutls)
if test $? -ne 0; then
if "x$with_gnutls" == "xyes"; then
AC_MSG_ERROR("Is gnutls installed? -- could not get libs for gnutls")
else
with_gnutls=no
fi
fi
fi
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
saved_CFLAGS="$CFLAGS"
if test "x$with_gnutls" != "xno"; then
CFLAGS=`pkg-config gnutls --cflags`
AC_CHECK_LIB([gnutls], [gnutls_x509_crt_set_key], [],
[if test "x$with_gnutls" == "xyes"; then
AC_MSG_ERROR([GNUTLS >= 3.1.0 library not found: libgnutls.so])
else
with_gnutls="no"
fi])
fi
if test "x$with_gnutls" != "xno"; then
AC_CHECK_HEADER(gnutls/abstract.h, [], \
[if test "x$with_gnutls" == "xyes"; then
AC_MSG_ERROR([GNUTLS >= 3.1.0 library header not found: gnutls/abstract.h])
else
with_gnutls="no"
fi])
fi
if test "x$with_gnutls" != "xno"; then
with_gnutls="yes"
fi
AM_CONDITIONAL([WITH_GNUTLS], [test "x$with_gnutls" == "xyes"])
CFLAGS="$saved_CFLAGS"
CFLAGS="$CFLAGS -Wreturn-type -Wsign-compare -Wswitch-enum"
CFLAGS="$CFLAGS -Wmissing-prototypes -Wall -Werror"
AC_CONFIG_FILES(Makefile \
dist/swtpm.spec \
etc/Makefile \
samples/Makefile \
include/Makefile \
include/swtpm/Makefile \
src/Makefile \
src/selinux/Makefile \
src/swtpm/Makefile \
src/swtpm/swtpm.h \
src/swtpm_bios/Makefile \
src/swtpm_cert/Makefile \
src/swtpm_ioctl/Makefile \
src/swtpm_setup/Makefile \
man/Makefile \
man/man8/Makefile \
tests/Makefile \
)
AC_OUTPUT
echo
echo "with_gnutls : $with_gnutls (no = swtpm_cert will NOT be built)"
echo
echo "CFLAGS=$CFLAGS"
echo "LDFLAGS=$LDFLAGS"

13
etc/Makefile.am Normal file
View File

@ -0,0 +1,13 @@
#
# etc/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
swtpmsysconfdir = $(sysconfdir)
swtpmsysconf_DATA = \
swtpm_setup.conf
EXTRA_DIST= \
swtpm_setup.conf

4
etc/swtpm_setup.conf Executable file
View File

@ -0,0 +1,4 @@
# Program invoked for creating certificates
create_certs_tool= #/usr/share/swtpm-tools/swtpm-localca.sh
create_certs_tool_config = #/etc/swtpm-localca.conf
create_certs_tool_options = #/etc/swtpm-localca.options

View File

@ -7,11 +7,28 @@
man8_PODS = \
swtpm.pod \
swtpm_cuse.pod
swtpm_bios.pod \
swtpm_cert.pod \
swtpm_cuse.pod \
swtpm_ioctl.pod \
swtpm_setup.pod \
swtpm_setup.conf.pod
swtpm-localca.sh.pod \
swtpm-localca.options.pod \
swtpm-localca.conf.pod
man8_MANS = \
swtpm.8 \
swtpm_cuse.8
swtpm_bios.8 \
swtpm_cert.8 \
swtpm_cuse.8 \
swtpm_ioctl.8 \
swtpm_setup.8 \
swtpm_setup.conf.8 \
swtpm_setup.sh.8 \
swtpm-localca.sh.8 \
swtpm-localca.options.8 \
swtpm-localca.conf.8
%.8 : %.pod
@pod2man -r "swtpm" \

View File

@ -0,0 +1,179 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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-localca.conf 8"
.TH swtpm-localca.conf 8 "2014-11-07" "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\-localca.conf
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The file \fI/etc/swtpm\-localca.conf\fR contains configuration variables
for the \fIswtpm\-localca.sh\fR program.
.PP
The following configuration variables must be set:
.IP "\fBstatedir\fR" 4
.IX Item "statedir"
The name of a directory where to store data into. A lock will be created
in this directory.
.IP "\fBsigninkey\fR" 4
.IX Item "signinkey"
The file containing the key used for signing the certificates. Provide
a key in \s-1PEM\s0 format.
.IP "\fBissuercert\fR" 4
.IX Item "issuercert"
The file containing the certificate for this \s-1CA.\s0 Provide a certificate
in \s-1PEM\s0 format.
.IP "\fBcertserial\fR" 4
.IX Item "certserial"
The name of file containing the serial number for the next certificate.
.SH "EXAMPLE"
.IX Header "EXAMPLE"
An example \fIswtpm\-localca.conf\fR file may look as follows:
.PP
.Vb 4
\& statedir = /var/lib/swtpm_localca
\& signingkey = /var/lib/swtpm_localca/signkey.pem
\& issuercert = /var/lib/swtpm_localca/issuercert.pem
\& certserial = /var/lib/swtpm_localca/certserial
.Ve
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBswtpm\-localca.sh\fR
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

View File

@ -0,0 +1,50 @@
=head1 NAME
swtpm-localca.conf
=head1 DESCRIPTION
The file I</etc/swtpm-localca.conf> contains configuration variables
for the I<swtpm-localca.sh> program.
The following configuration variables must be set:
=over 4
=item B<statedir>
The name of a directory where to store data into. A lock will be created
in this directory.
=item B<signinkey>
The file containing the key used for signing the certificates. Provide
a key in PEM format.
=item B<issuercert>
The file containing the certificate for this CA. Provide a certificate
in PEM format.
=item B<certserial>
The name of file containing the serial number for the next certificate.
=back
=head1 EXAMPLE
An example I<swtpm-localca.conf> file may look as follows:
statedir = /var/lib/swtpm_localca
signingkey = /var/lib/swtpm_localca/signkey.pem
issuercert = /var/lib/swtpm_localca/issuercert.pem
certserial = /var/lib/swtpm_localca/certserial
=head1 SEE ALSO
B<swtpm-localca.sh>
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

View File

@ -0,0 +1,165 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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-localca.options 8"
.TH swtpm-localca.options 8 "2014-11-07" "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\-localca.options
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The file \fI/etc/swtpm\-localca.options\fR contains command line options
to pass to the \fIswtpm_setup\fR program and should hold options
that apply to the creation of all \s-1TPM\s0 Endorsement Key (\s-1EK\s0) and platform
certificates.
.SH "EXAMPLE"
.IX Header "EXAMPLE"
an example \fIswtpm\-localca.options\fR file may look as follows:
.PP
\&\-\-tpm\-manufacturer \s-1IBM\s0
\&\-\-tpm\-model swtpm-libtpms
\&\-\-tpm\-version 1.2
\&\-\-platform\-manufacturer Fedora
\&\-\-platform\-version 2.1
\&\-\-platform\-model \s-1QEMU\s0
\&\-\-subject \*(L"C=US,ST=NY,L=Yorktown\*(R"
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBswtpm\-localca.sh\fR
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

View File

@ -0,0 +1,30 @@
=head1 NAME
swtpm-localca.options
=head1 DESCRIPTION
The file I</etc/swtpm-localca.options> contains command line options
to pass to the I<swtpm_setup> program and should hold options
that apply to the creation of all TPM Endorsement Key (EK) and platform
certificates.
=head1 EXAMPLE
an example I<swtpm-localca.options> file may look as follows:
--tpm-manufacturer IBM
--tpm-model swtpm-libtpms
--tpm-version 1.2
--platform-manufacturer Fedora
--platform-version 2.1
--platform-model QEMU
--subject "C=US,ST=NY,L=Yorktown"
=head1 SEE ALSO
B<swtpm-localca.sh>
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

193
man/man8/swtpm-localca.sh.8 Normal file
View File

@ -0,0 +1,193 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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-localca.sh 8"
.TH swtpm-localca.sh 8 "2014-11-07" "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\-localca.sh
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBswtpm\-localca.sh [\s-1OPTIONS\s0]\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBswtpm\-localca.sh\fR is a tool to create \s-1TPM\s0 Endorsement Key (\s-1EK\s0) and platform
certificates on the host. It uses the \fIswtpm_cert\fR program to create
the certificates.
.PP
The program will typically be invoked by the \fIswtpm_setup\fR program
that uses the \fI/etc/swtpm_setup.conf\fR configuration file where
a variable needs to be set that points to this program.
It implements command line options that the \fIswtpm_setup\fR
program uses to provide the necessary parameters to it.
.PP
The following options are supported:
.IP "\fB\-\-type type\fR" 4
.IX Item "--type type"
This parameter indicates the type of certificate to create. The type parameter may
be one of the following: \fIek\fR, or \fIplatform\fR
.IP "\fB\-\-dir dir\fR" 4
.IX Item "--dir dir"
This parameter indicates the directory into which the certificate is to be stored.
The \s-1EK\s0 certificate is stored in this directory under the name
ek.cert and the platform certificate under the name platform.cert.
.IP "\fB\-\-ek ek\fR" 4
.IX Item "--ek ek"
This parameter indicates the modulus of the public key of the endorsement key
(\s-1EK\s0). The public key is provided as a sequence of \s-1ASCII\s0 hex digits.
.IP "\fB\-\-vmid \s-1ID\s0\fR" 4
.IX Item "--vmid ID"
This parameter indicates the \s-1ID\s0 of the \s-1VM\s0 for which to create the certificate.
.IP "\fB\-\-logfile <logfile\fR>" 4
.IX Item "--logfile <logfile>"
The log file to log output to; by default logging goes to stdout and stderr
on the console.
.IP "\fB\-\-configfile <configuration file\fR>" 4
.IX Item "--configfile <configuration file>"
The configuration file to use. If omitted, the default configuration
file \fI/etc/swtpm\-localca.conf\fR will be used.
.IP "\fB\-\-optsfile <options file\fR>" 4
.IX Item "--optsfile <options file>"
The options file to use. If omitted, the default options file
\&\fI/etc/swtpm\-localca.options\fR will be used.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBswtpm\-localca.conf\fR, \fBswtpm\-localca.options\fR,
\&\fBswtpm_setup\fR, \fBswtpm_setup.conf\fR
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

View File

@ -0,0 +1,69 @@
=head1 NAME
swtpm-localca.sh
=head1 SYNOPSIS
B<swtpm-localca.sh [OPTIONS]>
=head1 DESCRIPTION
B<swtpm-localca.sh> is a tool to create TPM Endorsement Key (EK) and platform
certificates on the host. It uses the I<swtpm_cert> program to create
the certificates.
The program will typically be invoked by the I<swtpm_setup> program
that uses the I</etc/swtpm_setup.conf> configuration file where
a variable needs to be set that points to this program.
It implements command line options that the I<swtpm_setup>
program uses to provide the necessary parameters to it.
The following options are supported:
=over 4
=item B<--type type>
This parameter indicates the type of certificate to create. The type parameter may
be one of the following: I<ek>, or I<platform>
=item B<--dir dir>
This parameter indicates the directory into which the certificate is to be stored.
The EK certificate is stored in this directory under the name
ek.cert and the platform certificate under the name platform.cert.
=item B<--ek ek>
This parameter indicates the modulus of the public key of the endorsement key
(EK). The public key is provided as a sequence of ASCII hex digits.
=item B<--vmid ID>
This parameter indicates the ID of the VM for which to create the certificate.
=item B<--logfile <logfile>>
The log file to log output to; by default logging goes to stdout and stderr
on the console.
=item B<--configfile <configuration file>>
The configuration file to use. If omitted, the default configuration
file I</etc/swtpm-localca.conf> will be used.
=item B<--optsfile <options file>>
The options file to use. If omitted, the default options file
I</etc/swtpm-localca.options> will be used.
=back
=head1 SEE ALSO
B<swtpm-localca.conf>, B<swtpm-localca.options>,
B<swtpm_setup>, B<swtpm_setup.conf>
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

203
man/man8/swtpm_bios.8 Normal file
View File

@ -0,0 +1,203 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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_bios 8"
.TH swtpm_bios 8 "2014-07-23" "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_bios
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBswtpm_bios [\s-1OPTIONS\s0]\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBswtpm_bios\fR is a tool that can send the commands to the \s-1TPM \s0(\fIswtpm\fR
program) that typically are used by the \s-1BIOS\s0 to initialize the \s-1TPM.\s0
The user can choose among several command line options as to what the
state should be with which the \s-1TPM\s0 is started.
.PP
This command requires the environment variable \fI\s-1TCSD_USE_TCP_DEVICE\s0\fR
to be set for communication via \s-1TCP.\s0 Otherwise it will use the device
set in the environment variable \fI\s-1TPM_DEVICE\s0\fR or fall back to use
\&\fI/dev/tpm0\fR to send the commands to. In \s-1TCP\s0 mode, the environment variable
\&\fI\s-1TCSD_TCP_DEVICE_HOSTNAME\s0\fR is used to indicate the host to send the commands
to. By default \fIlocalhost\fR is assumed. The default \s-1TCP\s0 port is 6545 unless
the environment variable \fI\s-1TCSD_TCP_DEVICE_PORT\s0\fR indicates another port.
.PP
This command will send the following sequence of commands to the \s-1TPM.\s0
.IP "\fBTPM_Startup(chosen mode)\fR \*(-- startup \s-1TPM\s0" 4
.IX Item "TPM_Startup(chosen mode) startup TPM"
.PD 0
.IP "\fBTSC_PhysicalPresence(0x20)\fR \*(-- PhysicalPresenceCMDEnable" 4
.IX Item "TSC_PhysicalPresence(0x20) PhysicalPresenceCMDEnable"
.IP "\fBTSC_PhysicalPresence(0x08)\fR \*(-- turn on physical presence" 4
.IX Item "TSC_PhysicalPresence(0x08) turn on physical presence"
.IP "\fBTPM_PhysicalEnable\fR \*(-- enable the \s-1TPM\s0" 4
.IX Item "TPM_PhysicalEnable enable the TPM"
.IP "\fBTPM_PhysicalSetDeactivated(0x0)\fR \*(-- activate \s-1TPM\s0" 4
.IX Item "TPM_PhysicalSetDeactivated(0x0) activate TPM"
.IP "\fBTPM_ContinueSelfTest\fR \*(-- continue self test" 4
.IX Item "TPM_ContinueSelfTest continue self test"
.PD
.PP
The following options are supported:
.IP "\fB\-c\fR" 4
.IX Item "-c"
Send TPM_Startup(\s-1ST_CLEAR\s0) (default). This instructs the \s-1TPM\s0 to start
with clear state.
.IP "\fB\-s\fR" 4
.IX Item "-s"
Send TPM_Startup(\s-1ST_STATE\s0). This instructs the \s-1TPM\s0 to start by restoring
previously saved state.
.IP "\fB\-d\fR" 4
.IX Item "-d"
Send TPM_Startup(\s-1ST_DEACTIVATED\s0). This instructs the \s-1TPM\s0 to start in
deactivated mode.
.IP "\fB\-n\fR" 4
.IX Item "-n"
Don't send a TPM_Startup command.
.IP "\fB\-o\fR" 4
.IX Item "-o"
Only send the startup command and nothing else.
.IP "\fB\-cs\fR" 4
.IX Item "-cs"
Send a TPM_ContinueSelfTest command.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

79
man/man8/swtpm_bios.pod Normal file
View File

@ -0,0 +1,79 @@
=head1 NAME
swtpm_bios
=head1 SYNOPSIS
B<swtpm_bios [OPTIONS]>
=head1 DESCRIPTION
B<swtpm_bios> is a tool that can send the commands to the TPM (I<swtpm>
program) that typically are used by the BIOS to initialize the TPM.
The user can choose among several command line options as to what the
state should be with which the TPM is started.
This command requires the environment variable I<TCSD_USE_TCP_DEVICE>
to be set for communication via TCP. Otherwise it will use the device
set in the environment variable I<TPM_DEVICE> or fall back to use
I</dev/tpm0> to send the commands to. In TCP mode, the environment variable
I<TCSD_TCP_DEVICE_HOSTNAME> is used to indicate the host to send the commands
to. By default I<localhost> is assumed. The default TCP port is 6545 unless
the environment variable I<TCSD_TCP_DEVICE_PORT> indicates another port.
This command will send the following sequence of commands to the TPM.
=over 4
=item B<TPM_Startup(chosen mode)> -- startup TPM
=item B<TSC_PhysicalPresence(0x20)> -- PhysicalPresenceCMDEnable
=item B<TSC_PhysicalPresence(0x08)> -- turn on physical presence
=item B<TPM_PhysicalEnable> -- enable the TPM
=item B<TPM_PhysicalSetDeactivated(0x0)> -- activate TPM
=item B<TPM_ContinueSelfTest> -- continue self test
=back
The following options are supported:
=over 4
=item B<-c>
Send TPM_Startup(ST_CLEAR) (default). This instructs the TPM to start
with clear state.
=item B<-s>
Send TPM_Startup(ST_STATE). This instructs the TPM to start by restoring
previously saved state.
=item B<-d>
Send TPM_Startup(ST_DEACTIVATED). This instructs the TPM to start in
deactivated mode.
=item B<-n>
Don't send a TPM_Startup command.
=item B<-o>
Only send the startup command and nothing else.
=item B<-cs>
Send a TPM_ContinueSelfTest command.
=back
=head1 SEE ALSO
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

220
man/man8/swtpm_cert.8 Normal file
View File

@ -0,0 +1,220 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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_cert 8"
.TH swtpm_cert 8 "2014-09-23" "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_cert
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBswtpm_cert [\s-1OPTIONS\s0]\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBswtpm_cert\fR is a local \s-1CA\s0 tool for creating X.509v3 certificates for the \s-1TPM\s0's
Endorsement Key. The reason for this specific tool is that it works without access
to the Endorsement Key's private key. Typically tools require either a self-signed
certificate request or access to the private key to issue a certificate.
This tool works with only the public key part.
.PP
The following options are supported:
.IP "\fB\-\-type {ek|platform|aik}\fR" 4
.IX Item "--type {ek|platform|aik}"
The type of certificate to create; by default an \s-1EK\s0 certificate is created.
.IP "\fB\-\-pubkey <filename\fR>" 4
.IX Item "--pubkey <filename>"
The public key (\s-1EK\s0) in \s-1PEM\s0 format.
.IP "\fB\-\-modulus <hex digits\fR>" 4
.IX Item "--modulus <hex digits>"
The modulus of the public key as a string of hex digits. This option
can be used in place of the \-\-pubkey option.
.IP "\fB\-\-exponent <exponent\fR>" 4
.IX Item "--exponent <exponent>"
The exponent of the public key. By default 0x10001 is assumed.
.IP "\fB\-\-signkey <filename\fR>" 4
.IX Item "--signkey <filename>"
The key used for signing the certificate. The file must be in \s-1PEM\s0 format.
.IP "\fB\-\-signkey\-password <password\fR>" 4
.IX Item "--signkey-password <password>"
Optional password for the signing key.
.IP "\fB\-\-issuercert <filename\fR>" 4
.IX Item "--issuercert <filename>"
The X.509 certificate of this signer that takes on the role of a local \s-1CA.\s0
.IP "\fB\-\-out\-cert <filename\fR>" 4
.IX Item "--out-cert <filename>"
The name of the file to write the X.509v3 certificate into. The output will
be in \s-1PEM\s0 format.
.IP "\fB\-\-serial <serial number\fR>" 4
.IX Item "--serial <serial number>"
Optional 32bit serial number for the certificate.
.IP "\fB\-\-days <number\fR>" 4
.IX Item "--days <number>"
The number of days the certificate is valid; by default it is valid for 365 days.
.IP "\fB\-\-pem\fR" 4
.IX Item "--pem"
Write the resulting certificate in \s-1PEM\s0 format; \s-1DER\s0 format is the default.
.IP "\fB\-\-tpm\-manufacturer <name\fR>" 4
.IX Item "--tpm-manufacturer <name>"
The name of the \s-1TPM\s0 manufacturer.
.IP "\fB\-\-tpm\-model <model\fR>" 4
.IX Item "--tpm-model <model>"
The \s-1TPM\s0 model (part number).
.IP "\fB\-\-tpm\-version <version\fR>" 4
.IX Item "--tpm-version <version>"
The \s-1TPM\s0's firmware version.
.IP "\fB\-\-platform\-manufacturer <name\fR>" 4
.IX Item "--platform-manufacturer <name>"
The name of the platform manufacturer.
.IP "\fB\-\-platform\-model <model\fR>" 4
.IX Item "--platform-model <model>"
The platform model.
.IP "\fB\-\-platform\-version <version\fR>" 4
.IX Item "--platform-version <version>"
The platform's version.
.IP "\fB\-\-subject <subject\fR>" 4
.IX Item "--subject <subject>"
Subject to for example provide the location of the \s-1TPM\s0 in the format of
C=<country>,ST=<state>,L=<location>.
Note that the location must no contain any spaces.
.IP "\fB\-\-help, \-h\fR" 4
.IX Item "--help, -h"
Display the help screen
.SH "SEE ALSO"
.IX Header "SEE ALSO"
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

108
man/man8/swtpm_cert.pod Normal file
View File

@ -0,0 +1,108 @@
=head1 NAME
swtpm_cert
=head1 SYNOPSIS
B<swtpm_cert [OPTIONS]>
=head1 DESCRIPTION
B<swtpm_cert> is a local CA tool for creating X.509v3 certificates for the TPM's
Endorsement Key. The reason for this specific tool is that it works without access
to the Endorsement Key's private key. Typically tools require either a self-signed
certificate request or access to the private key to issue a certificate.
This tool works with only the public key part.
The following options are supported:
=over 4
=item B<--type {ek|platform|aik}>
The type of certificate to create; by default an EK certificate is created.
=item B<--pubkey <filename>>
The public key (EK) in PEM format.
=item B<--modulus <hex digits>>
The modulus of the public key as a string of hex digits. This option
can be used in place of the --pubkey option.
=item B<--exponent <exponent>>
The exponent of the public key. By default 0x10001 is assumed.
=item B<--signkey <filename>>
The key used for signing the certificate. The file must be in PEM format.
=item B<--signkey-password <password>>
Optional password for the signing key.
=item B<--issuercert <filename>>
The X.509 certificate of this signer that takes on the role of a local CA.
=item B<--out-cert <filename>>
The name of the file to write the X.509v3 certificate into. The output will
be in PEM format.
=item B<--serial <serial number>>
Optional 32bit serial number for the certificate.
=item B<--days <number>>
The number of days the certificate is valid; by default it is valid for 365 days.
=item B<--pem>
Write the resulting certificate in PEM format; DER format is the default.
=item B<--tpm-manufacturer <name>>
The name of the TPM manufacturer.
=item B<--tpm-model <model>>
The TPM model (part number).
=item B<--tpm-version <version>>
The TPM's firmware version.
=item B<--platform-manufacturer <name>>
The name of the platform manufacturer.
=item B<--platform-model <model>>
The platform model.
=item B<--platform-version <version>>
The platform's version.
=item B<--subject <subject>>
Subject to for example provide the location of the TPM in the format of
C=<country>,ST=<state>,L=<location>.
Note that the location must no contain any spaces.
=item B<--help, -h>
Display the help screen
=back
=head1 SEE ALSO
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

189
man/man8/swtpm_ioctl.8 Normal file
View File

@ -0,0 +1,189 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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_ioctl 8"
.TH swtpm_ioctl 8 "2014-09-04" "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_ioctl
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBswtpm_ioctl [\s-1COMMAND\s0] <device>\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBswtpm_ioctl\fR implements a client tool for controlling the
\&\fIswtpm_cuse\fR \s-1TPM\s0 software emulator, such as for example its
initialization and shutdown. Once the swtpm_cuse has been
initialized, \s-1TPM\s0 commands can be sent to it.
.PP
The full path to the swtpm_cuse's character device must be provided such
as for example /dev/vtpm\-200.
.PP
The following commands are supported:
.IP "\fB\-c\fR" 4
.IX Item "-c"
Get the swtpm_cuse's capability flags indicating which commands
are supported.
.IP "\fB\-i\fR" 4
.IX Item "-i"
Send a hardware initialization signal to the swtpm_cuse. Volatile
state previously written by the \s-1TPM\s0 will be read and the file automatically
delete.
.IP "\fB\-s\fR" 4
.IX Item "-s"
Gracefully shut the swtpm_cuse down.
.IP "\fB\-e\fR" 4
.IX Item "-e"
Get the tpmEstablished bit.
.IP "\fB\-l locality\fR" 4
.IX Item "-l locality"
Set the locality for the subsequent \s-1TPM\s0 commands.
.IP "\fB\-v\fR" 4
.IX Item "-v"
Have the \s-1TPM\s0 write the volatile state to a file. Upon a TPM_Init (\-i) the
\&\s-1TPM\s0 state will be read and the \s-1TPM\s0 can then resume operation without further
intialization.
.IP "\fB\-C\fR" 4
.IX Item "-C"
Cancel an ongoing \s-1TPM\s0 command.
.IP "\fB\-h data\fR" 4
.IX Item "-h data"
Reset and extend \s-1PCR 17\s0 with the hash of the given data. If data is the single
character '\-', then all data are read from stdin.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBswtpm_cuse\fR

65
man/man8/swtpm_ioctl.pod Normal file
View File

@ -0,0 +1,65 @@
=head1 NAME
swtpm_ioctl
=head1 SYNOPSIS
B<swtpm_ioctl [COMMAND] E<lt>deviceE<gt>>
=head1 DESCRIPTION
B<swtpm_ioctl> implements a client tool for controlling the
I<swtpm_cuse> TPM software emulator, such as for example its
initialization and shutdown. Once the swtpm_cuse has been
initialized, TPM commands can be sent to it.
The full path to the swtpm_cuse's character device must be provided such
as for example /dev/vtpm-200.
The following commands are supported:
=over 4
=item B<-c>
Get the swtpm_cuse's capability flags indicating which commands
are supported.
=item B<-i>
Send a hardware initialization signal to the swtpm_cuse. Volatile
state previously written by the TPM will be read and the file automatically
delete.
=item B<-s>
Gracefully shut the swtpm_cuse down.
=item B<-e>
Get the tpmEstablished bit.
=item B<-l locality>
Set the locality for the subsequent TPM commands.
=item B<-v>
Have the TPM write the volatile state to a file. Upon a TPM_Init (-i) the
TPM state will be read and the TPM can then resume operation without further
intialization.
=item B<-C>
Cancel an ongoing TPM command.
=item B<-h data>
Reset and extend PCR 17 with the hash of the given data. If data is the single
character '-', then all data are read from stdin.
=back
=head1 SEE ALSO
B<swtpm_cuse>

220
man/man8/swtpm_setup.8 Normal file
View File

@ -0,0 +1,220 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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_setup 8"
.TH swtpm_setup 8 "2014-11-19" "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_setup
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBswtpm_setup [\s-1OPTIONS\s0]\fR
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBswtpm_setup\fR is a tool that prepares the intial state for a libtpms-based
\&\s-1TPM.\s0
.PP
The following options are supported:
.IP "\fB\-\-runas <userid\fR>" 4
.IX Item "--runas <userid>"
Use this userid to run swtpm_setup.sh; by default 'tss' is used.
.IP "\fB\-\-config <file\fR>" 4
.IX Item "--config <file>"
Path to configuration file containing the tool to use for creating
certificates; see also \fBswtpm_setup.conf\fR
.IP "\fB\-\-tpm\-state <dir\fR>" 4
.IX Item "--tpm-state <dir>"
Path to a directory where the \s-1TPM\s0's state will be written into;
this is a mandatory argument
.IP "\fB\-\-tpm\-executable\fR" 4
.IX Item "--tpm-executable"
Path to the \s-1TPM\s0 executable; this is an optional argument and
by default /usr/bin/swtpm is used
.IP "\fB\-\-createek\fR" 4
.IX Item "--createek"
Create the \s-1EK\s0
.IP "\fB\-\-take\-ownership\fR" 4
.IX Item "--take-ownership"
Take ownership; this option implies \-\-createek
.IP "\fB\-\-ownerpass <password\fR>" 4
.IX Item "--ownerpass <password>"
Provide custom owner password; default is ooo
.IP "\fB\-\-owner\-well\-known\fR" 4
.IX Item "--owner-well-known"
Use a password of all zeros (20 bytes of zeros) as the owner password
.IP "\fB\-\-srkpass <password\fR>" 4
.IX Item "--srkpass <password>"
Provide custom \s-1SRK\s0 password; default is sss
.IP "\fB\-\-srk\-well\-known\fR" 4
.IX Item "--srk-well-known"
Use a password of all zeros (20 bytes of zeros) as the \s-1SRK\s0 password
.IP "\fB\-\-create\-ek\-cert\fR" 4
.IX Item "--create-ek-cert"
Create an \s-1EK\s0 certificate; this implies \-\-createek
(\s-1NOT SUPPORTED YET\s0)
.IP "\fB\-\-create\-platform\-cert\fR" 4
.IX Item "--create-platform-cert"
Create a platform certificate; this implies \-\-create\-ek\-cert
.IP "\fB\-\-lock\-nvram\fR" 4
.IX Item "--lock-nvram"
Lock \s-1NVRAM\s0 access
.IP "\fB\-\-display\fR" 4
.IX Item "--display"
At the end display as much info as possible about the configuration
of the \s-1TPM\s0
.IP "\fB\-\-logfile <logfile\fR>" 4
.IX Item "--logfile <logfile>"
The logfile to log to. By default logging goes to stdout and stderr.
.IP "\fB\-\-keyfile <keyfile\fR>" 4
.IX Item "--keyfile <keyfile>"
The key file contains an \s-1ASCII\s0 hex key consisting of 32 hex digits with an
optional leading '0x'. This is the key to be used by the \s-1TPM\s0 emulator
for encrypting the state of the \s-1TPM. \s0
.IP "\fB\-\-pwdfile <passphrase file\fR>" 4
.IX Item "--pwdfile <passphrase file>"
The passpharse file contains a passphrase from which the \s-1TPM\s0 emulator
will derive the encyrption key from and use the key for encrypting the \s-1TPM\s0
state.
.IP "\fB\-\-help, \-h\fR" 4
.IX Item "--help, -h"
Display the help screen
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBswtpm_setup.conf\fR
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

208
man/man8/swtpm_setup.conf.8 Normal file
View File

@ -0,0 +1,208 @@
.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" 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 turned on, 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_setup.conf 8"
.TH swtpm_setup.conf 8 "2014-11-07" "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_setup.conf
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The file \fI/etc/swtpm_setup.conf\fR contains configuration information for
the swtpm_setup and swtpm_setup.sh programs. It must only contain
one configuration keywork per line, followed by an equals sign (=) and then
followed by appropriate configuration information. A comment at the
end of the line may be introduced by a hash (#) sign.
.PP
The following keywords are recognized:
.IP "\fBcreate_certs_tool\fR" 4
.IX Item "create_certs_tool"
This keyword is to be followed by the name of an executable or exectuable
script used for creating various \s-1TPM\s0 certificates. The tool will be
called with the following options
.RS 4
.IP "\fB\-\-type type\fR" 4
.IX Item "--type type"
This parameter indicates the type of certificate to create. The type parameter may
be one of the following: \fIek\fR, or \fIplatform\fR
.IP "\fB\-\-dir dir\fR" 4
.IX Item "--dir dir"
This parameter indicates the directory into which the certificate is to be stored.
It is expected that the \s-1EK\s0 certificate is stored in this directory under the name
ek.cert and the platform certificate under the name platform.cert.
.IP "\fB\-\-ek ek\fR" 4
.IX Item "--ek ek"
This parameter indicates the modulus of the public key of the endorsement key
(\s-1EK\s0). The public key is provided as a sequence of \s-1ASCII\s0 hex digits.
.IP "\fB\-\-vmid \s-1ID\s0\fR" 4
.IX Item "--vmid ID"
This parameter indicates the \s-1ID\s0 of the \s-1VM\s0 for which to create the certificate.
.IP "\fB\-\-logfile <logfile\fR>" 4
.IX Item "--logfile <logfile>"
The log file to log output to; by default logging goes to stdout and stderr
on the console.
.IP "\fB\-\-configfile <configuration file\fR>" 4
.IX Item "--configfile <configuration file>"
The configuration file to use. This file typically contains configuration
information for the invoked program. If omitted, the program must use
its default configuration file.
.IP "\fB\-\-optsfile <options file\fR>" 4
.IX Item "--optsfile <options file>"
The options file to use. This file typically contains options that the
invoked program uses. If omitted, the program must use its default
options file.
.RE
.RS 4
.RE
.IP "\fBcreate_certs_tool_config\fR" 4
.IX Item "create_certs_tool_config"
This keyword is to be followed by the name of a configuration file
that will be passed to the invoked program using the \-\-configfile
option described above. If omitted, the invoked program will use
the default configuration file.
.IP "\fBcreate_certs_tool_options\fR" 4
.IX Item "create_certs_tool_options"
This keyword is to be followed by the name of an options file
that will be passed to the invoked program using the \-\-optsfile
option described above. If omitted, the invoked program will use
the default options file.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBswtpm_setup\fR
.SH "REPORTING BUGS"
.IX Header "REPORTING BUGS"
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

View File

@ -0,0 +1,86 @@
=head1 NAME
swtpm_setup.conf
=head1 DESCRIPTION
The file I</etc/swtpm_setup.conf> contains configuration information for
the swtpm_setup and swtpm_setup.sh programs. It must only contain
one configuration keywork per line, followed by an equals sign (=) and then
followed by appropriate configuration information. A comment at the
end of the line may be introduced by a hash (#) sign.
The following keywords are recognized:
=over 4
=item B<create_certs_tool>
This keyword is to be followed by the name of an executable or exectuable
script used for creating various TPM certificates. The tool will be
called with the following options
=over 4
=item B<--type type>
This parameter indicates the type of certificate to create. The type parameter may
be one of the following: I<ek>, or I<platform>
=item B<--dir dir>
This parameter indicates the directory into which the certificate is to be stored.
It is expected that the EK certificate is stored in this directory under the name
ek.cert and the platform certificate under the name platform.cert.
=item B<--ek ek>
This parameter indicates the modulus of the public key of the endorsement key
(EK). The public key is provided as a sequence of ASCII hex digits.
=item B<--vmid ID>
This parameter indicates the ID of the VM for which to create the certificate.
=item B<--logfile <logfile>>
The log file to log output to; by default logging goes to stdout and stderr
on the console.
=item B<--configfile <configuration file>>
The configuration file to use. This file typically contains configuration
information for the invoked program. If omitted, the program must use
its default configuration file.
=item B<--optsfile <options file>>
The options file to use. This file typically contains options that the
invoked program uses. If omitted, the program must use its default
options file.
=back
=item B<create_certs_tool_config>
This keyword is to be followed by the name of a configuration file
that will be passed to the invoked program using the --configfile
option described above. If omitted, the invoked program will use
the default configuration file.
=item B<create_certs_tool_options>
This keyword is to be followed by the name of an options file
that will be passed to the invoked program using the --optsfile
option described above. If omitted, the invoked program will use
the default options file.
=back
=head1 SEE ALSO
B<swtpm_setup>
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

107
man/man8/swtpm_setup.pod Normal file
View File

@ -0,0 +1,107 @@
=head1 NAME
swtpm_setup
=head1 SYNOPSIS
B<swtpm_setup [OPTIONS]>
=head1 DESCRIPTION
B<swtpm_setup> is a tool that prepares the intial state for a libtpms-based
TPM.
The following options are supported:
=over 4
=item B<--runas <userid>>
Use this userid to run swtpm_setup.sh; by default 'tss' is used.
=item B<--config <file>>
Path to configuration file containing the tool to use for creating
certificates; see also B<swtpm_setup.conf>
=item B<--tpm-state <dir>>
Path to a directory where the TPM's state will be written into;
this is a mandatory argument
=item B<--tpm-executable>
Path to the TPM executable; this is an optional argument and
by default /usr/bin/swtpm is used
=item B<--createek>
Create the EK
=item B<--take-ownership>
Take ownership; this option implies --createek
=item B<--ownerpass <password>>
Provide custom owner password; default is ooo
=item B<--owner-well-known>
Use a password of all zeros (20 bytes of zeros) as the owner password
=item B<--srkpass <password>>
Provide custom SRK password; default is sss
=item B<--srk-well-known>
Use a password of all zeros (20 bytes of zeros) as the SRK password
=item B<--create-ek-cert>
Create an EK certificate; this implies --createek
(NOT SUPPORTED YET)
=item B<--create-platform-cert>
Create a platform certificate; this implies --create-ek-cert
=item B<--lock-nvram>
Lock NVRAM access
=item B<--display>
At the end display as much info as possible about the configuration
of the TPM
=item B<--logfile <logfile>>
The logfile to log to. By default logging goes to stdout and stderr.
=item B<--keyfile <keyfile>>
The key file contains an ASCII hex key consisting of 32 hex digits with an
optional leading '0x'. This is the key to be used by the TPM emulator
for encrypting the state of the TPM.
=item B<--pwdfile <passphrase file>>
The passpharse file contains a passphrase from which the TPM emulator
will derive the encyrption key from and use the key for encrypting the TPM
state.
=item B<--help, -h>
Display the help screen
=back
=head1 SEE ALSO
B<swtpm_setup.conf>
=head1 REPORTING BUGS
Report bugs to Stefan Berger <stefanb@linux.vnet.ibm.com>

View File

@ -0,0 +1 @@
.so man8/swtpm_setup.8

20
samples/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
#
# samples/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
samplesconfdir = $(datadir)/@PACKAGE@
samplessysconfdir = $(sysconfdir)
samplesconf_DATA = \
swtpm-localca.sh
samplessysconf_DATA = \
swtpm-localca.conf \
swtpm-localca.options
EXTRA_DIST= \
swtpm-localca.conf \
swtpm-localca.options \
swtpm-localca.sh

View File

@ -0,0 +1,4 @@
statedir = /var/lib/swtpm_localca
signingkey = /var/lib/swtpm_localca/signkey.pem
issuercert = /var/lib/swtpm_localca/issuercert.pem
certserial = /var/lib/swtpm_localca/certserial

View File

@ -0,0 +1,6 @@
--tpm-manufacturer IBM
--tpm-model swtpm-libtpms
--tpm-version 1.2
--platform-manufacturer Fedora
--platform-version 2.1
--platform-model QEMU

305
samples/swtpm-localca.sh Normal file
View File

@ -0,0 +1,305 @@
#!/bin/bash
#
# sample/swtpm-localca.sh
#
# Authors: Stefan Berger <stefanb@us.ibm.com>
#
# (c) Copyright IBM Corporation 2014.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# Neither the names of the IBM Corporation nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
LOCALCA_OPTIONS=/etc/swtpm-localca.options
LOCALCA_CONFIG=/etc/swtpm-localca.conf
# Default logging goes to stderr
LOGFILE=""
logit()
{
if [ -z "$LOGFILE" ]; then
echo "$1" >&1
else
echo "$1" >> $LOGFILE
fi
}
logerr()
{
if [ -z "$LOGFILE" ]; then
echo "Error: $1" >&2
else
echo "Error: $1" >> $LOGFILE
fi
}
# Get an configuration value from an configurations file
# @param1: The file with the options
# @param2: The name of the option
get_config_value() {
local configfile="$1"
local configname="$(echo "$2" | sed 's/-/\\-/g')"
local defaultvalue="$3"
local tmp
if [ ! -r $configfile ]; then
logerr "Cannot read config file $configfile"
return 1
fi
tmp=$(sed -n "s/^${configname}[[:space:]]*=[[:space:]]*\([^ ]\+\)/\1/p" \
$configfile)
if [ -z "$tmp" ]; then
if [ -n "$defaultvalue" ]; then
echo "$defaultvalue"
else
return 1
fi
else
echo "$tmp"
fi
return 0
}
get_next_cert_serial() {
local serial
touch ${LOCK}
(
# Avoid concurrent creation of next serial
flock -e 200
if [ ! -r ${CERTSERIAL} ]; then
echo -n "0" > ${CERTSERIAL}
fi
serial=$(cat ${CERTSERIAL})
if ! [[ "$serial" =~ ^[0-9]+$ ]]; then
serial=1
else
serial=$((serial+1))
fi
echo -n $serial > ${CERTSERIAL}
echo $serial
) 200>${LOCK}
}
create_cert() {
local typ="$1"
local dir="$2"
local ek="$3"
local vmid="$4"
local serial=$(get_next_cert_serial)
local options
if [ -r "${LOCALCA_OPTIONS}" ]; then
options=$(cat ${LOCALCA_OPTIONS})
fi
case "$typ" in
ek)
if [ -z "$(type -p swtpm_cert)" ]; then
echo "Missing swtpm_cert tool" > ${dir}/ek.cert
else
eval swtpm_cert \
$options \
--signkey ${SIGNKEY} \
--issuercert ${ISSUERCERT} \
--out-cert ${dir}/ek.cert \
--modulus "${ek}" \
--days $((10*365)) \
--serial $serial
if [ $? -eq 0 ]; then
logit "Successfully created EK certificate locally."
else
logerr "Could not create EK certificate locally."
fi
fi
;;
platform)
if [ -z "$(type -p swtpm_cert)" ]; then
echo "Missing swtpm_cert tool" > ${dir}/platform.cert
else
eval swtpm_cert \
$options \
--type platform \
--signkey ${SIGNKEY} \
--issuercert ${ISSUERCERT} \
--out-cert ${dir}/platform.cert \
--modulus "${ek}" \
--days $((10*365)) \
--serial $serial
if [ $? -eq 0 ]; then
logit "Successfully created platform certificate locally."
else
logerr "Could not create platform certificate locally."
fi
fi
;;
esac
}
# Create the local CA's (self signed) certificate if it doesn't already exist.
#
create_localca_cert() {
touch ${LOCK}
(
# Avoid concurrent creation of keys and certs
flock -e 200
if [ ! -d ${STATEDIR} ]; then
# RPM installation must have created this already ...
# so user tss can use it (user tss cannot create it)
mkdir -p ${STATEDIR}
fi
if [ ! -r ${SIGNKEY} ]; then
certtool --generate-privkey > ${SIGNKEY}
local tmp=$(mktemp)
echo "cn=swtpm-localca" > ${tmp}
echo "ca" >> ${tmp}
echo "cert_signing_key" >> ${tmp}
certtool \
--generate-self-signed \
--template ${tmp} \
--outfile ${ISSUERCERT} \
--load-privkey ${SIGNKEY}
rm -f ${tmp}
fi
) 200>${LOCK}
}
main() {
local typ ek dir vmid tmp
while [ $# -ne 0 ]; do
case "$1" in
--type)
shift
typ="$1"
;;
--ek)
shift
ek="$1"
;;
--dir)
shift
dir="$1"
;;
--vmid)
shift
vmid="$1"
;;
--optsfile)
shift
LOCALCA_OPTIONS="$1"
;;
--configfile)
shift
LOCALCA_CONFIG="$1"
;;
--logfile)
shift
LOGFILE="$1"
esac
shift
done
if [ -n "$LOGFILE" ]; then
touch $LOGFILE &>/dev/null
if [ ! -w "$LOGFILE" ]; then
logerr "Cannot write to logfile ${LOGFILE}."
exit 1
fi
fi
if [ ! -r "$LOCALCA_OPTIONS" ]; then
logerr "Cannot access options file ${LOCALCA_OPTIONS}."
exit 1
fi
if [ ! -r "$LOCALCA_CONFIG" ]; then
logerr "Cannot access config file ${LOCALCA_CONFIG}."
exit 1
fi
tmp=$(get_config_value "$LOCALCA_CONFIG" "statedir")
if [ -z "$tmp" ]; then
logerr "Missing 'statedir' config value in config file ${LOCALCA_CONFIG}"
exit 1
fi
STATEDIR="$tmp"
if [ ! -d "$STATEDIR" ]; then
mkdir -p "$STATEDIR"
if [ $? -ne 0 ]; then
logerr "Could not create directory '${STATEDIR}."
exit 1
fi
fi
LOCK="${STATEDIR}/.lock"
if [ ! -w ${LOCK} ]; then
touch $LOCK
if [ ! -w ${LOCK} ]; then
logerr "Could not create lock file ${LOCK}."
exit 1
fi
fi
SIGNKEY=$(get_config_value "$LOCALCA_CONFIG" "signingkey")
if [ -z "$SIGNKEY" ]; then
logerr "Missing signingkey variable in config file $LOCALCA_CONFIG."
exit 1
fi
if [ ! -r "$SIGNKEY" ]; then
logerr "Cannot access signing key ${SIGNKEY}."
exit 1
fi
ISSUERCERT=$(get_config_value "$LOCALCA_CONFIG" "issuercert")
if [ -z "$ISSUERCERT" ]; then
logerr "Missing issuercert variable in config file $LOCALCA_CONFIG."
exit 1
fi
if [ ! -r "$ISSUERCERT" ]; then
logerr "Cannot access issuer certificate ${ISSUERCERT}."
exit 1
fi
CERTSERIAL=$(get_config_value "$LOCALCA_CONFIG" "certserial" \
"${STATEDIR}/certserial")
create_localca_cert
create_cert "$typ" "$dir" "$ek" "$vmid"
}
main "$@" # 2>&1 | tee -a /tmp/localca.log

View File

@ -6,4 +6,8 @@
SUBDIRS = \
selinux \
swtpm
swtpm \
swtpm_bios \
swtpm_cert \
swtpm_ioctl \
swtpm_setup

View File

@ -0,0 +1,12 @@
#
# src/swtpm_bios/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
noinst_HEADERS =
bin_PROGRAMS = \
swtpm_bios
swtpm_bios_SOURCES = tpm_bios.c

327
src/swtpm_bios/tpm_bios.c Normal file
View File

@ -0,0 +1,327 @@
/*
* tpm_bios --
*
* Authors: Ken Goldman <kgoldman@us.ibm.com>
* Stefan Berger <stefanb@us.ibm.com>
*
* (c) Copyright IBM Corporation 2014.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the names of the IBM Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/un.h>
static int open_connection(void)
{
int fd = -1, tcp_device_port;
char *tcp_device_hostname = NULL;
char *un_socket_device_path = NULL;
char *tcp_device_port_string = NULL;
if (getenv("TCSD_USE_TCP_DEVICE")) {
if ((tcp_device_hostname = getenv("TCSD_TCP_DEVICE_HOSTNAME")) == NULL)
tcp_device_hostname = "localhost";
if ((tcp_device_port_string = getenv("TCSD_TCP_DEVICE_PORT")) != NULL)
tcp_device_port = atoi(tcp_device_port_string);
else
tcp_device_port = 6545;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd >= 0) {
struct hostent *host = gethostbyname(tcp_device_hostname);
if (host != NULL) {
struct sockaddr_in addr;
memset(&addr, 0x0, sizeof(addr));
addr.sin_family = host->h_addrtype;
addr.sin_port = htons(tcp_device_port);
memcpy(&addr.sin_addr,
host->h_addr,
host->h_length);
if (connect(fd, (struct sockaddr *)&addr,
sizeof(addr)) < 0) {
close(fd);
fd = -1;
}
} else {
close (fd);
fd = -1;
}
}
if (fd < 0 && un_socket_device_path) {
struct sockaddr_un addr;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd >= 0) {
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, un_socket_device_path,
sizeof(addr.sun_path));
if (connect(fd, (void *)&addr, sizeof(addr)) < 0) {
close(fd);
fd = -1;
}
}
}
if (fd < 0) {
printf("Could not connect using TCP or UNIXIO socket.\n");
}
} else {
char *devname = getenv("TPM_DEVICE");
if (!devname)
devname = "/dev/tpm0";
fd = open(devname, O_RDWR );
if ( fd < 0 ) {
printf( "Unable to open device '%s'.\n", devname );
}
}
return fd;
}
static int talk(const unsigned char *buf, size_t count, int *tpm_errcode)
{
ssize_t len;
unsigned int pkt_len;
int rc = -1;
int fd;
unsigned char buffer[1024];
fd = open_connection();
if (fd < 0) {
goto err_exit;
}
len = write(fd, buf, count);
if (len < 0 || (size_t)len != count) {
printf("Write to file descriptor failed.\n");
goto err_close_fd;
}
len = read(fd, buffer, sizeof(buffer));
if (len < 0) {
printf("Read from file descriptor failed.\n");
goto err_close_fd;
}
if (len < 10) {
printf("Returned packet is too short.\n");
goto err_close_fd;
}
pkt_len = ntohl( *((uint32_t *)(buffer + 2)));
if ((unsigned int)len != pkt_len) {
printf("Malformed response.\n");
goto err_close_fd;
}
*tpm_errcode = ntohl( *((uint32_t *)(buffer + 6)));
rc = 0;
err_close_fd:
close(fd);
fd = -1;
err_exit:
return rc;
}
static int TPM_Startup(unsigned char parm, int *tpm_errcode)
{
unsigned char tpm_startup[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99,
0x00, 0x01
};
tpm_startup[11] = parm;
return talk(tpm_startup, sizeof(tpm_startup), tpm_errcode);
}
static int TSC_PhysicalPresence(unsigned short parm, int *tpm_errcode)
{
unsigned char tsc_pp[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a,
0x00, 0x20
};
tsc_pp[10] = parm >> 8;
tsc_pp[11] = parm;
return talk(tsc_pp, sizeof(tsc_pp), tpm_errcode);
}
static int TPM_PhysicalEnable(int *tpm_errcode)
{
unsigned char tpm_pe[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f
};
return talk(tpm_pe, sizeof(tpm_pe), tpm_errcode);
}
static int TPM_PhysicalSetDeactivated(unsigned char parm, int *tpm_errcode)
{
unsigned char tpm_psd[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72,
0x00
};
tpm_psd[10] = parm;
return talk(tpm_psd, sizeof(tpm_psd), tpm_errcode);
}
static int TPM_ContinueSelfTest(int *tpm_errcode)
{
unsigned char tpm_cst[] = {
0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x53
};
return talk(tpm_cst, sizeof(tpm_cst), tpm_errcode);
}
static void print_usage(const char *prgname)
{
printf(
"\n"
"%s [options]\n"
"\n"
"Runs TPM_Startup (unless -n), then (unless -o) sets PP, enable, activate \n"
"\n"
"The following options are supported:\n"
"\t-c startup clear (default)\n"
"\t-s startup state\n"
"\t-d startup deactivate\n"
"\t-n no startup\n"
"\t-o startup only\n"
"\t-cs run TPM_ContinueSelfTest\n",
prgname);
return;
}
int main(int argc, char *argv[])
{
int ret = 0;
int i; /* argc iterator */
int do_more = 1;
int contselftest = 0;
unsigned char startupparm = 0x1; /* parameter for TPM_Startup(); */
int tpm_errcode = 0;
/* command line argument defaults */
for (i=1 ; (i<argc) && (ret == 0) ; i++) {
if (strcmp(argv[i],"-c") == 0) {
startupparm = 0x01;
do_more = 1;
} else if (strcmp(argv[i],"-d") == 0) {
do_more = 0;
startupparm = 0x03;
} else if (strcmp(argv[i],"-h") == 0) {
print_usage(argv[0]);
exit(EXIT_SUCCESS);
} else if (strcmp(argv[i],"-n") == 0) {
startupparm = 0xff;
do_more = 1;
} else if (strcmp(argv[i],"-s") == 0) {
startupparm = 0x2;
do_more = 1;
} else if (strcmp(argv[i],"-o") == 0) {
do_more = 0;
} else if (strcmp(argv[i],"-cs") == 0) {
contselftest = 1;
} else {
printf("\n%s is not a valid option\n", argv[i]);
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
}
if (ret == 0) {
if (0xff != startupparm) {
ret = TPM_Startup(startupparm, &tpm_errcode);
if (tpm_errcode != 0) {
printf("TPM_Startup returned error code "
"0x%08x\n", ret);
}
}
}
/* Sends the TSC_PhysicalPresence command to turn on physicalPresenceCMDEnable */
if ((ret == 0) && do_more) {
TSC_PhysicalPresence(0x20, &tpm_errcode);
}
/* Sends the TSC_PhysicalPresence command to turn on physicalPresence */
if ((ret == 0) && do_more) {
ret = TSC_PhysicalPresence(0x08, &tpm_errcode);
if (tpm_errcode != 0) {
printf("TSC_PhysicalPresence returned error code "
"0x%08x\n", tpm_errcode);
}
}
/* Sends the TPM_Process_PhysicalEnable command to clear disabled */
if ((ret == 0) && do_more) {
ret = TPM_PhysicalEnable(&tpm_errcode);
if (tpm_errcode != 0) {
printf("TPM_PhysicalEnable returned error "
"code 0x%08x\n", tpm_errcode);
}
}
/* Sends the TPM_Process_PhysicalSetDeactivated command to clear deactivated */
if ((ret == 0) && do_more) {
ret = TPM_PhysicalSetDeactivated(0, &tpm_errcode);
if (tpm_errcode != 0) {
printf("TPM_PhysicalSetDeactivated returned error "
"code 0x%08x\n", tpm_errcode);
}
}
if ((ret == 0) && contselftest) {
ret = TPM_ContinueSelfTest(&tpm_errcode);
if (tpm_errcode != 0) {
printf("TPM_ContinueSelfTest returned error "
"code 0x%08x\n", tpm_errcode);
}
}
return ret;
}

View File

@ -0,0 +1,27 @@
#
# src/swtpm_cert/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
noinst_HEADERS =
bin_PROGRAMS =
if WITH_GNUTLS
bin_PROGRAMS += \
swtpm_cert
endif
swtpm_cert_SOURCES = \
ek-cert.c
ek-cert.o : tpm_asn1.h
swtpm_cert_LDADD = -ltasn1
tpm_asn1.h : tpm.asn
asn1Parser -o $@ $^
EXTRA_DIST = \
tpm.asn

912
src/swtpm_cert/ek-cert.c Normal file
View File

@ -0,0 +1,912 @@
/*
* ek-cert.c
*
* Authors: Stefan Berger <stefanb@us.ibm.com>
*
* (c) Copyright IBM Corporation 2014.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the names of the IBM Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Note: The construction of the certificate follows the TCG Credential
* Profile for TPM Family 1.2; Level 2 Unified Trust Certificate
* in section 3.5
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <limits.h>
#include <arpa/inet.h>
#include <gnutls/abstract.h>
#include <gnutls/gnutls.h>
#include "tpm_asn1.h"
enum cert_type_t {
CERT_TYPE_EK = 1,
CERT_TYPE_PLATFORM,
CERT_TYPE_AIK,
};
extern const ASN1_ARRAY_TYPE tpm_asn1_tab[];
ASN1_TYPE _tpm_asn;
static void
usage(const char *prg)
{
fprintf(stdout,
"Usage: %s [options]\n"
"\n"
"Create TPM certificates without requiring the EK private key.\n"
"\n"
"The following options are supported:\n"
"--pubkey <filename> : PEM file for public key (EK)\n"
"--signkey <filename> : PEM file for CA signing key\n"
"--signkey-password <pass> : Password for the CA signing key\n"
"--issuercert <filename> : PEM file with CA cert\n"
"--out-cert <filename> : Filename for certificate\n"
"--modulus <hex string> : The modulus of the public key\n"
"--exponent <exponent> : The exponent of the public key\n"
"--serial <serial number> : The certificate serial number\n"
"--days <number> : Number of days the cert is valid\n"
"--pem : Write certificate in PEM format; default is DER\n"
"--type <platform|ek> : The type of certificate to create; default is ek\n"
"--tpm-manufacturer <name> : The name of the TPM manufacturer\n"
"--tpm-model <model> : The TPM model (part number)\n"
"--tpm-version <version> : The TPM version (firmware version)\n"
"--platform-manufacturer <name> : The name of the Platform manufacturer\n"
"--platfrom-model <model> : The Platform model (part number)\n"
"--platform-version <version> : The Platform version (firmware version)\n"
"--subject <subject> : Subject such as location in format\n"
" C=US,ST=NY,L=NewYork\n"
"--help : Display this help screen and exit\n"
"\n"
,prg);
}
static char
hex_to_str(char digit) {
char value = -1;
if (digit >= '0' && digit <= '9') {
value = digit - '0';
} else if (digit >= 'a' && digit <= 'f') {
value = digit - 'a' + 10;
} else if (digit >= 'A' && digit <= 'F') {
value = digit - 'A' + 10;
}
return value;
}
static unsigned char *
hex_str_to_bin(const char *hexstr, int *modulus_len)
{
int len;
unsigned char *result;
int i = 0, j = 0;
unsigned char val1, val2;
len = strlen(hexstr);
if ((len & 1) != 0) {
fprintf(stderr, "Got an odd number of hex digits (%d).\n", len);
return NULL;
}
result = malloc(len / 2);
i = 0;
j = 0;
while (i < len) {
val1 = hex_to_str(hexstr[i]);
if (val1 < 0) {
fprintf(stderr, "Illegal hex character '%c'.", hexstr[i]);
free(result);
return NULL;
}
i++;
val2 = hex_to_str(hexstr[i]);
if (val2 < 0) {
fprintf(stderr, "Illegal hex character '%c'.", hexstr[i]);
free(result);
return NULL;
}
i++;
result[j++] = (val1 << 4) | val2;
}
*modulus_len = j;
return result;
}
static gnutls_pubkey_t
create_rsa_from_modulus(unsigned char *modulus, unsigned int modulus_len,
uint32_t exponent)
{
unsigned char exp_array[4];
uint32_t exponent_no = htonl(exponent);
gnutls_pubkey_t rsa = NULL;
gnutls_datum_t mod;
gnutls_datum_t exp = {
.data = exp_array,
.size = sizeof(exp_array),
};
int err;
memcpy(exp_array, &exponent_no, sizeof(exp_array));
err = gnutls_pubkey_init(&rsa);
if (err < 0) {
fprintf(stderr, "Could not initialized public key structure : %s\n",
gnutls_strerror(err));
return NULL;
}
mod.data = modulus;
mod.size = modulus_len;
err = gnutls_pubkey_import_rsa_raw(rsa, &mod, &exp);
if (err < 0) {
fprintf(stderr, "Could not set modulus and exponent on RSA key : %s\n",
gnutls_strerror(err));
gnutls_pubkey_deinit(rsa);
rsa = NULL;
}
return rsa;
}
static int
asn_init()
{
static bool inited;
int err;
if (inited)
return ASN1_SUCCESS;
err = asn1_array2tree(tpm_asn1_tab, &_tpm_asn, NULL);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "array2tree error: %d", err);
goto cleanup;
}
inited = true;
cleanup:
return err;
}
static int
create_tpm_manufacturer_info(const char *manufacturer,
const char *tpm_model,
const char *tpm_version,
gnutls_datum_t *asn1)
{
ASN1_TYPE at = ASN1_TYPE_EMPTY;
int err;
err = asn_init();
if (err != ASN1_SUCCESS) {
goto cleanup;
}
err = asn1_create_element(_tpm_asn, "TPM.TPMManufacturerInfo", &at);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "asn1_create_element error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "tpmManufacturer.id", "2.23.133.2.1", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "1. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "tpmManufacturer.manufacturer",
manufacturer, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "2. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "tpmModel.id", "2.23.133.2.2", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "3. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "tpmModel.model", manufacturer, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "4. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "tpmVersion.id", "2.23.133.2.3", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "5. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "tpmVersion.version", manufacturer, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "6. asn1_write_value error: %d\n", err);
goto cleanup;
}
/* determine needed size of byte array */
asn1->size = 0;
err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL);
if (err != ASN1_MEM_ERROR) {
fprintf(stderr, "1. asn1_der_coding error: %d\n", err);
goto cleanup;
}
//fprintf(stderr, "size=%d\n", asn1->size);
asn1->data = gnutls_malloc(asn1->size + 16);
err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "2. asn1_der_coding error: %d\n", err);
gnutls_free(asn1->data);
asn1->data = NULL;
goto cleanup;
}
#if 0
fprintf(stderr, "size=%d\n", asn1->size);
unsigned int i = 0;
for (i = 0; i < asn1->size; i++) {
fprintf(stderr, "%02x ", asn1->data[i]);
}
fprintf(stderr, "\n");
#endif
cleanup:
asn1_delete_structure(&at);
return err;
}
static int
create_platf_manufacturer_info(const char *manufacturer,
const char *platf_model,
const char *platf_version,
gnutls_datum_t *asn1)
{
ASN1_TYPE at = ASN1_TYPE_EMPTY;
int err;
err = asn_init();
if (err != ASN1_SUCCESS) {
goto cleanup;
}
err = asn1_create_element(_tpm_asn, "TPM.PlatformManufacturerInfo", &at);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "asn1_create_element error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "platformManufacturer.id", "2.23.133.2.4", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b1. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "platformManufacturer.manufacturer",
manufacturer, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b2. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "platformModel.id", "2.23.133.2.5", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b3. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "platformModel.model", manufacturer, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b4. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "platformVersion.id", "2.23.133.2.6", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b5. asn1_write_value error: %d\n", err);
goto cleanup;
}
err = asn1_write_value(at, "platformVersion.version", manufacturer, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b6. asn1_write_value error: %d\n", err);
goto cleanup;
}
/* determine needed size of byte array */
asn1->size = 0;
err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL);
if (err != ASN1_MEM_ERROR) {
fprintf(stderr, "b1. asn1_der_coding error: %d\n", err);
goto cleanup;
}
//fprintf(stderr, "size=%d\n", asn1->size);
asn1->data = gnutls_malloc(asn1->size + 16);
err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "b2. asn1_der_coding error: %d\n", err);
gnutls_free(asn1->data);
asn1->data = NULL;
goto cleanup;
}
#if 0
fprintf(stderr, "size=%d\n", asn1->size);
unsigned int i = 0;
for (i = 0; i < asn1->size; i++) {
fprintf(stderr, "%02x ", asn1->data[i]);
}
fprintf(stderr, "\n");
#endif
cleanup:
asn1_delete_structure(&at);
return err;
}
int
main(int argc, char *argv[])
{
int ret = 1;
int i;
gnutls_pubkey_t pubkey = NULL;
gnutls_x509_privkey_t sigkey = NULL;
gnutls_x509_crt_t sigcert = NULL;
gnutls_x509_crt_t crt = NULL;
const char *pubkey_filename = NULL;
const char *sigkey_filename = NULL;
const char *cert_filename = NULL;
const char *modulus_str = NULL;
const char *issuercert_filename = NULL;
unsigned char *modulus_bin = NULL;
int modulus_len = 0;
gnutls_datum_t datum = { NULL, 0}, out = { NULL, 0};
int serial = 1;
time_t now;
int err;
FILE *cert_file;
char *subject = NULL;
const char *error = NULL;
int days = 365;
char *sigkeypass = NULL;
uint32_t ser_number;
long int exponent = 0x10001;
bool write_pem = false;
uint8_t id[512];
size_t id_size = sizeof(id);
enum cert_type_t certtype = CERT_TYPE_EK;
const char *oid;
unsigned int key_usage;
char *tpm_manufacturer = NULL;
char *tpm_version = NULL;
char *tpm_model = NULL;
char *platf_manufacturer = NULL;
char *platf_version = NULL;
char *platf_model = NULL;
i = 1;
while (i < argc) {
if (!strcmp(argv[i], "--pubkey")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --pubkey.\n");
goto cleanup;
}
pubkey_filename = argv[i];
} else if (!strcmp(argv[i], "--modulus")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --modulus.\n");
goto cleanup;
}
modulus_str = argv[i];
if (!(modulus_bin = hex_str_to_bin(modulus_str, &modulus_len))) {
goto cleanup;
}
} else if (!strcmp(argv[i], "--exponent")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --exponent.\n");
goto cleanup;
}
exponent = strtol(argv[i], NULL, 0);
if (exponent == 0) {
fprintf(stderr, "Exponent is wrong and cannot be 0.\n");
goto cleanup;
}
if (exponent > UINT_MAX) {
fprintf(stderr, "Exponent must fit into 32bits.\n");
goto cleanup;
}
} else if (!strcmp(argv[i], "--signkey")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --signkey.\n");
goto cleanup;
}
sigkey_filename = argv[i];
} else if (!strcmp(argv[i], "--signkey-password")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --signkey-password.\n");
goto cleanup;
}
sigkeypass = argv[i];
} else if (!strcmp(argv[i], "--issuercert")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --issuercert.\n");
goto cleanup;
}
issuercert_filename = argv[i];
} else if (!strcmp(argv[i], "--out-cert")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --out-cert.\n");
goto cleanup;
}
cert_filename = argv[i];
} else if (!strcmp(argv[i], "--subject")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --subject.\n");
goto cleanup;
}
subject = argv[i];
} else if (!strcmp(argv[i], "--days")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --days.\n");
goto cleanup;
}
days = atoi(argv[i]);
} else if (!strcmp(argv[i], "--serial")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --serial.\n");
goto cleanup;
}
serial = atoi(argv[i]);
} else if (!strcmp(argv[i], "--type")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --type.\n");
goto cleanup;
}
if (!strcasecmp(argv[i], "ek")) {
certtype = CERT_TYPE_EK;
} else if (!strcasecmp(argv[i], "platform")) {
certtype = CERT_TYPE_PLATFORM;
// } else if (!strcasecmp(argv[i], "aik")) {
// /* AIK cert needs EK cert as input */
// certtype = CERT_TYPE_AIK;
} else {
fprintf(stderr, "Unknown certificate type '%s'.\n",
argv[i]);
goto cleanup;
}
} else if (!strcmp(argv[i], "--tpm-manufacturer")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --tpm-manufacturer.\n");
goto cleanup;
}
tpm_manufacturer = argv[i];
} else if (!strcmp(argv[i], "--tpm-model")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --tpm-model.\n");
goto cleanup;
}
tpm_model = argv[i];
} else if (!strcmp(argv[i], "--tpm-version")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --tpm-version.\n");
goto cleanup;
}
tpm_version = argv[i];
} else if (!strcmp(argv[i], "--platform-manufacturer")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --platform-manufacturer.\n");
goto cleanup;
}
platf_manufacturer = argv[i];
} else if (!strcmp(argv[i], "--platform-model")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --platform-model.\n");
goto cleanup;
}
platf_model = argv[i];
} else if (!strcmp(argv[i], "--platform-version")) {
i++;
if (i == argc) {
fprintf(stderr, "Missing argument for --platform-version.\n");
goto cleanup;
}
platf_version = argv[i];
} else if (!strcmp(argv[i], "--pem")) {
write_pem = true;
} else if (!strcmp(argv[i], "--help")) {
usage(argv[0]);
exit(0);
} else {
fprintf(stderr, "Unknown command line parameter '%s'.\n", argv[i]);
usage(argv[0]);
exit(1);
}
i++;
}
ser_number = htonl(serial);
if (pubkey_filename == NULL && modulus_bin == NULL) {
fprintf(stderr, "Missing public EK file and modulus.\n");
usage(argv[0]);
goto cleanup;
}
if (issuercert_filename == NULL) {
fprintf(stderr, "The issuer certificate name is required.\n");
goto cleanup;
}
switch (certtype) {
case CERT_TYPE_EK:
case CERT_TYPE_PLATFORM:
if (tpm_manufacturer == NULL ||
tpm_model == NULL ||
tpm_version == NULL) {
fprintf(stderr, "--tpm-manufacturer and --tpm-model and "
"--tpm version "
"must all be provided\n");
goto cleanup;
}
break;
case CERT_TYPE_AIK:
break;
}
switch (certtype) {
case CERT_TYPE_PLATFORM:
if (platf_manufacturer == NULL ||
platf_model == NULL ||
platf_version == NULL) {
fprintf(stderr, "--platform-manufacturer and --platform-model and "
"--platform version "
"must all be provided\n");
goto cleanup;
}
break;
case CERT_TYPE_EK:
case CERT_TYPE_AIK:
break;
}
err = gnutls_global_init();
if (err < 0) {
fprintf(stderr, "gnutls_global_init failed.\n");
goto cleanup;
}
gnutls_x509_privkey_init(&sigkey);
if (pubkey_filename) {
gnutls_pubkey_init(&pubkey);
err = gnutls_load_file(pubkey_filename, &datum);
if (err != GNUTLS_E_SUCCESS) {
fprintf(stderr, "Could not open file for EK public key: %s\n",
strerror(errno));
goto cleanup;
}
err = gnutls_pubkey_import(pubkey, &datum, GNUTLS_X509_FMT_PEM);
gnutls_free(datum.data);
datum.data = NULL;
if (err != GNUTLS_E_SUCCESS) {
fprintf(stderr, "Could not import EK.\n");
goto cleanup;
}
} else {
pubkey = create_rsa_from_modulus(modulus_bin, modulus_len,
exponent);
free(modulus_bin);
modulus_bin = NULL;
if (pubkey == NULL)
goto cleanup;
}
/* all types of keys must have pubkey set now otherwise the signing
will not work */
if (sigkey_filename == NULL) {
fprintf(stderr, "Missing signature key.\n");
usage(argv[0]);
exit(1);
}
#define CHECK_GNUTLS_ERROR(_err, _msg, ...) \
if (_err != GNUTLS_E_SUCCESS) { \
fprintf(stderr, _msg, __VA_ARGS__); \
goto cleanup; \
}
err = gnutls_load_file(sigkey_filename, &datum);
CHECK_GNUTLS_ERROR(err, "Could not read signing key from file %s: %s\n",
sigkey_filename, gnutls_strerror(err));
if (sigkeypass) {
err = gnutls_x509_privkey_import2(sigkey, &datum, GNUTLS_X509_FMT_PEM,
sigkeypass, 0);
} else {
err = gnutls_x509_privkey_import(sigkey, &datum, GNUTLS_X509_FMT_PEM);
}
gnutls_free(datum.data);
datum.data = NULL;
CHECK_GNUTLS_ERROR(err, "Could not import signing key : %s\n",
gnutls_strerror(err));
err = gnutls_load_file(issuercert_filename, &datum);
CHECK_GNUTLS_ERROR(err, "Could not read certificate from file %s : %s\n",
issuercert_filename, gnutls_strerror(err));
gnutls_x509_crt_init(&sigcert);
err = gnutls_x509_crt_import(sigcert, &datum, GNUTLS_X509_FMT_PEM);
gnutls_free(datum.data);
datum.data = NULL;
CHECK_GNUTLS_ERROR(err, "Could not import issuer certificate: %s\n",
gnutls_strerror(err));
err = gnutls_x509_crt_init(&crt);
CHECK_GNUTLS_ERROR(err, "CRT init failed: %s\n", gnutls_strerror(err))
/* 3.5.1 Version */
err = gnutls_x509_crt_set_version(crt, 3);
CHECK_GNUTLS_ERROR(err, "Could not set version on CRT: %s\n",
gnutls_strerror(err))
/* 3.5.2 Serial Number */
err = gnutls_x509_crt_set_serial(crt, &ser_number, sizeof(ser_number));
CHECK_GNUTLS_ERROR(err, "Could not set serial on CRT: %s\n",
gnutls_strerror(err))
/* 3.5.5 Validity */
now = time(NULL);
err = gnutls_x509_crt_set_activation_time(crt, now);
CHECK_GNUTLS_ERROR(err, "Could not set activation time on CRT: %s\n",
gnutls_strerror(err))
err = gnutls_x509_crt_set_expiration_time(crt,
now + (time_t)days * 24 * 60 * 60);
CHECK_GNUTLS_ERROR(err, "Could not set expiration time on CRT: %s\n",
gnutls_strerror(err))
/* 3.5.6 Subject -- should be empty, but we allow it anyway */
if (subject) {
err = gnutls_x509_crt_set_dn(crt, subject, &error);
CHECK_GNUTLS_ERROR(err,
"Could not set DN on CRT: %s\n"
"DN '%s must be fault after %s\n.'",
gnutls_strerror(err),
subject, error)
}
/* 3.5.7 Public Key Info */
switch (certtype) {
case CERT_TYPE_EK:
oid = "1.2.840.113549.1.1.7";
break;
case CERT_TYPE_PLATFORM:
oid = NULL;
break;
case CERT_TYPE_AIK:
oid = "1.2.840.113549.1.1.1";
break;
default:
fprintf(stderr, "Internal error: unhandle case in line %d\n",
__LINE__);
goto cleanup;
}
if (oid) {
err = gnutls_x509_crt_set_key_purpose_oid(crt, oid, 0);
CHECK_GNUTLS_ERROR(err, "Could not set key purpose on CRT: %s\n",
gnutls_strerror(err))
}
/* 3.5.8 Certificate Policies -- skip since not mandated */
/* 3.5.9 Subject Alternative Names -- missing code */
err = create_tpm_manufacturer_info(tpm_manufacturer, tpm_model,
tpm_version, &datum);
if (!err && datum.size > 0) {
/*
* GNUTLS's write_new_general_name can only handle a few GNUTLS_SAN_*
* -> we have to use GNUTLS_SAN_URI
*/
err = gnutls_x509_crt_set_subject_alt_name(crt,
GNUTLS_SAN_URI,
datum.data, datum.size,
GNUTLS_FSAN_SET);
CHECK_GNUTLS_ERROR(err, "Could not set subject alt name: %s\n",
gnutls_strerror(err))
}
gnutls_free(datum.data);
datum.data = NULL;
datum.size = 0;
switch (certtype) {
case CERT_TYPE_PLATFORM:
err = create_platf_manufacturer_info(platf_manufacturer, platf_model,
platf_version, &datum);
break;
case CERT_TYPE_AIK:
case CERT_TYPE_EK:
break;
default:
fprintf(stderr, "Internal error: unhandle case in line %d\n",
__LINE__);
goto cleanup;
}
if (!err && datum.size > 0) {
/*
* GNUTLS's write_new_general_name can only handle a few GNUTLS_SAN_*
* -> we have to use GNUTLS_SAN_URI
*/
err = gnutls_x509_crt_set_subject_alt_name(crt,
GNUTLS_SAN_URI,
datum.data, datum.size,
GNUTLS_FSAN_APPEND);
CHECK_GNUTLS_ERROR(err, "Could not append to subject alt name: %s\n",
gnutls_strerror(err))
}
gnutls_free(datum.data);
datum.data = NULL;
/* 3.5.10 Basic Constraints */
err = gnutls_x509_crt_set_basic_constraints(crt, 0, -1);
CHECK_GNUTLS_ERROR(err, "Could not set key usage id: %s\n",
gnutls_strerror(err))
/* 3.5.11 Subject Directory Attributes -- missing */
/* 3.5.12 Authority Key Id */
err = gnutls_x509_crt_get_key_id(sigcert, 0, id, &id_size);
if (err == GNUTLS_E_SUCCESS && id_size > 0) {
err = gnutls_x509_crt_set_authority_key_id(crt, id, id_size);
CHECK_GNUTLS_ERROR(err, "Could not set the authority key id: %s\n",
gnutls_strerror(err))
}
/* 3.5.13 Authority Info Access -- may be omitted */
/* 3.5.14 CRL Distribution -- missing */
/* 3.5.15 Key Usage */
switch (certtype) {
case CERT_TYPE_EK:
case CERT_TYPE_PLATFORM:
key_usage = GNUTLS_KEY_KEY_ENCIPHERMENT;
break;
case CERT_TYPE_AIK:
key_usage = GNUTLS_KEY_DIGITAL_SIGNATURE;
break;
default:
fprintf(stderr, "Internal error: unhandle case in line %d\n",
__LINE__);
goto cleanup;
}
err = gnutls_x509_crt_set_key_usage(crt, key_usage);
CHECK_GNUTLS_ERROR(err, "Could not set key usage id: %s\n",
gnutls_strerror(err))
/* 3.5.16 Extended Key Usage -- missing */
/* 3.5.17 Subject Key Id -- should not be included */
/* 3.5.18 Issuer Alt. Name -- should not be included */
/* 3.5.19 FreshestCRL -- should not be included */
/* 3.5.20 Subject Info. Access -- should not be included */
/* 3.5.21 Subject and Issued Unique Ids -- must be omitted */
/* 3.5.22 Virtualized Platform Attestation Service -- missing */
/* 3.5.23 Migration Controller Attestation Service -- missing */
/* 3.5.24 Migration Controller Registration Service -- missing */
/* 3.5.25 Virtual Platform Backup Service -- missing */
/* set public key */
err = gnutls_x509_crt_set_pubkey(crt, pubkey);
CHECK_GNUTLS_ERROR(err, "Could not set public EK on CRT: %s\n",
gnutls_strerror(err))
/* sign cert */
err = gnutls_x509_crt_sign(crt, sigcert, sigkey);
CHECK_GNUTLS_ERROR(err, "Could not sign the CRT: %s\n",
gnutls_strerror(err))
/* write cert to file; either PEM or DER */
gnutls_x509_crt_export2(crt,
(write_pem)
? GNUTLS_X509_FMT_PEM
: GNUTLS_X509_FMT_DER, &out);
if (cert_filename) {
cert_file = fopen(cert_filename, "wb");
if (cert_file == NULL) {
fprintf(stderr, "Could not open %s for writing the certificate: %s\n",
cert_filename,
strerror(errno));
goto cleanup;
}
if (out.size != fwrite(out.data, 1, out.size, cert_file)) {
fprintf(stderr, "Could not write certificate into file: %s\n",
strerror(errno));
fclose(cert_file);
goto cleanup;
}
fclose(cert_file);
} else {
fprintf(stdout, "%s\n", out.data);
}
ret = 0;
cleanup:
gnutls_free(out.data);
gnutls_x509_crt_deinit(crt);
gnutls_x509_crt_deinit(sigcert);
gnutls_x509_privkey_deinit(sigkey);
gnutls_pubkey_deinit(pubkey);
gnutls_global_deinit();
return ret;
}

26
src/swtpm_cert/out Normal file
View File

@ -0,0 +1,26 @@
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <libtasn1.h>
const asn1_static_node tpm_asn1_tab[] = {
{ "TPM", 536875024, NULL },
{ NULL, 1073741836, NULL },
{ "tcg", 1879048204, NULL },
{ "joint-iso-itu-t", 1073741825, "2"},
{ "international-organizations", 1073741825, "23"},
{ "tcg", 1, "133"},
{ "tcg-attribute", 1879048204, NULL },
{ NULL, 1073741825, "tcg"},
{ NULL, 1, "2"},
{ "tcg-at-tpmManufacturer", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "1"},
{ "TPMManufacturerInfo", 1610612741, NULL },
{ "tpmManufacturer", 2, "TPMManufacturer"},
{ "TPMManufacturer", 536870917, NULL },
{ "tcg-at-tpmManufacturer", 1073741836, NULL },
{ "name", 34, NULL },
{ NULL, 0, NULL }
};

62
src/swtpm_cert/tpm.asn Normal file
View File

@ -0,0 +1,62 @@
TPM { }
DEFINITIONS IMPLICIT TAGS ::=
BEGIN
tcg OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) international-organizations(23) tcg(133)
}
tcg-attribute OBJECT IDENTIFIER ::= {tcg 2}
tcg-at-tpmManufacturer OBJECT IDENTIFIER ::= {tcg-attribute 1}
tcg-at-tpmModel OBJECT IDENTIFIER ::= {tcg-attribute 2}
tcg-at-tpmVersion OBJECT IDENTIFIER ::= {tcg-attribute 3}
tcg-at-platformManufacturer OBJECT IDENTIFIER ::= {tcg-attribute 4}
tcg-at-platformModel OBJECT IDENTIFIER ::= {tcg-attribute 5}
tcg-at-platformVersion OBJECT IDENTIFIER ::= {tcg-attribute 6}
TPMManufacturerInfo ::= SEQUENCE {
tpmManufacturer TPMManufacturer,
tpmModel TPMModel,
tpmVersion TPMVersion
}
TPMManufacturer ::= SEQUENCE {
id OBJECT IDENTIFIER,
manufacturer UTF8String
}
TPMModel ::= SEQUENCE {
id OBJECT IDENTIFIER,
model UTF8String
}
TPMVersion ::= SEQUENCE {
id OBJECT IDENTIFIER,
version UTF8String
}
PlatformManufacturerInfo ::= SEQUENCE {
platformManufacturer PlatformManufacturer,
platformModel PlatformModel,
platformVersion PlatformVersion
}
PlatformManufacturer ::= SEQUENCE {
id OBJECT IDENTIFIER,
manufacturer UTF8String
}
PlatformModel ::= SEQUENCE {
id OBJECT IDENTIFIER,
model UTF8String
}
PlatformVersion ::= SEQUENCE {
id OBJECT IDENTIFIER,
version UTF8String
}
END

62
src/swtpm_cert/tpm_asn1.h Normal file
View File

@ -0,0 +1,62 @@
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <libtasn1.h>
const asn1_static_node tpm_asn1_tab[] = {
{ "TPM", 536875024, NULL },
{ NULL, 1073741836, NULL },
{ "tcg", 1879048204, NULL },
{ "joint-iso-itu-t", 1073741825, "2"},
{ "international-organizations", 1073741825, "23"},
{ "tcg", 1, "133"},
{ "tcg-attribute", 1879048204, NULL },
{ NULL, 1073741825, "tcg"},
{ NULL, 1, "2"},
{ "tcg-at-tpmManufacturer", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "1"},
{ "tcg-at-tpmModel", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "2"},
{ "tcg-at-tpmVersion", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "3"},
{ "tcg-at-platformManufacturer", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "4"},
{ "tcg-at-platformModel", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "5"},
{ "tcg-at-platformVersion", 1879048204, NULL },
{ NULL, 1073741825, "tcg-attribute"},
{ NULL, 1, "6"},
{ "TPMManufacturerInfo", 1610612741, NULL },
{ "tpmManufacturer", 1073741826, "TPMManufacturer"},
{ "tpmModel", 1073741826, "TPMModel"},
{ "tpmVersion", 2, "TPMVersion"},
{ "TPMManufacturer", 1610612741, NULL },
{ "id", 1073741836, NULL },
{ "manufacturer", 34, NULL },
{ "TPMModel", 1610612741, NULL },
{ "id", 1073741836, NULL },
{ "model", 34, NULL },
{ "TPMVersion", 1610612741, NULL },
{ "id", 1073741836, NULL },
{ "version", 34, NULL },
{ "PlatformManufacturerInfo", 1610612741, NULL },
{ "platformManufacturer", 1073741826, "PlatformManufacturer"},
{ "platformModel", 1073741826, "PlatformModel"},
{ "platformVersion", 2, "PlatformVersion"},
{ "PlatformManufacturer", 1610612741, NULL },
{ "id", 1073741836, NULL },
{ "manufacturer", 34, NULL },
{ "PlatformModel", 1610612741, NULL },
{ "id", 1073741836, NULL },
{ "model", 34, NULL },
{ "PlatformVersion", 536870917, NULL },
{ "id", 1073741836, NULL },
{ "version", 34, NULL },
{ NULL, 0, NULL }
};

View File

@ -0,0 +1,15 @@
#
# src/cuse_tpm_ioctl/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
noinst_HEADERS =
bin_PROGRAMS = \
swtpm_ioctl
swtpm_ioctl_SOURCES = tpm_ioctl.c
swtpm_ioctl_CFLAGS = \
-I$(top_srcdir)/include

316
src/swtpm_ioctl/tpm_ioctl.c Normal file
View File

@ -0,0 +1,316 @@
/*
* tpm_ioctl -- ioctl utility for the CUSE TPM
*
* Authors: David Safford <safford@us.ibm.com>
* Stefan Berger <stefanb@us.ibm.com>
*
* (c) Copyright IBM Corporation 2014.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the names of the IBM Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* tool for using 'swtpm cuse' ioctls
*
* cuse_tpm_ioctl [ -c | -i | -s | -e | -l num ] devicepath
* -c get ptm capabilities
* -i do a hardware TPM_Init
* -s shutdown tpm_server_cuse
* -e get tpmEstablished bit
* -l set locality to num
* -h hash the given data
* -v store volatile data to file
* -C cancel an ongoing TPM command
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <swtpm/tpm_ioctl.h>
static void usage(const char *prgname)
{
fprintf(stdout,
"Usage: %s command <device path>\n"
"\n"
"The following commands are supported:\n"
"-c : get ptm capabilities\n"
"-i : do a hardware TPM_Init; if volatile state is found, it will\n"
" resume the TPM with it and delete it afterwards\n"
"-s : shutdown the CUSE tpm\n"
"-e : get the tpmEstablished bit\n"
"-v : store the TPM's volatile data\n"
"-C : cancel an ongoing TPM command\n"
"-l <num> : set the locality to the given number; valid numbers are 0-4\n"
"-h <data>: hash the given data; if data is '-' then data are read from\n"
" stdin\n\n"
,prgname);
}
int main(int argc, char *argv[])
{
int fd;
int devindex, n;
ptmest_t est;
ptmloc_t loc;
ptmcap_t cap;
ptmhdata_t hdata;
ptmres_t res;
ptminit_t init;
size_t idx;
if (argc < 2) {
fprintf(stderr, "Error: Missing command.\n\n");
usage(argv[0]);
return 1;
}
switch (argv[1][1]) {
case 'l':
case 'h':
devindex = 3;
break;
default:
devindex = 2;
break;
}
if (devindex >= argc) {
fprintf(stderr, "Error: Not enough parameters.\n\n");
usage(argv[0]);
return 1;
}
fd = open(argv[devindex], O_RDWR);
if (fd < 0) {
fprintf(stderr,
"Could not open CUSE TPM device %s: %s\n",
argv[devindex], strerror(errno));
return -1;
}
switch (argv[1][1]) {
case 'c':
n = ioctl(fd, PTM_GET_CAPABILITY, &cap);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_GET_CAPABILITY: "
"%s\n", strerror(errno));
return 1;
}
/* no tpm_result here */
printf("ptm capability is 0x%lx\n",cap);
break;
case 'i':
init.u.req.init_flags = INIT_FLAG_DELETE_VOLATILE;
n = ioctl(fd, PTM_INIT, &init);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_INIT: "
"%s\n", strerror(errno));
return 1;
}
res = init.u.resp.tpm_result;
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_INIT: 0x%x\n", res);
return 1;
}
break;
case 'e':
n = ioctl(fd, PTM_GET_TPMESTABLISHED, &est);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_GET_ESTABLISHED: "
"%s\n", strerror(errno));
return 1;
}
res = est.tpm_result;
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_GET_TPMESTABLISHED: 0x%x\n", res);
return 1;
}
printf("tpmEstablished is %d\n",est.bit);
break;
case 's':
n = ioctl(fd, PTM_SHUTDOWN, &res);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_SHUTDOWN: "
"%s\n", strerror(errno));
return 1;
}
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_SHUTDOWN: 0x%x\n", res);
return 1;
}
break;
case 'l':
loc.u.req.loc = atoi(argv[2]);
if (loc.u.req.loc < 0 || loc.u.req.loc > 4) {
fprintf(stderr,
"Locality must be a number from 0 to 4.\n");
return 1;
}
n = ioctl(fd, PTM_SET_LOCALITY, &loc);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_SET_LOCALITY: "
"%s\n", strerror(errno));
return 1;
}
res = loc.u.resp.tpm_result;
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_SET_LOCALITY: 0x%x\n", res);
return 1;
}
break;
case 'h':
/* hash string given on command line */
n = ioctl(fd, PTM_HASH_START, &res);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_HASH_START: "
"%s\n", strerror(errno));
return 1;
}
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_HASH_START: 0x%x\n", res);
return 1;
}
if (strlen(argv[2]) == 1 && argv[2][0] == '-') {
/* read data from stdin */
while (1) {
idx = 0;
int c = 0;
while (idx < sizeof(hdata.u.req.data)) {
c = fgetc(stdin);
if (c == EOF)
break;
hdata.u.req.data[idx] = (char)c;
idx++;
}
hdata.u.req.length = idx;
n = ioctl(fd, PTM_HASH_DATA, &hdata);
res = hdata.u.resp.tpm_result;
if (n != 0 || res != 0 || c == EOF)
break;
}
} else {
idx = 0;
while (idx < strlen(argv[2])) {
size_t tocopy = strlen(argv[2]) - idx;
if (tocopy > sizeof(hdata.u.req.data))
tocopy = sizeof(hdata.u.req.data);
hdata.u.req.length = tocopy;
memcpy(hdata.u.req.data, &(argv[2])[idx],
tocopy);
idx += tocopy;
n = ioctl(fd, PTM_HASH_DATA, &hdata);
res = hdata.u.resp.tpm_result;
if (n != 0 || res != 0)
break;
}
}
if (n != 0) {
fprintf(stderr,
"Could not execute ioctl PTM_HASH_DATA: "
"%s\n", strerror(errno));
return 1;
}
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_HASH_DATA: 0x%x\n", res);
return 1;
}
n = ioctl(fd, PTM_HASH_END, &res);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_HASH_END: "
"%s\n", strerror(errno));
return 1;
}
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_HASH_END: 0x%x\n", res);
return 1;
}
break;
case 'C':
n = ioctl(fd, PTM_CANCEL_TPM_CMD, &res);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_CANCEL_TPM_CMD: "
"%s\n", strerror(errno));
return 1;
}
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_CANCEL_TPM_CMD: 0x%x\n",
res);
return 1;
}
break;
case 'v':
n = ioctl(fd, PTM_STORE_VOLATILE, &res);
if (n < 0) {
fprintf(stderr,
"Could not execute ioctl PTM_STORE_VOLATILE: "
"%s\n", strerror(errno));
return 1;
}
if (res != 0) {
fprintf(stderr,
"TPM result from PTM_STORE_VOLATILE: 0x%x\n",
res);
return 1;
}
break;
default:
usage(argv[0]);
return 1;
}
return 0;
}

View File

@ -0,0 +1,22 @@
#
# src/swtpm_setup/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
bin_PROGRAMS = \
swtpm_setup
# swtpm_tcsd_launcher
swtpm_setup_SOURCES = swtpm_setup.c
# swtpm_tcsd_launcher_SOURCES = tcsd-launcher.c
dist_bin_SCRIPTS = swtpm_setup.sh
install-exec-hook:
chown tss:tss $(DESTDIR)/$(bindir)/swtpm_setup.sh
chmod 750 $(DESTDIR)/$(bindir)/swtpm_setup.sh
#chmod 4755 $(DESTDIR)/$(bindir)/swtpm_tcsd_launcher

157
src/swtpm_setup/swtpm_setup.c Executable file
View File

@ -0,0 +1,157 @@
/*
* swtpm_setup.c
*
* Authors: Stefan Berger <stefanb@us.ibm.com>
*
* (c) Copyright IBM Corporation 2011,2014.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the names of the IBM Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <libgen.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#define E_USER_GROUP "tss"
/*
* Those parameters interpreted by swtpm_setup.sh that have an additional
* parameter.
*/
const char *one_arg_params[] = {
"--tpm-state",
"--tpm",
"--ownerpass",
"--srkpass",
"--config",
"--vmid",
"--logfile",
"--keyfile",
"--pwdfile",
NULL
};
int main(int argc, char *argv[])
{
const char *program = "swtpm_setup.sh";
char resolved_path[PATH_MAX];
char *dir;
char *path_program;
size_t length;
struct passwd *passwd;
int i = 1, j;
const char *userid = E_USER_GROUP;
while (i < argc) {
if (!strcmp("--runas", argv[i])) {
i++;
if (i == argc) {
fprintf(stderr, "Missing user argument for --runas");
exit(1);
}
userid = argv[i];
break;
}
for (j = 0; one_arg_params[j] != NULL; j++) {
if (!strcmp(one_arg_params[j], argv[i])) {
i++;
break;
}
}
i++;
}
if (!realpath("/proc/self/exe", resolved_path)) {
fprintf(stderr, "Could not resolve path to executable : %s\n",
strerror(errno));
return EXIT_FAILURE;
}
dir = dirname(resolved_path);
if (!dir) {
fprintf(stderr, "Could not get directory from path '%s'.",
resolved_path);
return EXIT_FAILURE;
}
length = strlen(dir) + 1 + strlen(program) + 2;
path_program = malloc(length);
if (!path_program) {
fprintf(stderr, "Out of memory.\n");
return EXIT_FAILURE;
}
if (snprintf(path_program, length, "%s/%s", dir, program) >=
(int)length) {
fprintf(stderr, "Internal error writing string.\n");
return EXIT_FAILURE;
}
passwd = getpwnam(userid);
if (!passwd) {
fprintf(stderr, "Could not get account data of user %s.\n", userid);
return EXIT_FAILURE;
}
if (setgid(passwd->pw_gid)) {
fprintf(stderr,"Setting groupid to tss (%d) failed.\n",
passwd->pw_gid);
return EXIT_FAILURE;
}
if (initgroups(passwd->pw_name, passwd->pw_gid)) {
fprintf(stderr,"initgroups() failed: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if (setuid(passwd->pw_uid)) {
fprintf(stderr,"Setting userid to tss (%d) failed.\n",
passwd->pw_uid);
return EXIT_FAILURE;
}
execv(path_program, argv);
/* should never get here */
fprintf(stderr, "As user %s: Could not execute '%s' : %s\n",
passwd->pw_name,
path_program,
strerror(errno));
return EXIT_FAILURE;
}

746
src/swtpm_setup/swtpm_setup.sh Executable file
View File

@ -0,0 +1,746 @@
#!/bin/bash
#
# swtpm_setup.sh
#
# Authors: Stefan Berger <stefanb@us.ibm.com>
#
# (c) Copyright IBM Corporation 2011,2014.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# Neither the names of the IBM Corporation nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# echo "UID=$UID EUID=$EUID"
# Dependencies:
#
# - tpm_tools (tpm-tools package with NVRAM utilities)
# - tcsd (trousers package with tcsd with -c <configfile> option)
# - expect (expect package)
SWTPM=`type -P swtpm`
if [ -n "$SWTPM" ]; then
SWTPM="$SWTPM socket"
fi
TCSD=`type -P tcsd`
if [ -z "$TCSD" ]; then
echo "Error: tcsd program not found."
exit 1
fi
SETUP_CREATE_EK_F=1
SETUP_TAKEOWN_F=2
SETUP_EK_CERT_F=4
SETUP_PLATFORM_CERT_F=8
SETUP_LOCK_NVRAM_F=16
SETUP_SRKPASS_ZEROS_F=32
SETUP_OWNERPASS_ZEROS_F=64
SETUP_DISPLAY_RESULTS_F=4096
# default values for passwords
DEFAULT_OWNER_PASSWORD=ooo
DEFAULT_SRK_PASSWORD=sss
# default configuration file
DEFAULT_CONFIG_FILE="/etc/swtpm_setup.conf"
# TPM constants
TPM_NV_INDEX_D_BIT=$((0x10000000))
TPM_NV_INDEX_EKCert=$((0xF000))
TPM_NV_INDEX_PlatformCert=$((0xF002))
TPM_NV_INDEX_LOCK=$((0xFFFFFFFF))
# Default logging goes to stderr
LOGFILE=""
trap "cleanup" SIGTERM EXIT
logit()
{
if [ -z "$LOGFILE" ]; then
echo "$1" >&1
else
echo "$1" >> $LOGFILE
fi
}
logit_cmd()
{
if [ -z "$LOGFILE" ]; then
eval "$1" >&1
else
eval "$1" >> $LOGFILE
fi
}
logerr()
{
if [ -z "$LOGFILE" ]; then
echo "Error: $1" >&2
else
echo "Error: $1" >> $LOGFILE
fi
}
call_create_certs()
{
local ret=0
local flags="$1"
local configfile="$2"
local certdir="$3"
local ek="$4"
local vmid="$5"
local logparam
local params="" cmd
if [ -n "$LOGFILE" ]; then
logparam="--logfile $LOGFILE"
fi
if [ $((flags & SETUP_EK_CERT_F)) -ne 0 ] || \
[ $((flags & SETUP_PLATFORM_CERT_F)) -ne 0 ]; then
if [ -r "$configfile" ]; then
# The config file contains lines in the format:
# key = value
# or with a comment at the end started by #:
# key = value # comment
create_certs_tool="$(sed -n 's/\s*create_certs_tool\s*=\s*\([^#]*\).*/\1/p' \
"$configfile")"
create_certs_tool_config="$(sed -n 's/\s*create_certs_tool_config\s*=\s*\([^#]*\).*/\1/p' \
"$configfile")"
if [ -n "$create_certs_tool_config" ]; then
params="$params --configfile \"$create_certs_tool_config\""
fi
create_certs_tool_options="$(sed -n 's/\s*create_certs_tool_options\s*=\s*\([^#]*\).*/\1/p' \
"$configfile")"
if [ -n "$create_certs_tool_options" ]; then
params="$params --optsfile $create_certs_tool_optsfile"
fi
else
logerr "Could not access config file" \
"'$configfile' to get" \
"name of certificate tool to invoke."
return 1
fi
fi
if [ -n "$create_certs_tool" ]; then
if [ $((flags & SETUP_EK_CERT_F)) -ne 0 ]; then
cmd="$create_certs_tool \
--type ek \
--ek "$ek" \
--dir "$certdir" \
--vmid "$vmid" \
${logparam} ${params}"
logit " Invoking: $(echo $cmd | tr -s " ")"
eval $cmd
ret=$?
if [ $ret -ne 0 ]; then
return $ret
fi
fi
if [ $((flags & SETUP_PLATFORM_CERT_F)) -ne 0 ]; then
cmd="$create_certs_tool \
--type platform \
--ek "$ek" \
--dir "$certdir" \
--vmid "$vmid" \
${logparam} ${params}"
logit " Invoking: $(echo $cmd | tr -s " ")"
eval $cmd
ret=$?
if [ $ret -ne 0 ]; then
return $ret
fi
fi
fi
return $ret
}
start_tpm()
{
local swtpm="$1"
local swtpm_state="$2"
local ctr=0
export TPM_PORT
export TPM_PATH=$swtpm_state
while [ $ctr -lt 100 ]; do
TPM_PORT=$(shuf -i 30000-65535 -n 1)
# skip used ports
if [ -n "$(netstate -lnpt 2>/dev/null |
gawk '{print $4}' |
grep ":${TPM_PORT} ")" ]; then
let ctr=ctr+1
continue
fi
$swtpm 2>&1 1>/dev/null &
SWTPM_PID=$!
# poll for open port (good) or the process to have
# disappeared (bad); whatever happens first
while :; do
kill -0 $SWTPM_PID 2>/dev/null
if [ $? -ne 0 ]; then
# process dead; try next socket
break
fi
# Did swtpm open the TCP port yet?
if [ -n "$(netstat -napt 2>/dev/null |
grep " $SWTPM_PID/" |
grep ":$TPM_PORT ")" ]; then
echo "TPM is listening on TCP port $TPM_PORT."
return 0
fi
sleep 0.1
done
let ctr=$ctr+1
done
return 1
}
stop_tpm()
{
[ "$SWTPM_PID" != "" ] && kill -SIGTERM $SWTPM_PID
SWTPM_PID=
}
start_tcsd()
{
local TCSD=$1
local user=$(id -u -n)
local group=$(id -g -n)
local ctr=0
export TSS_TCSD_PORT
TCSD_CONFIG=`mktemp`
TCSD_DATA_DIR=`mktemp -d`
TCSD_DATA_FILE=`mktemp --tmpdir=$TCSD_DATA_DIR`
while [ $ctr -lt 100 ]; do
TSS_TCSD_PORT=$(shuf -i 30000-65535 -n 1)
# skip used ports
if [ -n "$(netstate -lnpt 2>/dev/null |
gawk '{print $4}' |
grep ":${TSS_TCSD_PORT} ")" ]; then
let ctr=$ctr+1
continue
fi
cat << EOF >$TCSD_CONFIG
port = $TSS_TCSD_PORT
system_ps_file = $TCSD_DATA_FILE
EOF
# tcsd requires tss:tss and 0600 on TCSD_CONFIG
# -> only root can start
chmod 600 $TCSD_CONFIG
#ls -l $TCSD_CONFIG
if [ $(id -u) -eq 0 ]; then
chown tss:tss $TCSD_CONFIG 2>/dev/null
chown tss:tss $TCSD_DATA_DIR 2>/dev/null
chown tss:tss $TCSD_DATA_FILE 2>/dev/null
fi
if [ $? -ne 0 ]; then
logerr "Could not change ownership on $TCSD_CONFIG to ${user}:${group}."
ls -l $TCSD_CONFIG
return 1
fi
case "$(id -u)" in
0)
$TCSD -c $TCSD_CONFIG -e -f 2>&1 1>/dev/null &
TCSD_PID=$!
;;
*)
# for tss user, use the wrapper
$TCSD -c $TCSD_CONFIG -e -f 2>&1 1>/dev/null &
#if [ $? -ne 0]; then
# swtpm_tcsd_launcher -c $TCSD_CONFIG -e -f 2>&1 1>/dev/null &
#fi
TCSD_PID=$!
;;
esac
# TSS still alive?
# poll for open port (good) or the process to have
# disappeared (bad); whatever happens first
while :; do
kill -0 $TCSD_PID 2>/dev/null
if [ $? -ne 0 ]; then
# process dead; try next socket
break
fi
# Did tcsd open the TCP port yet?
if [ -n "$(netstat -napt 2>/dev/null |
grep " $TCSD_PID/" |
grep ":$TSS_TCSD_PORT ")" ]; then
echo "TSS is listening on TCP port $TSS_TCSD_PORT."
return 0
fi
sleep 0.1
done
let ctr=$ctr+1
done
return 1
}
stop_tcsd()
{
[ "$TCSD_PID" != "" ] && kill -SIGTERM $TCSD_PID
TCSD_PID=
}
cleanup()
{
stop_tpm
stop_tcsd
rm -rf "$TCSD_CONFIG" "$TCSD_DATA_FILE" "$TCSD_DATA_DIR"
}
init_tpm()
{
local flags="$1"
local config_file="$2"
local tpm_state_path="$3"
local ownerpass="$4"
local srkpass="$5"
local vmid="$6"
# where external app writes certs into
local certsdir="$tpm_state_path"
local ek tmp
local PLATFORM_CERT_FILE="$certsdir/platform.cert"
local EK_CERT_FILE="$certsdir/ek.cert"
local nvramauth="OWNERREAD|OWNERWRITE"
start_tpm "$SWTPM" "$tpm_state_path"
if [ $? -ne 0 ]; then
logerr "Could not start TPM."
return 1
fi
export TCSD_USE_TCP_DEVICE=1
export TCSD_TCP_DEVICE_PORT=$TPM_PORT
PATH=$PATH:.
swtpm_bios
if [ $? -ne 0 ]; then
logerr "swtpm_bios failed"
return 1
fi
# TPM is enabled and activated upon first start
start_tcsd $TCSD
if [ $? -ne 0 ]; then
return 1
fi
if [ $((flags & $SETUP_CREATE_EK_F)) -ne 0 ]; then
tpm_createek 2>&1 1>/dev/null
if [ $? -ne 0 ]; then
logerr "tpm_createek failed"
return 1
fi
logit "Successfully created EK."
# Get the value of the EK
ek=$(tpm_getpubek |
sed '1,/Public Key:/d' |
tr -d " " |
tr -d '\t' |
tr -d '\n')
fi
# temporarily take ownership if an EK was created
if [ $((flags & $SETUP_CREATE_EK_F)) -ne 0 ] ; then
local parm_z=""
local parm_y=""
if [ $((flags & $SETUP_SRKPASS_ZEROS_F)) -ne 0 ]; then
parm_z="-z"
fi
if [ $((flags & $SETUP_OWNERPASS_ZEROS_F)) -ne 0 ]; then
parm_y="-y"
fi
a=$(expect -c "
set parm_z \"$parm_z\"
set parm_y \"$parm_y\"
spawn tpm_takeownership \$parm_z \$parm_y
if { \$parm_y == \"\" } {
expect {
\"Enter owner password:\"
{ send \"$ownerpass\n\" }
}
expect {
\"Confirm password:\"
{ send \"$ownerpass\n\" }
}
}
if { \$parm_z == \"\" } {
expect {
\"Enter SRK password:\"
{ send \"$srkpass\n\" }
}
expect {
\"Confirm password:\"
{ send \"$srkpass\n\" }
}
}
expect eof
catch wait result
exit [lindex \$result 3]
")
if [ $? -ne 0 ]; then
logerr "Could not take ownership of TPM."
return 1
fi
logit "Successfully took ownership of the TPM."
fi
# have external program create the certificates now
call_create_certs "$flags" "$config_file" "$certsdir" "$ek" "$vmid"
if [ $? -ne 0 ]; then
return 1
fi
# Define NVRAM are for Physical Presence Interface; unfortunately
# there are no useful write permissions...
#tpm_nvdefine \
# -i $((0x50010000)) \
# -p "PPREAD|PPWRITE|WRITEDEFINE" \
# -s 6 2>&1 > /dev/null
if [ $((flags & SETUP_EK_CERT_F)) -ne 0 ] && \
[ -r "${EK_CERT_FILE}" ]; then
tpm_nvdefine \
-i $((TPM_NV_INDEX_EKCert|TPM_NV_INDEX_D_BIT)) \
-p "${nvramauth}" \
-s $(stat -c%s "${EK_CERT_FILE}") 2>&1 >/dev/null
if [ $? -ne 0 ]; then
logerr "Could not create NVRAM area for EK certificate."
return 1
fi
tpm_nvwrite -i $((TPM_NV_INDEX_EKCert|TPM_NV_INDEX_D_BIT)) \
-f "${EK_CERT_FILE}" 2>&1 >/dev/null
logit "Successfully created NVRAM area for EK certificate."
rm -f ${EK_CERT_FILE}
fi
if [ $((flags & SETUP_PLATFORM_CERT_F)) -ne 0 ] && \
[ -r "${PLATFORM_CERT_FILE}" ] ; then
tpm_nvdefine \
-i $((TPM_NV_INDEX_PlatformCert|TPM_NV_INDEX_D_BIT)) \
-p "${nvramauth}" \
-s $(stat -c%s "${PLATFORM_CERT_FILE}") 2>&1 >/dev/null
if [ $? -ne 0 ]; then
logerr "Could not create NVRAM area for platform" \
"certificate."
return 1
fi
tpm_nvwrite \
-i $((TPM_NV_INDEX_PlatformCert|TPM_NV_INDEX_D_BIT)) \
-f "$PLATFORM_CERT_FILE" 2>&1 >/dev/null
logit "Successfully created NVRAM area for platform" \
"certificate."
rm -f ${PLATFORM_CERT_FILE}
fi
if [ $((flags & SETUP_DISPLAY_RESULTS_F)) -ne 0 ]; then
local nvidxs=`tpm_nvinfo -n | grep 0x | gawk '{print $1}'`
for i in $nvidxs; do
logit "Content of NVRAM area $i:"
tmp="tpm_nvread -i $i --password=$ownerpass"
logit_cmd "$cmd"
done
fi
# Last thing is to lock the NVRAM area
if [ $((flags & SETUP_LOCK_NVRAM_F)) -ne 0 ]; then
tpm_nvdefine -i $TPM_NV_INDEX_LOCK 2>&1 >/dev/null
if [ $? -ne 0 ]; then
logerr "Could not lock NVRAM access."
return 1
fi
logit "Successfully locked NVRAM access."
fi
# give up ownership if not wanted
if [ $((flags & SETUP_TAKEOWN_F)) -eq 0 -a \
$((flags & SETUP_CREATE_EK_F)) -ne 0 ] ; then
a=$(expect -c "
spawn tpm_clear
expect {
\"Enter owner password:\" { send \"$ownerpass\n\" }
}
expect eof
catch wait result
exit [lindex \$result 3]
")
if [ $? -ne 0 ]; then
logerr "Could not give up ownership of TPM."
return 1
fi
logit "Successfully gave up ownership of the TPM."
# TPM is now disabled and deactivated; enable and activate it
stop_tpm
start_tpm "$SWTPM" "$tpm_state_path"
if [ $? -ne 0 ]; then
logerr "Could not re-start TPM."
return 1
fi
TCSD_TCP_DEVICE_PORT=$TPM_PORT
swtpm_bios -c
if [ $? -ne 0 ]; then
logerr "swtpm_bios -c -o failed"
return 1
fi
logit "Successfully enabled and activated the TPM"
fi
return 0
}
usage()
{
cat <<EOF
Usage: $1 [options]
The following options are supported:
--runas <user> : Use the given user id to switch to and run this program;
this parameter is interpreted by swtpm_setup that switches
to this user and invokes swtpm_setup.sh; defaults to 'tss'
--tpm-state <dir>: Path to a directory where the TPM's state will be written into;
this is a mandatory argument
--tpm <executable>
: Path to the TPM executable; this is an optional argument and
by default $SWTPM is used
--keyfile <file> : File containing the encryption key to be used by the TPM
emulator; this parameter will be passed to the TPM using
'--key file=<file>'
--createek : Create the EK
--take-ownership : Take ownership; this option implies --createek
--ownerpass <password>
: Provide custom owner password; default is $DEFAULT_OWNER_PASSWORD
--owner-well-known:
: Use an owner password of 20 zero bytes
--srkpass <password>
: Provide custom SRK password; default is $DEFAULT_SRK_PASSWORD
--srk-well-known:
: Use an SRK password of 20 zero bytes
--create-ek-cert : Create an EK certificate; this implies --createek
(NOT SUPPORTED YET)
--create-platform-cert
: Create a platform certificate; this implies --create-ek-cert
(NOT SUPPORTED YET)
--lock-nvram : Lock NVRAM access
--display : At the end display as much info as possible about the
configuration of the TPM
--config <config file>
: Path to configuration file; default is $DEFAULT_CONFIG_FILE
--logfile <logfile>
: Path to log file; default is logging to stderr
--keyfile <keyfile>
: Path to a key file containing the encryption key for the
TPM to encrypt its persistent state with. The content
must be a 32 hex digit number representing a 128bit AES key.
--pwdfile <pwdfile>
: Path to a file containing a passphrase from which the
TPM will derive the 128bit AES key. The passphrase ca be
32 bytes long.
--help,-h,-? : Display this help screen
EOF
}
main()
{
local flags=0
local tpm_state_path=""
local config_file="$DEFAULT_CONFIG_FILE"
local vmid=""
local ret
local keyfile pwdfile
while [ $# -ne 0 ]; do
case "$1" in
--tpm-state) shift; tpm_state_path="$1";;
--tpm) shift; SWTPM="$1";;
--createek) flags=$((flags | SETUP_CREATE_EK_F));;
--take-ownership) flags=$((flags |
SETUP_CREATE_EK_F|SETUP_TAKEOWN_F));;
--ownerpass) shift; ownerpass="$1";;
--owner-well-known) flags=$((flags | SETUP_OWNERPASS_ZEROS_F));;
--srkpass) shift; srkpass="$1";;
--srk-well-known) flags=$((flags | SETUP_SRKPASS_ZEROS_F));;
--create-ek-cert) flags=$((flags |
SETUP_CREATE_EK_F|SETUP_EK_CERT_F));;
--create-platform-cert) flags=$((flags |
SETUP_CREATE_EK_F|SETUP_PLATFORM_CERT_F));;
--lock-nvram) flags=$((flags | SETUP_LOCK_NVRAM_F));;
--display) flags=$((flags | SETUP_DISPLAY_RESULTS_F));;
--config) shift; config_file="$1";;
--vmid) shift; vmid="$1";;
--keyfile) shift; keyfile="$1";;
--pwdfile) shift; pwdfile="$1";;
--runas) shift;; # ignore here
--logfile) shift; LOGFILE="$1";;
--help|-h|-?) usage $0; exit 0;;
*) logerr "Unknown option $1"; usage $0; exit 1;;
esac
shift
done
[ "$ownerpass" == "" ] && ownerpass=$DEFAULT_OWNER_PASSWORD
[ "$srkpass" == "" ] && srkpass=$DEFAULT_SRK_PASSWORD
if [ -n "$LOGFILE" ]; then
touch $LOGFILE &>/dev/null
if [ ! -w "$LOGFILE" ]; then
echo "Cannot write to logfile ${LOGFILE}." >&2
exit 1
fi
fi
if [ "$tpm_state_path" == "" ]; then
logerr "--tpm-state must be provided"
exit 1
fi
if [ ! -d "$tpm_state_path" ]; then
logerr "$tpm_state_path is not a directory that user $(whoami) could access."
exit 1
fi
if [ ! -r "$tpm_state_path" ]; then
logerr "Need read rights on directory $tpm_state_path for user $(whoami)."
exit 1
fi
if [ ! -w "$tpm_state_path" ]; then
logerr "Need write rights on directory $tpm_state_path for user $(whoami)."
exit 1
fi
rm -f \
"$tpm_state_path"/*permall \
"$tpm_state_path"/*volatilestate \
"$tpm_state_path"/*savestate \
2>/dev/null
if [ $? -ne 0 ]; then
logerr "Could not remove previous state files. Need execute access rights on the directory."
exit 1
fi
if [ -z "$SWTPM" ]; then
logerr "Default TPM 'swtpm' could not be found and was not provided using --tpm."
exit 1
fi
if [ ! -x "$(echo $SWTPM | cut -d " " -f1)" ]; then
logerr "TPM at $SWTPM is not an executable."
exit 1
fi
if [ ! -x "$TCSD" ]; then
logerr "TSS at $TCSD is not an executable."
exit 1
fi
if [ ! -r "$config_file" ]; then
logerr "Cannot access config file ${config_file}."
exit 1
fi
if [ -n "$keyfile" ]; then
if [ ! -r "$keyfile" ]; then
logerr "Cannot access keyfile $keyfile."
exit 1
fi
SWTPM="$SWTPM --key file=$keyfile"
logit " The TPM's state will be encrypted with a provided key."
elif [ -n "$pwdfile" ]; then
if [ ! -r "$pwdfile" ]; then
logerr "Cannot access passphrase file $pwdfile."
exit 1
fi
SWTPM="$SWTPM --key pwdfile=$pwdfile"
logit " The TPM's state will be encrypted using a key derived from a passphrase."
fi
logit "Starting vTPM manufacturing as $(id -n -u):$(id -n -g) @ $(date +%c)"
init_tpm $flags "$config_file" "$tpm_state_path" "$ownerpass" "$srkpass" "$vmid"
ret=$?
if [ $ret -eq 0 ]; then
logit "Successfully authored TPM state."
else
logerr "An error occurred. Authoring the TPM state failed."
fi
logit "Ending vTPM manufacturing @ $(date +%c)"
exit $ret
}
main "$@"

Binary file not shown.

View File

@ -0,0 +1,95 @@
/*
* tcsd-launcher.c
*
* Authors: Stefan Berger <stefanb@us.ibm.com>
*
* (c) Copyright IBM Corporation 2011,2014.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the names of the IBM Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <libgen.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#define E_USER_GROUP "tss" /* preferably tss */
int main(int argc, char *argv[])
{
const char *program = "/usr/sbin/tcsd";
struct passwd *passwd;
passwd = getpwnam(E_USER_GROUP);
if (!passwd) {
fprintf(stderr, "Could not get account data of user tss.\n");
return EXIT_FAILURE;
}
if (getuid() != passwd->pw_uid ||
getgid() != passwd->pw_gid) {
fprintf(stderr, "Only %s is allowed to launch this program.\n",
E_USER_GROUP);
fprintf(stderr, "uid=%d, gid=%d\n", getuid(), getgid());
return EXIT_FAILURE;
}
if (setegid(passwd->pw_gid)) {
fprintf(stderr, "Setting effective groupid to tss (%d) failed.\n",
passwd->pw_gid);
return EXIT_FAILURE;
}
if (initgroups(passwd->pw_name, passwd->pw_gid)) {
fprintf(stderr, "initgroups() failed: %s", strerror(errno));
return EXIT_FAILURE;
}
if (seteuid(passwd->pw_uid)) {
fprintf(stderr, "Setting effective userid to tss (%d) failed.\n",
passwd->pw_uid);
return EXIT_FAILURE;
}
execv(program, argv);
/* should never get here */
fprintf(stderr, "Could not execute '%s' : %s\n",
program,
strerror(errno));
return EXIT_FAILURE;
}

45
tests/Makefile.am Normal file
View File

@ -0,0 +1,45 @@
#
# tests/Makefile.am
#
# For the license, see the LICENSE file in the root directory.
#
check_PROGRAMS =
TESTS = \
test_init \
test_getcap \
test_locality \
test_hashing \
test_volatilestate \
test_wrongorder \
test_encrypted_state \
\
test_commandline \
test_parameters \
test_resume_volatile
if WITH_GNUTLS
TESTS += \
test_swtpm_cert
endif
EXTRA_DIST=$(TESTS) \
swtpm_setup.conf \
create_certs.sh \
data/issuercert.pem \
data/pubek.pem \
data/signkey.pem \
data/keyfile.txt \
data/pwdfile.txt \
data/tpmstate1/tpm-00.permall \
data/tpmstate1/tpm-00.volatilestate \
data/tpmstate1/README \
data/tpmstate2/tpm-00.permall \
data/tpmstate2/tpm-00.volatilestate \
data/tpmstate2/pwdfile.txt \
data/tpmstate2/README \
test_swtpm_cert
# Cannot run the tests in parallel...
.NOTPARALLEL:

41
tests/create_certs.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/bash
#echo $@
main() {
local typ ek dir vmid
while [ $# -ne 0 ]; do
#echo $1
case "$1" in
--type)
shift
typ="$1"
;;
--ek)
shift
ek="$1"
;;
--dir)
shift
dir="$1"
;;
--vmid)
shift
vmid="$1"
;;
esac
shift
done
case "$typ" in
ek)
echo -n "ek" > ${dir}/ek.cert
;;
platform)
echo -n "platform" > ${dir}/platform.cert
;;
esac
}
main "$@"

20
tests/data/issuercert.pem Normal file
View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDVTCCAg2gAwIBAgIEU+QtUTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDEw1z
d3RwbS1sb2NhbGNhMCIYDzIwMTQwODA4MDE1MjE3WhgPMjAxNTA4MDgwMTUyMTda
MBgxFjAUBgNVBAMTDXN3dHBtLWxvY2FsY2EwggFSMA0GCSqGSIb3DQEBAQUAA4IB
PwAwggE6AoIBMQC/Wa5oJFA0zpTB4P4GlyWrs9vKx35Gum6DN09cD6VVjzI/ApK9
fuONbZ9WnpKlSeq6nGKqNkhZpA/OeO2UdGLsCTxyX6kEugEth8SnP4RSX4gVM5pF
JXq03eWNMSH+A2GDNWT2ZgH7iSB9ks097NxThhHKkJbGDyKmNz3s+/jOqdFpYIvu
Z92Z3Oh13KM7Hp6S9m+DwWictb+o844MbJGrA3lyFEPxXNFAGjTEO08nlKmH3jb9
e/k8jfg/7A7ZoYXMuwsPUi4TM0O27X3MRgYerEu5mfRgenyi5M0pGJBGd/IcTS0s
NeIBtAXvXCMVAzFdcrf4MLULQsLQ+5vSyKujEUHiEEba25KIzjnNGPgzQnwkB8Dp
3p5/lvKAUmXLl7D3FdBzR2j7WFW1E5TJRIU/AgMBAAGjQzBBMA8GA1UdEwEB/wQF
MAMBAf8wDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4EFgQUZy3CXsth31HTcjCiWNAG
oI2PaZEwDQYJKoZIhvcNAQELBQADggExAB7qxGQ7mYVIFalQpYMERi3ASO85ZyQB
f7fdQmTHoIYGOT3DoVVxbNKNyaymyKLveA+qGZc/iYsOCjduDAuOdiR2Ugs+Ct7t
kFlrSbrjME3vzWv8yROn+q48jQ9L9E5GmWIz9e68sIRJCgLraQsVZ5EgulsowJGu
Jv06wkRKdT37WWCyrZ5L7LVX5JjlNQEaTLC4s7GY7kkJ6YSVBxoO7O4XZUxRM/vC
AQ6wwqBVO38wwnuE1kB4GlJ728QJC5Le1ekIg4TuSO8Jc/oBUwBJ8cZ7+bx30M95
8UwES5/X5MFqKuvwQoZ4rAufKNZwjHAPzzZevGlDUlBdVL8y2/NtF2fJDRLuM+dK
LaAwZpCh8gdyiAKbGU6j7f5lNEDpmJqgv4C+1Lasq0n/1da0Tr6IoBU=
-----END CERTIFICATE-----

1
tests/data/keyfile.txt Normal file
View File

@ -0,0 +1 @@
12345678901234567890123456789012

10
tests/data/pubek.pem Normal file
View File

@ -0,0 +1,10 @@
-----BEGIN PUBLIC KEY-----
MIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEAv1muaCRQNM6UweD+Bpcl
q7Pbysd+RrpugzdPXA+lVY8yPwKSvX7jjW2fVp6SpUnqupxiqjZIWaQPznjtlHRi
7Ak8cl+pBLoBLYfEpz+EUl+IFTOaRSV6tN3ljTEh/gNhgzVk9mYB+4kgfZLNPezc
U4YRypCWxg8ipjc97Pv4zqnRaWCL7mfdmdzoddyjOx6ekvZvg8FonLW/qPOODGyR
qwN5chRD8VzRQBo0xDtPJ5Sph942/Xv5PI34P+wO2aGFzLsLD1IuEzNDtu19zEYG
HqxLuZn0YHp8ouTNKRiQRnfyHE0tLDXiAbQF71wjFQMxXXK3+DC1C0LC0Pub0sir
oxFB4hBG2tuSiM45zRj4M0J8JAfA6d6ef5bygFJly5ew9xXQc0do+1hVtROUyUSF
PwIDAQAB
-----END PUBLIC KEY-----

1
tests/data/pwdfile.txt Normal file
View File

@ -0,0 +1 @@
mypassword

165
tests/data/signkey.pem Normal file
View File

@ -0,0 +1,165 @@
Public Key Info:
Public Key Algorithm: RSA
Key Security Level: Normal (2432 bits)
modulus:
00:bf:59:ae:68:24:50:34:ce:94:c1:e0:fe:06:97:
25:ab:b3:db:ca:c7:7e:46:ba:6e:83:37:4f:5c:0f:
a5:55:8f:32:3f:02:92:bd:7e:e3:8d:6d:9f:56:9e:
92:a5:49:ea:ba:9c:62:aa:36:48:59:a4:0f:ce:78:
ed:94:74:62:ec:09:3c:72:5f:a9:04:ba:01:2d:87:
c4:a7:3f:84:52:5f:88:15:33:9a:45:25:7a:b4:dd:
e5:8d:31:21:fe:03:61:83:35:64:f6:66:01:fb:89:
20:7d:92:cd:3d:ec:dc:53:86:11:ca:90:96:c6:0f:
22:a6:37:3d:ec:fb:f8:ce:a9:d1:69:60:8b:ee:67:
dd:99:dc:e8:75:dc:a3:3b:1e:9e:92:f6:6f:83:c1:
68:9c:b5:bf:a8:f3:8e:0c:6c:91:ab:03:79:72:14:
43:f1:5c:d1:40:1a:34:c4:3b:4f:27:94:a9:87:de:
36:fd:7b:f9:3c:8d:f8:3f:ec:0e:d9:a1:85:cc:bb:
0b:0f:52:2e:13:33:43:b6:ed:7d:cc:46:06:1e:ac:
4b:b9:99:f4:60:7a:7c:a2:e4:cd:29:18:90:46:77:
f2:1c:4d:2d:2c:35:e2:01:b4:05:ef:5c:23:15:03:
31:5d:72:b7:f8:30:b5:0b:42:c2:d0:fb:9b:d2:c8:
ab:a3:11:41:e2:10:46:da:db:92:88:ce:39:cd:18:
f8:33:42:7c:24:07:c0:e9:de:9e:7f:96:f2:80:52:
65:cb:97:b0:f7:15:d0:73:47:68:fb:58:55:b5:13:
94:c9:44:85:3f:
public exponent:
01:00:01:
private exponent:
7f:a4:4e:30:10:11:24:b8:ad:08:8b:92:48:49:29:
0a:d9:86:83:45:02:1a:22:20:b8:0c:fc:36:38:05:
9d:06:51:89:30:a9:3c:18:d9:a8:2c:f8:fe:29:f7:
3e:a5:09:1c:84:57:58:9d:af:33:84:ba:3a:8b:f6:
47:72:3f:ce:9d:f6:a1:80:e8:59:4b:ce:9f:55:92:
bb:d2:25:ed:60:e6:80:e6:14:41:8d:d7:c5:b0:c3:
80:a4:c6:bd:0f:fa:4b:31:21:f1:2f:68:a1:26:fe:
f2:65:2b:dd:e4:13:b0:ef:9d:0c:97:d8:cb:b3:aa:
f4:5f:a3:42:63:6e:bc:45:11:79:0e:bb:29:44:45:
d1:6e:47:ee:df:48:4f:96:84:47:1a:76:96:d8:3c:
75:53:ac:5c:70:dc:bc:49:90:88:a9:2d:2d:97:50:
7e:36:79:d7:01:99:de:6b:d8:30:94:e0:c4:b1:e2:
ef:f4:e8:2f:f6:be:5a:fd:90:c9:72:85:84:51:0d:
e5:88:da:1d:62:a3:1b:27:7a:4f:e2:20:77:03:5b:
87:18:43:15:fd:5b:96:06:4a:8e:c2:c8:df:0c:f6:
5b:a9:2e:34:33:62:47:fc:c6:26:6d:b6:e2:b2:b1:
d7:49:94:33:e1:d5:b4:d0:fe:42:6d:d0:1f:b7:e8:
24:f0:b7:ba:85:ea:ff:ce:24:5a:1b:5e:c0:87:08:
d8:71:6e:b4:62:8e:f0:12:c5:fe:c0:cd:06:2c:8e:
87:b1:2b:3d:51:10:51:ed:fd:59:92:2e:08:58:e5:
85:aa:de:c1:
prime1:
00:e4:e4:ef:1e:a3:b3:17:4c:af:c3:64:04:8e:44:
53:0d:92:6c:eb:36:26:5e:3c:ea:40:69:a8:5b:01:
c2:5e:83:a4:fe:1e:e5:e9:6c:d0:01:5e:c4:07:9c:
45:78:66:8f:0f:23:08:4b:3c:cd:6c:2b:4b:b3:8e:
82:32:af:77:5f:d8:53:fc:36:4a:90:24:ac:95:fb:
c6:fd:53:e5:ae:42:52:7c:f1:21:c1:c1:0f:27:e0:
10:b0:b3:09:7b:a3:ea:e4:3c:bc:7e:12:83:89:a8:
75:0f:62:c2:c3:ae:d0:19:05:80:56:c2:1b:fb:b5:
6d:a1:53:e5:56:91:65:55:d4:54:8d:32:3d:ac:79:
11:b7:94:06:61:ab:ed:58:6e:06:fa:e7:26:91:20:
2f:c7:5f:
prime2:
00:d6:02:94:72:6c:88:f0:a0:3d:f9:a6:7a:f4:00:
a1:69:b3:56:40:ab:eb:44:6e:24:05:d4:2b:cd:16:
42:3e:6c:58:64:f5:70:7d:59:bb:7f:e1:68:d8:10:
dc:3c:ad:f4:5f:f8:83:4b:f7:82:63:eb:01:27:15:
5c:ec:bf:7d:b6:82:c6:13:db:67:19:0f:b1:e6:f1:
2b:af:83:0a:fa:34:b3:d9:95:fd:2a:cd:3f:73:8b:
8b:b6:9a:68:83:72:71:1b:92:33:d2:aa:0f:03:89:
09:6d:a3:d0:e8:9d:4e:c9:64:1b:1e:16:88:06:7a:
92:f0:c3:05:8b:50:f0:61:30:af:9d:49:7b:0f:f9:
c7:9e:5c:60:82:50:58:f6:4d:86:e7:22:fb:7f:1f:
2f:6e:21:
coefficient:
1d:45:51:8d:0f:13:1e:fb:d4:67:41:31:43:71:cb:
bf:73:ae:fa:cd:00:3d:8f:45:94:75:98:92:be:fe:
ff:f3:b8:2d:d1:03:47:14:c0:1a:49:0c:c8:94:6d:
d4:94:a2:e8:c3:53:71:4f:7c:55:6b:7d:77:ff:dc:
8b:82:87:19:f3:1a:2c:20:fb:6b:8a:13:22:d0:5e:
1a:ae:ca:46:bc:b9:2c:24:58:10:84:f4:0e:05:06:
89:f4:33:ab:24:67:9f:4e:69:3f:41:5e:8a:56:ed:
47:ef:cc:38:bf:2f:43:4c:b4:d4:d8:2c:5b:4a:b2:
01:bc:4a:50:53:81:1c:bb:6c:ac:65:da:2e:81:04:
7b:6f:71:a8:71:82:29:7a:a9:af:99:0a:30:d3:4d:
ce:ac:
exp1:
00:90:4a:24:d6:ba:b8:ed:ca:20:ce:5a:21:69:11:
77:0d:8a:2d:71:04:bc:a1:11:63:55:e1:85:08:81:
8e:66:88:34:1d:21:9b:2b:4f:b5:bb:f7:62:39:ad:
f0:39:1a:e5:b9:d4:0a:a9:6b:15:cf:c7:67:3c:34:
6c:ac:c8:e1:c6:a0:97:28:d9:8c:9d:5b:11:14:a7:
17:e4:9f:db:9c:c3:20:3e:b4:be:e3:e5:f0:c8:e1:
3d:84:36:08:97:51:58:84:32:29:5c:8c:0d:31:5c:
e9:16:1e:da:ca:02:4c:1a:49:d6:82:5a:70:cb:76:
ae:3a:51:a9:b3:ad:8a:24:d5:e9:ca:ec:4d:e6:88:
97:7b:93:2b:86:ac:9b:bc:ef:f7:24:79:4c:5d:95:
dd:a8:9f:
exp2:
00:b0:ef:e1:1b:d9:70:3e:c1:bd:7b:b2:90:e5:3b:
c0:38:4b:f5:7b:f2:a7:c9:23:e6:d4:8a:de:cb:e9:
23:4b:c8:f8:2c:40:60:88:c2:af:aa:c3:0a:93:d9:
1c:bd:6e:75:25:03:aa:4a:1c:90:c9:5b:7a:d0:7d:
71:1e:ac:13:9b:d9:f3:3a:67:a3:8d:ac:d4:41:44:
14:02:40:2d:cb:3f:d7:92:85:d7:92:93:af:6a:30:
6d:8a:c3:8e:b5:5e:e0:f5:12:a3:96:00:d3:f8:f0:
4b:c3:42:35:6e:9c:e0:8e:d1:1d:3a:7b:16:6b:84:
dc:08:02:b5:8a:c1:98:7c:42:6c:6f:76:59:30:94:
2a:de:5b:31:cf:8b:ee:81:75:07:9c:01:e8:3c:e9:
e3:a5:01:
Public Key ID: 67:2D:C2:5E:CB:61:DF:51:D3:72:30:A2:58:D0:06:A0:8D:8F:69:91
Public key's random art:
+--[ RSA 2432]----+
| ..o+. . o |
| = oo. . o.|
| E . ... ..+|
| = . . +.|
| + . S B . . |
| . . B = . . |
| . o . . |
| |
| |
+-----------------+
-----BEGIN RSA PRIVATE KEY-----
MIIFfAIBAAKCATEAv1muaCRQNM6UweD+Bpclq7Pbysd+RrpugzdPXA+lVY8yPwKS
vX7jjW2fVp6SpUnqupxiqjZIWaQPznjtlHRi7Ak8cl+pBLoBLYfEpz+EUl+IFTOa
RSV6tN3ljTEh/gNhgzVk9mYB+4kgfZLNPezcU4YRypCWxg8ipjc97Pv4zqnRaWCL
7mfdmdzoddyjOx6ekvZvg8FonLW/qPOODGyRqwN5chRD8VzRQBo0xDtPJ5Sph942
/Xv5PI34P+wO2aGFzLsLD1IuEzNDtu19zEYGHqxLuZn0YHp8ouTNKRiQRnfyHE0t
LDXiAbQF71wjFQMxXXK3+DC1C0LC0Pub0siroxFB4hBG2tuSiM45zRj4M0J8JAfA
6d6ef5bygFJly5ew9xXQc0do+1hVtROUyUSFPwIDAQABAoIBMH+kTjAQESS4rQiL
kkhJKQrZhoNFAhoiILgM/DY4BZ0GUYkwqTwY2ags+P4p9z6lCRyEV1idrzOEujqL
9kdyP86d9qGA6FlLzp9VkrvSJe1g5oDmFEGN18Www4Ckxr0P+ksxIfEvaKEm/vJl
K93kE7DvnQyX2MuzqvRfo0JjbrxFEXkOuylERdFuR+7fSE+WhEcadpbYPHVTrFxw
3LxJkIipLS2XUH42edcBmd5r2DCU4MSx4u/06C/2vlr9kMlyhYRRDeWI2h1ioxsn
ek/iIHcDW4cYQxX9W5YGSo7CyN8M9lupLjQzYkf8xiZttuKysddJlDPh1bTQ/kJt
0B+36CTwt7qF6v/OJFobXsCHCNhxbrRijvASxf7AzQYsjoexKz1REFHt/VmSLghY
5YWq3sECgZkA5OTvHqOzF0yvw2QEjkRTDZJs6zYmXjzqQGmoWwHCXoOk/h7l6WzQ
AV7EB5xFeGaPDyMISzzNbCtLs46CMq93X9hT/DZKkCSslfvG/VPlrkJSfPEhwcEP
J+AQsLMJe6Pq5Dy8fhKDiah1D2LCw67QGQWAVsIb+7VtoVPlVpFlVdRUjTI9rHkR
t5QGYavtWG4G+ucmkSAvx18CgZkA1gKUcmyI8KA9+aZ69AChabNWQKvrRG4kBdQr
zRZCPmxYZPVwfVm7f+Fo2BDcPK30X/iDS/eCY+sBJxVc7L99toLGE9tnGQ+x5vEr
r4MK+jSz2ZX9Ks0/c4uLtppog3JxG5Iz0qoPA4kJbaPQ6J1OyWQbHhaIBnqS8MMF
i1DwYTCvnUl7D/nHnlxgglBY9k2G5yL7fx8vbiECgZkAkEok1rq47cogzlohaRF3
DYotcQS8oRFjVeGFCIGOZog0HSGbK0+1u/diOa3wORrludQKqWsVz8dnPDRsrMjh
xqCXKNmMnVsRFKcX5J/bnMMgPrS+4+XwyOE9hDYIl1FYhDIpXIwNMVzpFh7aygJM
GknWglpwy3auOlGps62KJNXpyuxN5oiXe5MrhqybvO/3JHlMXZXdqJ8CgZkAsO/h
G9lwPsG9e7KQ5TvAOEv1e/KnySPm1Irey+kjS8j4LEBgiMKvqsMKk9kcvW51JQOq
ShyQyVt60H1xHqwTm9nzOmejjazUQUQUAkAtyz/XkoXXkpOvajBtisOOtV7g9RKj
lgDT+PBLw0I1bpzgjtEdOnsWa4TcCAK1isGYfEJsb3ZZMJQq3lsxz4vugXUHnAHo
POnjpQECgZgdRVGNDxMe+9RnQTFDccu/c676zQA9j0WUdZiSvv7/87gt0QNHFMAa
SQzIlG3UlKLow1NxT3xVa313/9yLgocZ8xosIPtrihMi0F4arspGvLksJFgQhPQO
BQaJ9DOrJGefTmk/QV6KVu1H78w4vy9DTLTU2CxbSrIBvEpQU4Ecu2ysZdougQR7
b3GocYIpeqmvmQow003OrA==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,13 @@
The volatile state of this TPM instance has
PCR[10] = 6edd3260501da32ade90a14ca310dfc3a74fa004
The state is not encrypted.
The value of PCR 10 can be found as follows:
# od -tx1 tpm-00.volatilestate
[...]
0000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6e
0000440 dd 32 60 50 1d a3 2a de 90 a1 4c a3 10 df c3 a7
[...]

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
The volatile state of this TPM instance has
PCR[10] = 6edd3260501da32ade90a14ca310dfc3a74fa004
The state is encrypted.
The value of PCR 10 cannot easily be found in tpm-00.volatilestate.

View File

@ -0,0 +1 @@
mypassword

Binary file not shown.

Binary file not shown.

2
tests/swtpm_setup.conf Executable file
View File

@ -0,0 +1,2 @@
# Program invoked for creating certificates
create_certs_tool=create_certs.sh

105
tests/test_commandline Executable file
View File

@ -0,0 +1,105 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
TPMDIR=`mktemp -d`
TPMAUTHORING=$ROOT/src/swtpm_setup/swtpm_setup
PATH=${PWD}/${ROOT}/src/swtpm:$PATH
PATH=${PWD}/${ROOT}/src/swtpm_setup:$PATH
PATH=${PWD}/${ROOT}/src/swtpm_bios:$PATH
trap "cleanup" SIGTERM EXIT
function cleanup()
{
rm -rf $TPMDIR
}
PORT=11234
export TCSD_TCP_DEVICE_HOSTNAME=localhost
export TCSD_TCP_DEVICE_PORT=$PORT
export TCSD_USE_TCP_DEVICE=1
# Test 1: test port and directory command line parameters
$SWTPM_EXE socket -p $PORT -i $TPMDIR &>/dev/null &
PID=$!
sleep 5
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Test 1 failed: TPM process not running"
exit 1
fi
swtpm_bios &>/dev/null
if [ $? -ne 0 ]; then
echo "Test 1 failed: tpm_bios did not work"
exit 1
fi
kill -SIGTERM $PID &>/dev/null
sleep 1
exec 20<&1-; exec 21<&2-
kill -0 $PID &>/dev/null
RES=$?
exec 1<&20-; exec 2<&21-
if [ $RES -eq 0 ]; then
kill -SIGKILL $PID
echo "Test 1 failed: TPM process did not terminate on SIGTERM"
exit 1
fi
echo "Test 1 passed"
cleanup
# Test 2: test port, directory and terminate command line parameters
TPMDIR=`mktemp -d`
$SWTPM_EXE socket -p $PORT -i $TPMDIR -t &>/dev/null &
PID=$!
sleep 5
exec 20<&1-; exec 21<&2-
kill -0 $PID
exec 1<&20-; exec 2<&21-
if [ $? -ne 0 ]; then
echo "Test 2 failed: TPM process not running"
exit 1
fi
exec 200<> /dev/tcp/localhost/$PORT
if [ $? -ne 0 ]; then
echo "Test 2 failed: Could not connect to TPM"
exit 1
fi
exec 200>&-
# Give it time to shut down
sleep 2
exec 20<&1-; exec 21<&2-
kill -0 $PID
RES=$?
exec 1<&20-; exec 2<&21-
if [ $RES -eq 0 ]; then
kill -SIGKILL $PID
echo "Test 2 failed: TPM process did not terminate on connection loss"
exit 1
fi
echo "Test 2 passed"

202
tests/test_encrypted_state Executable file
View File

@ -0,0 +1,202 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
KEY=1234567890abcdef1234567890abcdef
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
keyfile=$(mktemp)
logfile=$(mktemp)
echo "$KEY" > $keyfile
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
rm -f $keyfile $logfile
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME --key file=$keyfile,mode=aes-cbc,format=hex \
--log file=$logfile
#sleep 20
#echo "continuing"
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
export TPM_DUMP_COMMANDS=1
export TPM_DEVICE=/dev/$VTPM_NAME
#tpmbios -o
# Startup the TPM
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n)
exp=' 00 c4 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Did not get expected result from TPM_Startup(ST_Clear)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
$CUSE_TPM_IOCTL -h 1234 /dev/$VTPM_NAME
# Read PCR 17
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (1) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Save the volatile state
$CUSE_TPM_IOCTL -v /dev/$VTPM_NAME
if [ ! -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
exit 1
fi
sleep 5
# Shut the TPM down
exec 100>&-
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
# Start the TPM again; have the keyfile removed
$SWTPM_EXE -n $VTPM_NAME --key file=$keyfile,mode=aes-cbc,format=hex,remove \
--log file=$logfile
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
if [ -r $keyfile ]; then
echo "Error: Keyfile $keyfile was not removed by swtpm_cuse."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
# Volatile state must have been removed by TPM now
if [ -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists."
exit 1
fi
# Read the PCR again ...
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Save the volatile state again
$CUSE_TPM_IOCTL -v /dev/$VTPM_NAME
if [ ! -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
exit 1
fi
# Send a new TPM_Init
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
# Volatile state must have been removed by TPM now
if [ -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists."
exit 1
fi
# Read the PCR again ...
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Finale shut down
exec 100>&-
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0

93
tests/test_getcap Executable file
View File

@ -0,0 +1,93 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
# Get the capabilities flags from the TPM
act=$($CUSE_TPM_IOCTL -c /dev/$VTPM_NAME)
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after getting capabilities."
exit 1
fi
exp="ptm capability is 0x([[:xdigit:]]+)"
if ! [[ "$act" =~ ^${exp}$ ]]; then
echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'."
exit 1
fi
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0

178
tests/test_hashing Executable file
View File

@ -0,0 +1,178 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
export TPM_DUMP_COMMANDS=1
export TPM_DEVICE=/dev/$VTPM_NAME
#tpmbios -o
# Startup the TPM
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n)
exp=' 00 c4 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Did not get expected result from TPM_Startup(ST_Clear)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Check the TPM Established bit before the hashing
RES=$($CUSE_TPM_IOCTL -e /dev/$VTPM_NAME)
exp='tpmEstablished is 0'
if [ "$RES" != "$exp" ]; then
echo "Error (1): TPM Established flag has wrong value."
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
$CUSE_TPM_IOCTL -h 1234 /dev/$VTPM_NAME
# Read PCR 17
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (1) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Check the TPM Established bit after the hashing
RES=$($CUSE_TPM_IOCTL -e /dev/$VTPM_NAME)
exp='tpmEstablished is 1'
if [ "$RES" != "$exp" ]; then
echo "Error (2): TPM Established flag has wrong value."
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Reset the establishment bit via locality 3
$CUSE_TPM_IOCTL -l 3 /dev/$VTPM_NAME
if [ $? -ne -0 ]; then
echo "Error: Could not set locality 3"
exit 1
fi
ECHO=$(which echo)
if [ -z "$ECHO" ]; then
echo "Could not find NON-bash builtin echo tool."
exit 1
fi
# \x40 or \x0B seems to confuse 'normal' echo
$ECHO -en '\x00\xC1\x00\x00\x00\x0A\x40\x00\x00\x0B' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Could not reset the establishment bit"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Check the TPM Established bit after the reset
RES=$($CUSE_TPM_IOCTL -e /dev/$VTPM_NAME)
exp='tpmEstablished is 0'
if [ "$RES" != "$exp" ]; then
echo "Error (3): TPM Established flag has wrong value."
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# back to locality 0
$CUSE_TPM_IOCTL -l 0 /dev/$VTPM_NAME
# Read from a file
dd if=/dev/zero bs=1024 count=1024 2>/dev/null| \
$CUSE_TPM_IOCTL -h - /dev/$VTPM_NAME
# Read PCR 17
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 d8 0e 7a 7b 3c 37 88 7d b4 c2 88 08 1d a7 53 f6 4b 11 3a 9c'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0

78
tests/test_init Executable file
View File

@ -0,0 +1,78 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0

131
tests/test_locality Executable file
View File

@ -0,0 +1,131 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
# Set locality 4 on the TPM
$CUSE_TPM_IOCTL -l 4 /dev/$VTPM_NAME
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not accept locality 4."
exit 1
fi
# Set illegal locality 5 on the TPM
$CUSE_TPM_IOCTL -l 5 /dev/$VTPM_NAME
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM accepted locality 5."
exit 1
fi
# Set locality 0 on the TPM
$CUSE_TPM_IOCTL -l 0 /dev/$VTPM_NAME
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not accept locality 0."
exit 1
fi
# In locality 2 we can reset PCR 20
$CUSE_TPM_IOCTL -l 2 /dev/$VTPM_NAME
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not accept locality 2."
exit 1
fi
exec 100<>/dev/$VTPM_NAME
# Startup the TPM
echo -en '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n)
exp=' 00 c4 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Did not get expected result from TPM_Startup(ST_Clear)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Reset PCR 20
echo -en '\x00\xC1\x00\x00\x00\x0F\x00\x00\x00\xC8\x00\x03\x00\x00\x10' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n)
exp=' 00 c4 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Could not reset PCR 20 in locality 2"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Shut down TPM
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0

110
tests/test_parameters Executable file
View File

@ -0,0 +1,110 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
DIR=$(dirname "$0")
ROOT=${DIR}/..
PARAMETERS=(
""
"--createek"
"--take-ownership"
"--createek --lock-nvram"
"--take-ownership --lock-nvram"
"--lock-nvram"
"--take-ownership --ownerpass OOO"
"--take-ownership --srkpass SSS"
"--take-ownership --ownerpass OO --srkpass SS"
"--take-ownership --lock-nvram --display"
"--display"
"--lock-nvram --display"
"--take-ownership --srk-well-known"
"--take-ownership --owner-well-known"
"--take-ownership --srk-well-known --owner-well-known"
"--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${DIR}/swtpm_setup.conf --vmid test --display"
"--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${DIR}/swtpm_setup.conf --vmid test --display --keyfile ${DIR}/data/keyfile.txt"
"--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${DIR}/swtpm_setup.conf --vmid test --display --pwdfile ${DIR}/data/pwdfile.txt"
)
FILESIZES=(
1169
1589
2050
1589
2050
1169
2050
2050
2050
2050
1169
1169
2050
2050
2050
1705
1712
1712
)
SWTPM=swtpm
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
TCSD=`type -P tcsd`
TPMDIR=`mktemp -d`
SWTPM_SETUP_CONF=$ROOT/etc/swtpm_setup.conf
# filesystem privileges require to run swtpm_setup as root during test
TPMAUTHORING="$ROOT/src/swtpm_setup/swtpm_setup --config ${SWTPM_SETUP_CONF} --runas root"
PATH=${PWD}/${ROOT}/src/swtpm_bios:$PATH
PATH=${PWD}/${ROOT}/src/swtpm_setup:$PATH
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
trap "cleanup" SIGTERM EXIT
if test "$TCSD" = ""; then
echo "TCSD executable 'tcsd' was not found in path."
exit 1
fi
function cleanup()
{
rm -rf $TPMDIR
}
chown tss:tss $TPMDIR 2>/dev/null
if [ $? -ne 0 ]; then
echo "Could not change ownership of $TPMDIR to tss:tss." \
"You need to be root."
exit 1
fi
for (( i=0; i<${#PARAMETERS[*]}; i++)); do
rm -rf $TPMDIR/*
echo -n "Test $i: "
$TPMAUTHORING \
--tpm-state $TPMDIR \
--tpm "$SWTPM_EXE socket" \
${PARAMETERS[$i]} 2>&1 >/dev/null
if [ $? -ne 0 ]; then
echo "ERROR: Test with parameters '${PARAMETERS[$i]}' failed."
exit 1
elif [ ! -f $TPMDIR/tpm-00.permall ]; then
echo "ERROR: Test with parameters '${PARAMETERS[$i]}' did not
produce file $TPMDIR/tpm-00.permall."
exit 1
fi
FILESIZE=`stat -c%s $TPMDIR/tpm-00.permall`
if [ ${FILESIZE} -ne ${FILESIZES[$i]} ]; then
echo "ERROR: Unexpected file size of $FILESIZE, "\
"expected ${FILESIZES[$i]}. Parameters: ${PARAMETERS[$i]}"
exit 1
fi
echo "SUCCESS with parameters '${PARAMETERS[$i]}'."
done

169
tests/test_resume_volatile Executable file
View File

@ -0,0 +1,169 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
export TPM_PATH=${PWD}/${DIR}/data/tpmstate1
# make a backup of the volatile state
VOLATILE_STATE=$TPM_PATH/tpm-00.volatilestate
VOLATILE_STATE_BAK=${VOLATILE_STATE}.bak
cp -f $VOLATILE_STATE $VOLATILE_STATE_BAK
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
exec 100<>/dev/$VTPM_NAME
# Read PCR 10
/usr/bin/echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 6e dd 32 60 50 1d a3 2a de 90 a1 4c a3 10 df c3 a7 4f a0 04'
if [ "$RES" != "$exp" ]; then
echo "Error: (1) Did not get expected result from TPM_PCRRead(10)"
echo "expected: $exp"
echo "received: $RES"
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
# Save the volatile state again
$CUSE_TPM_IOCTL -v /dev/$VTPM_NAME
if [ ! -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
# Shut the TPM down
exec 100>&-
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
echo "Test 1: Ok"
# 2nd test: with encrypted state
export TPM_PATH=${PWD}/${DIR}/data/tpmstate2
# make a backup of the volatile state
VOLATILE_STATE=$TPM_PATH/tpm-00.volatilestate
VOLATILE_STATE_BAK=${VOLATILE_STATE}.bak
cp -f $VOLATILE_STATE $VOLATILE_STATE_BAK
$SWTPM_EXE -n $VTPM_NAME --key pwdfile=${PWD}/${DIR}/data/tpmstate2/pwdfile.txt
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
exec 100<>/dev/$VTPM_NAME
# Read PCR 10
/usr/bin/echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 6e dd 32 60 50 1d a3 2a de 90 a1 4c a3 10 df c3 a7 4f a0 04'
if [ "$RES" != "$exp" ]; then
echo "Error: (1) Did not get expected result from TPM_PCRRead(10)"
echo "expected: $exp"
echo "received: $RES"
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
# Save the volatile state again
$CUSE_TPM_IOCTL -v /dev/$VTPM_NAME
if [ ! -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
exit 1
fi
# Shut the TPM down
exec 100>&-
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
# Restore the original volatile state
mv $VOLATILE_STATE_BAK $VOLATILE_STATE
echo "Test 2: Ok"

117
tests/test_swtpm_cert Executable file
View File

@ -0,0 +1,117 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM_CERT=${ROOT}/src/swtpm_cert/swtpm_cert
cert=$(mktemp)
trap "cleanup" SIGTERM EXIT
function cleanup()
{
rm -f ${cert}
}
${SWTPM_CERT} \
--signkey ${DIR}/data/signkey.pem \
--issuercert ${DIR}/data/issuercert.pem \
--out-cert ${cert} \
--modulus 'b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497' \
--days 3650 \
--pem \
--tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2
#expecting size to be constant
size=$(stat -c%s ${cert} 2>/dev/null)
exp=1224
if [ $size -ne $exp ]; then
echo "Error: Certificate file has wrong size."
echo " Expected: $exp; found: $size"
exit 1
fi
# truncate result file
echo -n > ${cert}
echo "Test 1: OK"
${SWTPM_CERT} \
--signkey ${DIR}/data/signkey.pem \
--issuercert ${DIR}/data/issuercert.pem \
--out-cert ${cert} \
--modulus 'b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497' \
--days 3650 \
--subject "OU=foo,L=NewYork,ST=NY,C=US" \
--pem \
--tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2
#expecting size to be constant
size=$(stat -c%s ${cert} 2>/dev/null)
exp=1302
if [ $size -ne $exp ]; then
echo "Error: Certificate file has wrong size."
echo " Expected: $exp; found: $size"
exit 1
fi
# truncate result file
echo -n > ${cert}
echo "Test 2: OK"
${SWTPM_CERT} \
--signkey ${DIR}/data/signkey.pem \
--issuercert ${DIR}/data/issuercert.pem \
--out-cert ${cert} \
--pubkey ${DIR}/data/pubek.pem \
--days 3650 \
--subject "OU=foo,L=NewYork,ST=NY,C=US" \
--pem \
--tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2
#expecting size to be constant
size=$(stat -c%s ${cert} 2>/dev/null)
exp=1367
if [ $size -ne $exp ]; then
echo "Error: Certificate file has wrong size."
echo " Expected: $exp; found: $size"
exit 1
fi
# truncate result file
#certtool --certificate-info --infile ${cert}
echo -n > ${cert}
echo "Test 3: OK"
###################### Platform Certificate #####################
${SWTPM_CERT} \
--type platform \
--signkey ${DIR}/data/signkey.pem \
--issuercert ${DIR}/data/issuercert.pem \
--pubkey ${DIR}/data/pubek.pem \
--out-cert ${cert} \
--days 3650 \
--subject "OU=foo,L=NewYork,ST=NY,C=US" \
--pem \
--tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \
--platform-manufacturer Fedora \
--platform-model QEMU \
--platform-version 2.1
#expecting size to be constant
size=$(stat -c%s ${cert} 2>/dev/null)
exp=1411
if [ $size -ne $exp ]; then
echo "Error: Certificate file has wrong size."
echo " Expected: $exp; found: $size"
exit 1
fi
# truncate result file
#certtool --certificate-info --infile ${cert}
echo -n > ${cert}
echo "Test 4: OK"

185
tests/test_volatilestate Executable file
View File

@ -0,0 +1,185 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
export TPM_DUMP_COMMANDS=1
export TPM_DEVICE=/dev/$VTPM_NAME
#tpmbios -o
# Startup the TPM
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n)
exp=' 00 c4 00 00 00 0a 00 00 00 00'
if [ "$RES" != "$exp" ]; then
echo "Error: Did not get expected result from TPM_Startup(ST_Clear)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
$CUSE_TPM_IOCTL -h 1234 /dev/$VTPM_NAME
# Read PCR 17
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (1) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Save the volatile state
$CUSE_TPM_IOCTL -v /dev/$VTPM_NAME
if [ ! -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
exit 1
fi
# Shut the TPM down
exec 100>&-
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
# Start the TPM again
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
# Volatile state must have been removed by TPM now
if [ -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists."
exit 1
fi
# Read the PCR again ...
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Save the volatile state again
$CUSE_TPM_IOCTL -v /dev/$VTPM_NAME
if [ ! -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist."
exit 1
fi
# Send a new TPM_Init
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
# Volatile state must have been removed by TPM now
if [ -r $VOLATILE_STATE_FILE ]; then
echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists."
exit 1
fi
# Read the PCR again ...
exec 100<>/dev/$VTPM_NAME
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5'
if [ "$RES" != "$exp" ]; then
echo "Error: (2) Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
# Finale shut down
exec 100>&-
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0

114
tests/test_wrongorder Executable file
View File

@ -0,0 +1,114 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm_cuse
SWTPM_EXE=$ROOT/src/swtpm/$SWTPM
CUSE_TPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl
MAJOR=255
MINOR=100
VTPM_NAME=$(printf "vtpm-%d-%d" $MAJOR $MINOR)
export TPM_PATH=/tmp
STATE_FILE=$TPM_PATH/tpm-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
if [ "$(id -u)" -ne 0 ]; then
echo "Need to be root to run this test."
exit 77
fi
function cleanup()
{
pid=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
if [ -n "$pid" ]; then
kill -9 $pid
fi
}
trap "cleanup" EXIT
modprobe cuse
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
$SWTPM_EXE -n $VTPM_NAME
sleep 0.5
PID=$(ps aux | grep $SWTPM | grep $VTPM_NAME | gawk '{print $2}')
ps aux | grep $SWTPM | grep -v grep
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM did not start."
exit 1
fi
# Get the established bit before the TPM has been initialized
# This should not work
$CUSE_TPM_IOCTL -e /dev/$VTPM_NAME
if [ $? -eq 0 ]; then
echo "Error: Could get established bit from CUSE TPM before init."
exit 1
fi
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM must have crashed."
exit 1
fi
# Open access to the TPM
exec 100<>/dev/$VTPM_NAME
# Read PCR 17 -- this should give a fatal error response
echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100
RES=$(dd if=/proc/self/fd/100 2>/dev/null | od -t x1 -A n -w128)
exp=' 00 c4 00 00 00 0a 00 00 00 09'
if [ "$RES" != "$exp" ]; then
echo "Error: Did not get expected result from TPM_PCRRead(17)"
echo "expected: $exp"
echo "received: $RES"
exit 1
fi
exec 100>&-
kill -0 $PID
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM must have crashed."
exit 1
fi
# Init the TPM
$CUSE_TPM_IOCTL -i /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: CUSE TPM not running anymore after INIT."
exit 1
fi
$CUSE_TPM_IOCTL -s /dev/$VTPM_NAME
sleep 0.5
kill -0 $PID 2>/dev/null
if [ $? -eq 0 ]; then
echo "Error: CUSE TPM should not be running anymore."
exit 1
fi
if [ ! -e $STATE_FILE ]; then
echo "Error: TPM state file $STATE_FILE does not exist."
exit 1
fi
echo "OK"
exit 0