Merge ~lvoytek/ubuntu/+source/swtpm:merge-0.7.3-lunar into ubuntu/+source/swtpm:ubuntu/devel

Proposed by Lena Voytek
Status: Merged
Approved by: git-ubuntu bot
Approved revision: not available
Merged at revision: a41799c8a93dc0eef7b0942e3915fff253aa76fb
Proposed branch: ~lvoytek/ubuntu/+source/swtpm:merge-0.7.3-lunar
Merge into: ubuntu/+source/swtpm:ubuntu/devel
Diff against target: 12000 lines (+5652/-1392)
191 files modified
.github/ISSUE_TEMPLATE/bug_report.md (+3/-0)
.gitignore (+5/-4)
.travis.yml (+0/-1)
CHANGES (+41/-18)
INSTALL (+4/-3)
Makefile.am (+0/-1)
configure.ac (+60/-29)
debian/changelog (+19/-0)
debian/clean (+3/-0)
debian/control (+0/-2)
debian/patches/no-autoconf-in-debian.patch (+5/-7)
debian/patches/openssl-not-certtool.patch (+23/-23)
debian/patches/series (+0/-1)
debian/rules (+6/-0)
debian/swtpm-tools.install (+5/-2)
dev/null (+0/-51)
include/Makefile.am (+2/-0)
include/compiler_dependencies.h (+17/-0)
include/swtpm/tpm_ioctl.h (+4/-0)
include/sys_dependencies.h (+8/-0)
man/man8/Makefile.am (+14/-8)
man/man8/swtpm-create-tpmca.pod (+6/-6)
man/man8/swtpm-localca.8 (+1/-0)
man/man8/swtpm-localca.conf.pod (+3/-3)
man/man8/swtpm-localca.options.pod (+2/-2)
man/man8/swtpm.pod (+75/-10)
man/man8/swtpm_cert.pod (+4/-1)
man/man8/swtpm_cuse.pod (+4/-1)
man/man8/swtpm_localca.pod (+4/-4)
man/man8/swtpm_setup.conf.pod (+6/-0)
man/man8/swtpm_setup.pod (+98/-12)
samples/Makefile.am (+6/-32)
samples/swtpm-create-user-config-files.in (+7/-60)
samples/swtpm-localca.in (+5/-0)
samples/swtpm_setup.conf.in (+3/-1)
src/Makefile.am (+1/-0)
src/selinux/Makefile.am (+1/-1)
src/swtpm/Makefile.am (+13/-6)
src/swtpm/capabilities.c (+21/-4)
src/swtpm/common.c (+65/-16)
src/swtpm/common.h (+4/-2)
src/swtpm/ctrlchannel.c (+3/-3)
src/swtpm/cuse_tpm.c (+74/-41)
src/swtpm/daemonize.c (+302/-0)
src/swtpm/daemonize.h (+6/-5)
src/swtpm/mainloop.c (+12/-6)
src/swtpm/seccomp_profile.c (+3/-1)
src/swtpm/swtpm.c (+61/-32)
src/swtpm/swtpm_aes.c (+84/-44)
src/swtpm/swtpm_chardev.c (+62/-33)
src/swtpm/swtpm_nvstore.c (+174/-317)
src/swtpm/swtpm_nvstore.h (+40/-16)
src/swtpm/swtpm_nvstore_dir.c (+527/-0)
src/swtpm/swtpm_nvstore_linear.c (+480/-0)
src/swtpm/swtpm_nvstore_linear.h (+83/-0)
src/swtpm/swtpm_nvstore_linear_file.c (+295/-0)
src/swtpm/tlv.c (+10/-4)
src/swtpm/tpmlib.c (+11/-9)
src/swtpm/tpmstate.c (+39/-16)
src/swtpm/tpmstate.h (+7/-2)
src/swtpm/utils.c (+1/-1)
src/swtpm/utils.h (+10/-2)
src/swtpm_bios/tpm_bios.c (+2/-2)
src/swtpm_cert/ek-cert.c (+17/-15)
src/swtpm_ioctl/tpm_ioctl.c (+3/-6)
src/swtpm_localca/Makefile.am (+38/-0)
src/swtpm_localca/swtpm_localca.c (+31/-42)
src/swtpm_localca/swtpm_localca_utils.c (+21/-0)
src/swtpm_localca/swtpm_localca_utils.h (+2/-0)
src/swtpm_setup/Makefile.am (+4/-3)
src/swtpm_setup/swtpm.c (+120/-58)
src/swtpm_setup/swtpm.h (+13/-3)
src/swtpm_setup/swtpm_backend_dir.c (+118/-0)
src/swtpm_setup/swtpm_backend_file.c (+108/-0)
src/swtpm_setup/swtpm_setup.c (+415/-208)
src/swtpm_setup/swtpm_setup_conf.h.in (+3/-0)
src/swtpm_setup/swtpm_setup_utils.c (+151/-2)
src/swtpm_setup/swtpm_setup_utils.h (+2/-0)
src/utils/swtpm_utils.c (+23/-0)
src/utils/swtpm_utils.h (+6/-1)
swtpm.spec (+15/-10)
swtpm.spec.in (+14/-9)
tests/Makefile.am (+27/-12)
tests/_test_encrypted_state (+1/-1)
tests/_test_getcap (+1/-1)
tests/_test_hashing (+1/-1)
tests/_test_hashing2 (+1/-1)
tests/_test_init (+1/-1)
tests/_test_locality (+1/-1)
tests/_test_migration_key (+3/-3)
tests/_test_print_capabilities (+6/-6)
tests/_test_print_states (+70/-0)
tests/_test_save_load_encrypted_state (+3/-3)
tests/_test_save_load_state (+60/-8)
tests/_test_setbuffersize (+1/-1)
tests/_test_swtpm_bios (+1/-1)
tests/_test_tpm2_encrypted_state (+1/-1)
tests/_test_tpm2_file_permissions (+255/-0)
tests/_test_tpm2_getcap (+1/-1)
tests/_test_tpm2_hashing (+1/-1)
tests/_test_tpm2_hashing2 (+1/-1)
tests/_test_tpm2_hashing3 (+1/-1)
tests/_test_tpm2_init (+1/-1)
tests/_test_tpm2_locality (+1/-1)
tests/_test_tpm2_migration_key (+4/-4)
tests/_test_tpm2_print_capabilities (+5/-5)
tests/_test_tpm2_print_states (+70/-0)
tests/_test_tpm2_probe (+1/-1)
tests/_test_tpm2_resume_volatile (+1/-1)
tests/_test_tpm2_save_load_encrypted_state (+3/-3)
tests/_test_tpm2_save_load_state (+2/-2)
tests/_test_tpm2_save_load_state_da_timeout (+19/-7)
tests/_test_tpm2_savestate (+1/-1)
tests/_test_tpm2_setbuffersize (+1/-1)
tests/_test_tpm2_swtpm_bios (+1/-1)
tests/_test_tpm2_volatilestate (+1/-1)
tests/_test_tpm2_wrongorder (+1/-1)
tests/_test_tpm_probe (+1/-1)
tests/_test_volatilestate (+1/-1)
tests/_test_wrongorder (+1/-1)
tests/common (+91/-10)
tests/test_commandline (+67/-3)
tests/test_ctrlchannel (+7/-5)
tests/test_ctrlchannel2 (+7/-5)
tests/test_ctrlchannel3 (+2/-1)
tests/test_ctrlchannel4 (+3/-1)
tests/test_encrypted_state (+5/-0)
tests/test_getcap (+5/-0)
tests/test_hashing (+5/-0)
tests/test_hashing2 (+5/-0)
tests/test_init (+5/-0)
tests/test_locality (+5/-0)
tests/test_migration_key (+5/-0)
tests/test_parameters (+3/-2)
tests/test_print_capabilities (+5/-0)
tests/test_print_states (+20/-0)
tests/test_resume_volatile (+5/-0)
tests/test_samples_create_tpmca (+3/-2)
tests/test_save_load_encrypted_state (+5/-0)
tests/test_save_load_state (+16/-0)
tests/test_setbuffersize (+5/-0)
tests/test_setdatafd.py (+0/-3)
tests/test_swtpm_bios (+5/-0)
tests/test_swtpm_cert (+3/-4)
tests/test_swtpm_setup_create_cert (+33/-8)
tests/test_swtpm_setup_file_backend (+112/-0)
tests/test_swtpm_setup_misc (+79/-0)
tests/test_swtpm_setup_overwrite (+114/-0)
tests/test_tpm12 (+3/-2)
tests/test_tpm2_ctrlchannel2 (+3/-1)
tests/test_tpm2_derived_keys (+5/-0)
tests/test_tpm2_encrypted_state (+5/-0)
tests/test_tpm2_file_permissions (+41/-0)
tests/test_tpm2_getcap (+5/-0)
tests/test_tpm2_hashing (+5/-0)
tests/test_tpm2_hashing2 (+5/-0)
tests/test_tpm2_hashing3 (+5/-0)
tests/test_tpm2_ibmtss2 (+14/-2)
tests/test_tpm2_init (+5/-0)
tests/test_tpm2_locality (+5/-0)
tests/test_tpm2_migration_key (+5/-0)
tests/test_tpm2_parameters (+15/-9)
tests/test_tpm2_partial_reads (+2/-1)
tests/test_tpm2_print_capabilities (+5/-0)
tests/test_tpm2_print_states (+29/-0)
tests/test_tpm2_probe (+5/-0)
tests/test_tpm2_resume_volatile (+5/-0)
tests/test_tpm2_samples_create_tpmca.test (+2/-2)
tests/test_tpm2_save_load_encrypted_state (+5/-0)
tests/test_tpm2_save_load_state (+5/-0)
tests/test_tpm2_save_load_state_2 (+19/-5)
tests/test_tpm2_save_load_state_2_block (+36/-0)
tests/test_tpm2_save_load_state_2_linear (+5/-0)
tests/test_tpm2_save_load_state_3 (+3/-1)
tests/test_tpm2_save_load_state_da_timeout (+5/-0)
tests/test_tpm2_savestate (+5/-0)
tests/test_tpm2_setbuffersize (+5/-0)
tests/test_tpm2_swtpm_bios (+5/-0)
tests/test_tpm2_swtpm_cert (+1/-1)
tests/test_tpm2_swtpm_cert_ecc (+1/-1)
tests/test_tpm2_swtpm_localca (+2/-2)
tests/test_tpm2_swtpm_localca_pkcs11.test (+4/-2)
tests/test_tpm2_swtpm_setup_create_cert (+124/-37)
tests/test_tpm2_swtpm_setup_overwrite (+117/-0)
tests/test_tpm2_volatilestate (+5/-0)
tests/test_tpm2_vtpm_proxy (+3/-1)
tests/test_tpm2_wrongorder (+5/-0)
tests/test_tpm_probe (+5/-0)
tests/test_volatilestate (+5/-0)
tests/test_vtpm_proxy (+3/-1)
tests/test_wrongorder (+5/-0)
Reviewer Review Type Date Requested Status
git-ubuntu bot Approve
Robie Basak Approve
Canonical Server Reporter Pending
Review via email: mp+439532@code.launchpad.net

Description of the change

Update to 0.7.3 to fix TPM secure boot in Lunar

PPA: https://launchpad.net/~lvoytek/+archive/ubuntu/swtpm-update-lunar

autopkgtest results:

autopkgtest [07:48:29]: @@@@@@@@@@@@@@@@@@@@ summary
run-tests PASS

Currently working on the FFE info for the bug

To post a comment you must log in.
Revision history for this message
Utkarsh Gupta (utkarsh) wrote :

I'll take this for (pair) review with Mitchell. Lena please let us know once the FFE bug is filed. Thanks.

Revision history for this message
Lena Voytek (lvoytek) wrote :

FFe filed, thanks!

Revision history for this message
Robie Basak (racb) wrote :

[Needs verifying:] In swtpm-tools, /usr/lib/x86_64-linux-gnu/swtpm/swtpm-localca seems to have moved to /usr/bin/swtpm_localca - I assume this is desirable/intentional?

[Not a blocker for upload if we need that right now:]

Apart from this I see no substantial changes in the binary, so this seems OK from the perspective of user functionality (modulo testing for which I think we can rely on existing test automation).

But, I think the packaging updates are a little confused. I would expect one of the following:

1) That we manage our own packaging as a "first class citizen", cherry-picking or deriving packaging from Debian or upstream but only where that makes sense for our own packaging.

2) That we base our packaging on an upstream (be it Debian or upstream's debian/ directory), try to keep that in sync as much as possible, maintaining a delta where necessary but rebasing and minimising that delta regularly. Basing on Debian like this is of course what we do for the majority of packages.

Right now I think we're somewhere in between these options, and I think this hurts maintainability. Some examples inline. In particular it seems to me that some changes are cherry-picks that don't apply to our current state of packaging. So why are we taking them? If because of option 2 above, then I'd expect these changes to be picked up by a rebase, that would for example also take the changes that are required for the cherry-picks to be useful.

Ideally, what I'd like to see is either: 1a) a minimal set of packaging changes required to bring us up to 0.7.3; or 1b) divergence and clean packaging for Ubuntu going forward, but including only packaging changes that make sense for us to carry; or 2) a rebase onto either Debian or upstream and the maintenance of a minimal delta as required.

But, I appreciate that we need to get 0.7.x in Lunar now for its TPM 2.0 support. And the above concerns are about future maintenance; the current branch does seem to work correctly for now in terms of the build output. So we can upload this as-is as a stop gap if necessary.

review: Needs Information
Revision history for this message
Robie Basak (racb) wrote :

(sorry Utkarsh; Christian asked in standup today that we look at this before you're back)

Revision history for this message
Lena Voytek (lvoytek) wrote :

Thanks for the review Robie!
The move of swtpm-localca is intentional for consistency with other binaries provided by swtpm-tools. I confirmed that this is working properly with lxc, with binaries in /usr/bin/ consisting of:
/usr/bin/swtpm /usr/bin/swtpm_bios /usr/bin/swtpm_cert /usr/bin/swtpm_ioctl /usr/bin/swtpm_localca /usr/bin/swtpm_setup

I agree that I cherry picked a bit too much for this version. I've gotten rid of the unneeded new files and updated the swtpm-tools.install file since the if statement is unnecessary. I think it's best to keep our changes low for now and ideally someday be more consistent with upstream once some fundamental differences are solved. Next cycle I'll try and get Debian and Ubuntu in sync (which this upload luckily helps with) to progress to that point.

Revision history for this message
Robie Basak (racb) wrote :

Thanks!

I verified that this update didn't change the list of files in the output binary packages on amd64, so I think we're good to go for now.

FTR, I also checked that your PPA orig tarball matches the official one from https://github.com/stefanberger/swtpm/archive/refs/tags/v0.7.3.tar.gz exactly. seeded-in-ubuntu reports nothing for swtpm, so I believe we can upload during the current Beta freeze safely, and the FFe is approved.

review: Approve
Revision history for this message
git-ubuntu bot (git-ubuntu-bot) wrote :

Approvers: racb, lvoytek
Uploaders: racb
MP auto-approved

review: Approve
Revision history for this message
Robie Basak (racb) wrote :

Sponsored.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
2index a5c166f..3a1a923 100644
3--- a/.github/ISSUE_TEMPLATE/bug_report.md
4+++ b/.github/ISSUE_TEMPLATE/bug_report.md
5@@ -31,5 +31,8 @@ A clear and concise description of what you expected to happen.
6 - gnutls:
7 - ...:
8
9+**Log files**
10+Please attach any log files. If using a VM and it was started with libvirt, attach the logfile found in `/var/log/swtpm/libvirt/qemu/VM-NAME-swtpm.log`.
11+
12 **Additional context**
13 Add any other context about the problem here.
14diff --git a/.gitignore b/.gitignore
15index 187d102..99680cb 100644
16--- a/.gitignore
17+++ b/.gitignore
18@@ -8,7 +8,6 @@
19 *.la
20 *.lo
21 *.o
22-*.patch
23 *~
24 .deps
25 .libs
26@@ -33,18 +32,17 @@ Makefile
27 /missing
28 /stamp-h1
29 /swtpm-*.tar.gz
30-/swtpm.spec
31 /m4/*
32 /.pc/*
33-/etc/swtpm_setup.conf
34 /patches/*
35 /include/swtpm.h
36 /man/man3/*.3
37 /man/man8/*.8
38+!/man/man8/swtpm-localca.8
39 /samples/swtpm-create-user-config-files
40 /samples/swtpm-localca
41 /samples/swtpm-localca.conf
42-/samples/swtpm_localca_conf.h
43+/samples/swtpm_setup.conf
44 /src/selinux/*.pp.bz2
45 /src/selinux/swtpm.pp
46 /src/selinux/swtpm_svirt.fc
47@@ -57,6 +55,8 @@ Makefile
48 /src/swtpm_bios/swtpm_bios
49 /src/swtpm_cert/swtpm_cert
50 /src/swtpm_ioctl/swtpm_ioctl
51+/src/swtpm_localca/swtpm_localca
52+/src/swtpm_localca/swtpm_localca_conf.h
53 src/swtpm_setup/swtpm_setup
54 src/swtpm_setup/swtpm_setup_conf.h
55 /test-driver
56@@ -65,6 +65,7 @@ tests/*.trs
57 tests/test_config
58 /debian/*debhelper*
59 /debian/*substvars
60+/debian/autoreconf.*
61 /debian/files
62 /debian/swtpm
63 /debian/swtpm-cuse
64diff --git a/.travis.yml b/.travis.yml
65index e32a149..4b16e3c 100644
66--- a/.travis.yml
67+++ b/.travis.yml
68@@ -18,7 +18,6 @@ addons:
69 - bash
70 - dh-exec
71 - python3-pip
72- - python3-twisted
73 - libfuse-dev
74 - libglib2.0-dev
75 - libjson-glib-dev
76diff --git a/CHANGES b/CHANGES
77index 75a6170..04231fb 100644
78--- a/CHANGES
79+++ b/CHANGES
80@@ -1,40 +1,63 @@
81 CHANGES - changes for swtpm
82
83-version 0.6.3:
84+version 0.7.3:
85+ - swtpm:
86+ - Use uint64_t in tlv_data_append() to avoid integer overflows
87+ - Use uint64_t to avoid integer wrap-around when adding a uint32_t
88+ - build-sys:
89+ - Fix configure script to support _FORTIFY_SOURCE=3
90+ - Define __USE_LINUX_IOCTL_DEFS in header file (Cygwin)
91+
92+version 0.7.2:
93 - swtpm:
94 - Do not chdir(/) when using --daemon
95 - swtpm-localca:
96 - Re-implement variable resolution for swtpm-localca.conf
97 - tests:
98 - Use ${WORKDIR} in config files to test env. var replacement
99- - man:
100+ - man pages:
101 - Add missing .config directory to path description when using ${HOME}
102 - build-sys:
103 - Add probing for -fstack-protector
104- - configure: Fix typo TPM2 -> TMP2
105
106-version 0.6.2:
107+version 0.7.1:
108 - swtpm:
109 - Check header size indicator against expected size (CVE-2022-23645)
110- - swtpm-localca:
111+ - swtpm_localca:
112 - Test for available issuercert before creating CA
113- - swtpm_setup:
114- - Report stderr as returned by external tool (swtpm-localcal)
115- - Fix exit code on error to be '1'.
116
117-version 0.6.1:
118+version 0.7.0:
119 - swtpm:
120- - Clear keys from stack and heap
121- - swtpm-localca:
122- - Add missing else branch for pkcs11 and PIN
123+ - Support for linear file storage backend (file://)
124+ - Report 'tpm-1.2' & 'tpm-2.0' in --print-capabilities depending what
125+ libtpms supports
126+ - Add implementation of SWTPM_HMAC using OpenSSL 3.0 APIs
127+ - Wipe keys from stack and heap
128+ - Many other small changes
129+ - Make --daemon not racy
130 - swtpm_setup:
131- - Initialize Gerror and free it
132- - Replace '\\s' in regex with [[:space:]] to fix cygwin
133- - tests:
134- - Kill tpm2-abrmd with SIGKILL rather SIGTERM
135+ - Only activate SHA256 PCR bank, not SHA1 bank anymore by default
136+ - Support for linear file storage backend (file://)
137+ - Implement option --create-config-files to create config files
138+ - Use non-deprecated APIs to contruct RSA key (OSSL 3)
139+ - Report stderr as returned by external tool (swtpm-localcal)
140+ - Replace '+' and ',' characters in VMId's to make work with
141+ common name in X509 subject
142+ - Add support for --reconfigure flag to change active PCR banks
143+ - swtpm_localca:
144+ - Created certificates for CAs and TPM that do not expire
145+ - swtpm_cert:
146+ - Allow passing -1 for days to get a non-expiring certificate
147+ - test:
148+ - ASAN-related test changes and skipping of tests if ASAN is used
149+ - Fix tests using tpm2-abrmd by preventing concurrency
150+ - Skip chardev related tests after checking for chardev support
151+ - exit with error code if mktemp fails
152+ - OSSL 3: Make TPM 1.2 test compile; skip IBM TSS 2 test
153 - build-sys:
154- - Use -DOPENSSL_SUPPRESS_DEPRECATED to suppress deprecation warnings (OSSL 3)
155- - Enable configuring with CFLAGS and passing additional CFLAGS on build
156+ - Introduce --enable-sanitizers to configure
157+ - Remove check for pip3 that was used by python swtpm_setup
158+ - Allow passing of aditional CFLAGS during build
159
160 version 0.6.0:
161 - swtpm:
162diff --git a/INSTALL b/INSTALL
163index 90d2d7d..5d9f3b0 100644
164--- a/INSTALL
165+++ b/INSTALL
166@@ -13,12 +13,13 @@ Building and running the swtpm has dependencies on the following packages:
167 - fuse-devel
168 - glib2
169 - glib2-devel
170+- json-glib-devel
171 - net-tools
172 - python3
173 - python3-twisted
174 - selinux-policy-devel
175+- socat
176 - trousers
177-- tpm-tools
178 - gnutls
179 - gnutls-devel
180 - libtasn1
181@@ -35,8 +36,8 @@ Debian/Ubuntu also needs the following packages to build:
182 On RHEL or Fedora use either one of the following methods to install
183 the above dependencies:
184
185- - sudo dnf builddep ./dist/swtpm.spec (Fedora >= 22)
186- - sudo yum install yum-utils ; sudo yum-builddep ./dist/swtpm.spec (RHEL and Fedora <= 21)
187+ - sudo dnf builddep ./swtpm.spec (Fedora >= 22)
188+ - sudo yum install yum-utils ; sudo yum-builddep ./swtpm.spec (RHEL and Fedora <= 21)
189 - sudo yum install <package name(s)>
190
191 On Ubuntu use the following command:
192diff --git a/Makefile.am b/Makefile.am
193index 096052e..25c3068 100644
194--- a/Makefile.am
195+++ b/Makefile.am
196@@ -5,7 +5,6 @@
197 #
198
199 SUBDIRS = \
200- etc \
201 include \
202 man \
203 samples \
204diff --git a/configure.ac b/configure.ac
205index aa5bbfc..ccae445 100644
206--- a/configure.ac
207+++ b/configure.ac
208@@ -23,7 +23,7 @@
209 # This file is derived from tpm-tool's configure.in.
210 #
211
212-AC_INIT([swtpm], [0.6.3])
213+AC_INIT([swtpm],[0.7.3])
214 AC_PREREQ([2.69])
215 AC_CONFIG_SRCDIR(Makefile.am)
216 AC_CONFIG_HEADERS([config.h])
217@@ -125,12 +125,17 @@ fi
218 if test "x$prefix" = "xNONE"; then
219 prefix="/usr/local"
220 fi
221+if test "x$exec_prefix" = "xNONE"; then
222+ exec_prefix=$prefix
223+fi
224 SYSCONFDIR=`eval echo $sysconfdir`
225 DATAROOTDIR=`eval echo $datarootdir`
226 LOCALSTATEDIR=`eval echo $localstatedir`
227+BINDIR=`eval echo $bindir`
228 AC_SUBST([SYSCONFDIR])
229 AC_SUBST([DATAROOTDIR])
230 AC_SUBST([LOCALSTATEDIR])
231+AC_SUBST([BINDIR])
232
233 cryptolib=openssl
234
235@@ -151,8 +156,6 @@ openssl)
236 AC_MSG_RESULT([Building with openssl crypto library])
237 LIBCRYPTO_LIBS=$(pkg-config --libs libcrypto)
238 AC_SUBST([LIBCRYPTO_LIBS])
239- LIBCRYPTO_EXTRA_CFLAGS="-DOPENSSL_SUPPRESS_DEPRECATED"
240- AC_SUBST([LIBCRYPTO_EXTRA_CFLAGS])
241 ;;
242 esac
243
244@@ -237,7 +240,7 @@ AC_SUBST([GLIB_CFLAGS])
245
246 GLIB_LIBS=$(pkg-config --libs glib-2.0)
247 if test $? -ne 0; then
248- AC_MSG_ERROR("Is libglib-2.0-dev/glib2-devel installed? -- could not get cflags")
249+ AC_MSG_ERROR("Is libglib-2.0-dev/glib2-devel installed? -- could not get libs")
250 fi
251 AC_SUBST([GLIB_LIBS])
252
253@@ -343,6 +346,29 @@ fi
254 AM_CONDITIONAL([WITH_GNUTLS], [test "x$with_gnutls" = "xyes"])
255 AC_SUBST([GNUTLS_LIBS])
256
257+DEFAULT_PCR_BANKS="sha256"
258+AC_ARG_ENABLE([default-pcr-banks],
259+ AS_HELP_STRING(
260+ [--enable-default-pcr-banks=list of PCR banks],
261+ [Have swtpm_setup activate the given PCR banks by default;
262+ default is sha256]
263+ ),
264+ [],
265+ []
266+)
267+
268+if test "x$enable_default_pcr_banks" != "x"; then
269+ DEFAULT_PCR_BANKS="$enable_default_pcr_banks"
270+fi
271+AC_MSG_CHECKING([which PCR banks to activate by default])
272+REGEX="^(sha1|sha256|sha384|sha512)(,(sha1|sha256|sha384|sha512)){0,3}\$"
273+if bash -c "[[[ $DEFAULT_PCR_BANKS =~ $REGEX ]]] && exit 0 || exit 1"; then
274+ AC_MSG_RESULT([$DEFAULT_PCR_BANKS])
275+else
276+ AC_MSG_ERROR([$DEFAULT_PCR_BANKS is an invalid list of PCR banks])
277+fi
278+AC_SUBST([DEFAULT_PCR_BANKS])
279+
280 AC_PATH_PROG([EXPECT], expect)
281 if test "x$EXPECT" = "x"; then
282 AC_MSG_ERROR([expect is required: expect package])
283@@ -370,16 +396,6 @@ fi
284
285 AM_PATH_PYTHON([3.3])
286
287-AC_PATH_PROG([PIP3], pip3)
288-if test "x$PIP3" = "x"; then
289- AC_PATH_PROG([PIP3], pip)
290- if test "x$PIP3" = "x"; then
291- AC_MSG_WARN([pip3 is required to uninstall the built package])
292- else
293- AC_MSG_WARN([Using pip as pip3 tool])
294- fi
295-fi
296-
297 AC_ARG_ENABLE([hardening],
298 AS_HELP_STRING([--disable-hardening], [Disable hardening flags]))
299
300@@ -394,11 +410,10 @@ if test "x$enable_hardening" != "xno"; then
301 HARDENING_CFLAGS="-fstack-protector-strong -Wstack-protector"
302 fi
303
304- dnl Must not have -O0 but must have a -O for -D_FORTIFY_SOURCE=2
305- TMP1="$(echo $CFLAGS | sed -n 's/.*\(-O0\).*/\1/p')"
306- TMP2="$(echo $CFLAGS | sed -n 's/.*\(-O\).*/\1/p')"
307- if test -z "$TMP1" && test -n "$TMP2"; then
308- HARDENING_CFLAGS="$HARDENING_CFLAGS -D_FORTIFY_SOURCE=2 "
309+ dnl Only support -D_FORTIFY_SOURCE=2 and have higher levels passed in by user
310+ dnl since they may create more overhead
311+ if $CC $CFLAGS -Werror -D_FORTIFY_SOURCE=2 $srcdir/include/swtpm/tpm_ioctl.h 2>/dev/null; then
312+ HARDENING_CFLAGS="$HARDENING_CFLAGS -D_FORTIFY_SOURCE=2"
313 fi
314 dnl Check linker for 'relro' and 'now'
315 save_CFLAGS="$CFLAGS"
316@@ -431,6 +446,23 @@ if test "x$enable_test_coverage" = "xyes"; then
317 COVERAGE_LDFLAGS="-fprofile-arcs"
318 fi
319
320+AC_ARG_ENABLE([sanitizers],
321+ AS_HELP_STRING([--enable-sanitizers], [Enable address/undefined sanitizers]))
322+
323+if test "x$enable_sanitizers" = "xyes"; then
324+ save_CFLAGS="$CFLAGS"
325+ CFLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
326+ AC_MSG_CHECKING([whether linker supports sanitizer])
327+ AC_LINK_IFELSE(
328+ [AC_LANG_SOURCE([[int main() { return 0; }]])],
329+ [SANITIZER_CFLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
330+ SANITIZER_LDFLAGS="-fsanitize=address,undefined"
331+ AC_MSG_RESULT(yes)],
332+ [AC_MSG_RESULT(no)]
333+ )
334+ CFLAGS="$save_CFLAGS"
335+fi
336+
337 AC_ARG_WITH([tss-user],
338 AS_HELP_STRING([--with-tss-user=TSS_USER],[The tss user to use]),
339 [TSS_USER="$withval"],
340@@ -466,9 +498,9 @@ AC_SUBST([TSS_GROUP])
341 CFLAGS="$CFLAGS -Wreturn-type -Wsign-compare -Wswitch-enum"
342 CFLAGS="$CFLAGS -Wmissing-prototypes -Wall -Werror"
343 CFLAGS="$CFLAGS -Wformat -Wformat-security"
344-CFLAGS="$CFLAGS $GNUTLS_CFLAGS $COVERAGE_CFLAGS"
345+CFLAGS="$CFLAGS $GNUTLS_CFLAGS $COVERAGE_CFLAGS $SANITIZER_CFLAGS"
346
347-LDFLAGS="$LDFLAGS $COVERAGE_LDFLAGS"
348+LDFLAGS="$LDFLAGS $COVERAGE_LDFLAGS $SANITIZER_LDFLAGS"
349
350 dnl Simulate the following for systems with pkg-config < 0.28:
351 dnl PKG_CHECK_VAR([libtpms_cryptolib], [libtpms], [cryptolib],
352@@ -500,11 +532,6 @@ linux-*)
353 [whether to build in vTPM proxy support (Linux only)])
354 esac
355
356-case $host_os in
357-cygwin)
358- CFLAGS="$CFLAGS -D__USE_LINUX_IOCTL_DEFS"
359-esac
360-
361 dnl Seccomp profile using -lseccomp (Linux only)
362 case $host_os in
363 linux-*)
364@@ -545,12 +572,10 @@ AC_SUBST([MY_LDFLAGS])
365 AC_CONFIG_FILES([Makefile \
366 debian/swtpm-tools.postinst \
367 swtpm.spec \
368- etc/Makefile \
369- etc/swtpm_setup.conf \
370 samples/Makefile \
371 samples/swtpm-localca.conf \
372 samples/swtpm-create-user-config-files \
373- samples/swtpm_localca_conf.h \
374+ samples/swtpm_setup.conf \
375 include/Makefile \
376 include/swtpm/Makefile \
377 include/swtpm.h \
378@@ -560,6 +585,8 @@ AC_CONFIG_FILES([Makefile \
379 src/swtpm_bios/Makefile \
380 src/swtpm_cert/Makefile \
381 src/swtpm_ioctl/Makefile \
382+ src/swtpm_localca/Makefile \
383+ src/swtpm_localca/swtpm_localca_conf.h \
384 src/swtpm_setup/Makefile \
385 src/swtpm_setup/swtpm_setup_conf.h \
386 src/utils/Makefile \
387@@ -569,6 +596,8 @@ AC_CONFIG_FILES([Makefile \
388 tests/Makefile \
389 tests/test_config \
390 ])
391+AC_CONFIG_FILES([samples/swtpm-localca],
392+ [chmod 755 samples/swtpm-localca])
393 AC_OUTPUT
394
395 echo
396@@ -578,6 +607,8 @@ printf "with_cuse : %5s (no = no CUSE interface)\n" $with_cuse
397 printf "with_chardev : %5s (no = no chardev interface)\n" $with_chardev
398 printf "with_vtpm_proxy : %5s (no = no vtpm proxy support; Linux only)\n" $with_vtpm_proxy
399 printf "with_seccomp : %5s (no = no seccomp profile; Linux only)\n" $with_seccomp
400+printf "\n"
401+printf "active PCR banks : %s\n" $DEFAULT_PCR_BANKS
402 echo
403 echo "Version to build : $PACKAGE_VERSION"
404 echo "Crypto library : $cryptolib"
405diff --git a/debian/changelog b/debian/changelog
406index 23a49b3..8f3d87c 100644
407--- a/debian/changelog
408+++ b/debian/changelog
409@@ -1,3 +1,22 @@
410+swtpm (0.7.3-0ubuntu1) lunar; urgency=medium
411+
412+ * New upstream release 0.7.3:
413+ - Bug fixes include:
414+ + Fix secure boot failure - TPM 2.0 not supported (LP: #2012028)
415+ * Add new debian/ files from upstream
416+ - d/clean: Clean man and gch files from source tree during build
417+ - d/not-installed: Do not install .la lib files with package
418+ - d/swtpm-libs.install: Install swtpm .so files with swtpm-libs package
419+ * d/rules: Add dh_clean and dh_makeshlibs overrides from upstream
420+ * d/swtpm-tools.install: Update installation of swtpm-tools files for 0.7
421+ * d/control: Remove unneeded dependencies for 0.7
422+ * Remove d/p/0001-Install-swtpm-localca-to-the-correct-path.patch as it is
423+ no longer needed to change swtpm-localca's path
424+ * d/p/no-autoconf-in-debian.patch: Refresh to clean fuzz
425+ * d/p/openssl-not-certtool.patch: Update and refresh to apply with 0.7
426+
427+ -- Lena Voytek <lena.voytek@canonical.com> Wed, 22 Mar 2023 14:03:19 -0700
428+
429 swtpm (0.6.3-0ubuntu5) lunar; urgency=medium
430
431 * d/usr.bin.swtpm: Allow swtpm to also access /run/libvirt/qemu/swtpm/*.pid
432diff --git a/debian/clean b/debian/clean
433new file mode 100644
434index 0000000..494005d
435--- /dev/null
436+++ b/debian/clean
437@@ -0,0 +1,3 @@
438+include/swtpm/*.gch
439+man/*/*.3
440+man/*/*.8
441diff --git a/debian/control b/debian/control
442index a62d3d8..429a050 100644
443--- a/debian/control
444+++ b/debian/control
445@@ -10,11 +10,9 @@ Build-Depends: libtool,
446 libfuse-dev,
447 libglib2.0-dev,
448 libjson-glib-dev,
449- libgmp-dev,
450 expect,
451 libtasn1-dev,
452 socat,
453- python3-twisted,
454 gnutls-dev,
455 gnutls-bin,
456 libssl-dev,
457diff --git a/debian/patches/0001-Install-swtpm-localca-to-the-correct-path.patch b/debian/patches/0001-Install-swtpm-localca-to-the-correct-path.patch
458deleted file mode 100644
459index 990d2dd..0000000
460--- a/debian/patches/0001-Install-swtpm-localca-to-the-correct-path.patch
461+++ /dev/null
462@@ -1,65 +0,0 @@
463-From e2e987443d475f472d50150aaf4aa87ebf584003 Mon Sep 17 00:00:00 2001
464-From: Steve Langasek <steve.langasek@canonical.com>
465-Date: Sat, 23 Oct 2021 01:14:23 -0700
466-Subject: [PATCH] Install swtpm-localca to the correct path.
467-
468-This is an auxiliary executable, not data; it belongs in the libexecdir
469-path, not datarootdir.
470----
471- configure.ac | 8 ++++----
472- etc/swtpm_setup.conf.in | 2 +-
473- src/swtpm_setup/swtpm_setup_conf.h.in | 2 +-
474- src/swtpm_setup/swtpm_setup_utils.c | 2 +-
475- 4 files changed, 7 insertions(+), 7 deletions(-)
476-
477-Index: swtpm/configure.ac
478-===================================================================
479---- swtpm.orig/configure.ac
480-+++ swtpm/configure.ac
481-@@ -116,8 +116,8 @@
482- if test "$prefix" = "/usr" && test "$sysconfdir" = '${prefix}/etc'; then
483- sysconfdir="/etc"
484- fi
485--if test "$prefix" = "" && test "$datarootdir" = '${prefix}/share'; then
486-- datarootdir="/usr/share"
487-+if test "$prefix" = "" && test "$libexecdir" = '${prefix}/libexec'; then
488-+ libexecdir="/usr/libexec"
489- fi
490- if test "$prefix" = "/usr" && test "$localstatedir" = '${prefix}/var'; then
491- localstatedir="/var"
492-@@ -126,10 +126,10 @@
493- prefix="/usr/local"
494- fi
495- SYSCONFDIR=`eval echo $sysconfdir`
496--DATAROOTDIR=`eval echo $datarootdir`
497-+LIBEXECDIR=`eval echo $libexecdir`
498- LOCALSTATEDIR=`eval echo $localstatedir`
499- AC_SUBST([SYSCONFDIR])
500--AC_SUBST([DATAROOTDIR])
501-+AC_SUBST([LIBEXECDIR])
502- AC_SUBST([LOCALSTATEDIR])
503-
504- cryptolib=openssl
505-Index: swtpm/etc/swtpm_setup.conf.in
506-===================================================================
507---- swtpm.orig/etc/swtpm_setup.conf.in
508-+++ swtpm/etc/swtpm_setup.conf.in
509-@@ -1,4 +1,4 @@
510- # Program invoked for creating certificates
511--create_certs_tool= @DATAROOTDIR@/swtpm/swtpm-localca
512-+create_certs_tool= @LIBEXECDIR@/swtpm/swtpm-localca
513- create_certs_tool_config = @SYSCONFDIR@/swtpm-localca.conf
514- create_certs_tool_options = @SYSCONFDIR@/swtpm-localca.options
515-Index: swtpm/samples/Makefile.am
516-===================================================================
517---- swtpm.orig/samples/Makefile.am
518-+++ swtpm/samples/Makefile.am
519-@@ -7,7 +7,7 @@
520- samplesconfdir = $(datadir)/@PACKAGE@
521- samplessysconfdir = $(sysconfdir)
522- # swtpm-localca was always installed in /usr/samples/swtpm-localca
523--bindir = $(samplesconfdir)
524-+bindir = $(pkglibexecdir)
525-
526- samplesconf_SCRIPTS = \
527- swtpm-create-tpmca \
528diff --git a/debian/patches/no-autoconf-in-debian.patch b/debian/patches/no-autoconf-in-debian.patch
529index 7f78e71..ed0cf52 100644
530--- a/debian/patches/no-autoconf-in-debian.patch
531+++ b/debian/patches/no-autoconf-in-debian.patch
532@@ -4,15 +4,13 @@ Description: don't modify debian directory from upstream configure script
533 Author: Steve Langasek <steve.langasek@ubuntu.com>
534 Last-Update: 2021-10-23
535
536-Index: swtpm/configure.ac
537-===================================================================
538---- swtpm.orig/configure.ac
539-+++ swtpm/configure.ac
540-@@ -540,7 +540,6 @@
541+--- a/configure.ac
542++++ b/configure.ac
543+@@ -570,7 +570,6 @@
544 AC_SUBST([MY_LDFLAGS])
545
546 AC_CONFIG_FILES([Makefile \
547 - debian/swtpm-tools.postinst \
548 swtpm.spec \
549- etc/Makefile \
550- etc/swtpm_setup.conf \
551+ samples/Makefile \
552+ samples/swtpm-localca.conf \
553diff --git a/debian/patches/openssl-not-certtool.patch b/debian/patches/openssl-not-certtool.patch
554index 77eb269..0e2c975 100644
555--- a/debian/patches/openssl-not-certtool.patch
556+++ b/debian/patches/openssl-not-certtool.patch
557@@ -14,7 +14,7 @@ Last-Update: 2021-11-05
558
559 --- a/configure.ac
560 +++ b/configure.ac
561-@@ -310,6 +310,11 @@ if test "x$with_gnutls" != "xno"; then
562+@@ -313,6 +313,11 @@
563 AC_MSG_RESULT([yes])
564 fi
565
566@@ -26,9 +26,9 @@ Last-Update: 2021-11-05
567 if test "x$with_gnutls" != "xno"; then
568 ORIG_CFLAGS="$CFLAGS"
569 GNUTLS_CFLAGS=$(pkg-config gnutls --cflags)
570---- a/man/man8/swtpm-localca.pod
571-+++ b/man/man8/swtpm-localca.pod
572-@@ -28,12 +28,6 @@ swtpm-localca-rootca-cert.pem respective
573+--- a/man/man8/swtpm_localca.pod
574++++ b/man/man8/swtpm_localca.pod
575+@@ -28,12 +28,6 @@
576 SWTPM_ROOTCA_PASSWORD can be set for the password of the root CA's
577 private key.
578
579@@ -41,9 +41,9 @@ Last-Update: 2021-11-05
580 The following options are supported:
581
582 =over 4
583---- a/samples/swtpm_localca.c
584-+++ b/samples/swtpm_localca.c
585-@@ -39,11 +39,7 @@ gchar *gl_LOGFILE = NULL;
586+--- a/src/swtpm_localca/swtpm_localca.c
587++++ b/src/swtpm_localca/swtpm_localca.c
588+@@ -39,11 +39,7 @@
589 #define LOCALCA_OPTIONS "swtpm-localca.options"
590 #define LOCALCA_CONFIG "swtpm-localca.conf"
591
592@@ -56,8 +56,8 @@ Last-Update: 2021-11-05
593
594 /* initialize the path of the options and config files */
595 static int init(gchar **options_file, gchar **config_file)
596-@@ -83,10 +79,10 @@ static int init(gchar **options_file, gc
597- return ret;
598+@@ -65,10 +61,10 @@
599+ return 0;
600 }
601
602 -/* Run the certtool command line prepared in cmd. Display error message
603@@ -69,7 +69,7 @@ Last-Update: 2021-11-05
604 {
605 g_autofree gchar *standard_error = NULL;
606 gint exit_status;
607-@@ -120,11 +116,12 @@ static int create_localca_cert(const gch
608+@@ -102,11 +98,12 @@
609 int lockfd;
610 int ret = 1;
611 struct stat statbuf;
612@@ -87,7 +87,7 @@ Last-Update: 2021-11-05
613
614 lockfd = lock_file(lockfile);
615 if (lockfd < 0)
616-@@ -140,25 +137,36 @@ static int create_localca_cert(const gch
617+@@ -122,25 +119,36 @@
618 g_autofree gchar *cakey = g_strjoin(G_DIR_SEPARATOR_S, directory, "swtpm-localca-rootca-privkey.pem", NULL);
619 g_autofree gchar *cacert = g_strjoin(G_DIR_SEPARATOR_S, directory, "swtpm-localca-rootca-cert.pem", NULL);
620 const gchar *swtpm_rootca_password = g_getenv("SWTPM_ROOTCA_PASSWORD");
621@@ -129,7 +129,7 @@ Last-Update: 2021-11-05
622 goto error;
623
624 if (chmod(cakey, S_IRUSR | S_IWUSR | S_IRGRP) != 0) {
625-@@ -166,32 +174,71 @@ static int create_localca_cert(const gch
626+@@ -148,32 +156,71 @@
627 goto error;
628 }
629
630@@ -151,7 +151,7 @@ Last-Update: 2021-11-05
631 - filecontent = "cn=swtpm-localca-rootca\n"
632 - "ca\n"
633 - "cert_signing_key\n"
634-- "expiration_days = 3600\n";
635+- "expiration_days = -1\n";
636 - template1_file_fd = write_to_tempfile(&template1_file,
637 - (const unsigned char *)filecontent, strlen(filecontent));
638 - if (template1_file_fd < 0)
639@@ -216,7 +216,7 @@ Last-Update: 2021-11-05
640 goto error;
641
642 g_free(cmd);
643-@@ -199,13 +246,22 @@ static int create_localca_cert(const gch
644+@@ -181,13 +228,22 @@
645 /* create the intermediate CA's key */
646 cmd = concat_arrays(NULL,
647 (gchar *[]) {
648@@ -244,14 +244,14 @@ Last-Update: 2021-11-05
649 goto error;
650
651 if (chmod(signkey, S_IRUSR | S_IWUSR | S_IRGRP) != 0) {
652-@@ -213,54 +269,67 @@ static int create_localca_cert(const gch
653+@@ -195,54 +251,67 @@
654 goto error;
655 }
656
657 - filecontent = "cn=swtpm-localca\n"
658 - "ca\n"
659 - "cert_signing_key\n"
660-- "expiration_days = 3600\n";
661+- "expiration_days = -1\n";
662 - if (swtpm_rootca_password != NULL && signkey_password != NULL)
663 - fc = g_strdup_printf("%spassword = %s\n", filecontent, swtpm_rootca_password);
664 - else
665@@ -347,7 +347,7 @@ Last-Update: 2021-11-05
666
667 --- a/tests/test_swtpm_setup_create_cert
668 +++ b/tests/test_swtpm_setup_create_cert
669-@@ -98,7 +98,7 @@ if [ ! -r "${CERTSERIAL}" ]; then
670+@@ -97,7 +97,7 @@
671 exit 1
672 fi
673
674@@ -356,9 +356,9 @@ Last-Update: 2021-11-05
675 echo "Error: Root CA's private key should be encrypted"
676 cat ${workdir}/swtpm-localca-rootca-privkey.pem
677 exit 1
678---- a/tests/test_tpm2_samples_swtpm_localca
679-+++ b/tests/test_tpm2_samples_swtpm_localca
680-@@ -75,24 +75,24 @@ do
681+--- a/tests/test_tpm2_swtpm_localca
682++++ b/tests/test_tpm2_swtpm_localca
683+@@ -75,24 +75,24 @@
684 fi
685
686 # Signing key should always be password protected
687@@ -387,7 +387,7 @@ Last-Update: 2021-11-05
688 fi
689
690 if [ ! -r "${workdir}/ek.cert" ]; then
691-@@ -133,7 +133,7 @@ do
692+@@ -133,7 +133,7 @@
693 fi
694
695 # Delete all keys to have CA re-created
696@@ -398,10 +398,10 @@ Last-Update: 2021-11-05
697 echo "Test 1: OK"
698 --- a/tests/test_tpm2_swtpm_setup_create_cert
699 +++ b/tests/test_tpm2_swtpm_setup_create_cert
700-@@ -102,6 +102,7 @@ for keysize in $(echo $keysizes); do
701+@@ -118,6 +118,7 @@
702 fi
703
704- rm -rf ${SIGNINGKEY} ${ISSUERCERT} ${CERTSERIAL}
705+ rm -rf "${SIGNINGKEY}" "${ISSUERCERT}" "${CERTSERIAL}" ${USER_CERTSDIR}/ek-*.crt
706 + rm -rf "$workdir/serial" "$workdir/index.txt"
707 done
708
709diff --git a/debian/patches/series b/debian/patches/series
710index 96cf98d..13a3a26 100644
711--- a/debian/patches/series
712+++ b/debian/patches/series
713@@ -1,3 +1,2 @@
714-0001-Install-swtpm-localca-to-the-correct-path.patch
715 no-autoconf-in-debian.patch
716 openssl-not-certtool.patch
717diff --git a/debian/rules b/debian/rules
718index 030599d..23735cf 100755
719--- a/debian/rules
720+++ b/debian/rules
721@@ -16,3 +16,9 @@ override_dh_auto_test:
722 ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
723 SWTPM_TEST_SECCOMP_OPT="--seccomp action=none" make -j4 check VERBOSE=1
724 endif
725+
726+override_dh_clean:
727+ dh_clean --exclude=man/man8/swtpm-localca.8
728+
729+override_dh_makeshlibs:
730+ dh_makeshlibs --no-scripts
731diff --git a/debian/swtpm-tools.install b/debian/swtpm-tools.install
732index 48b9c42..d0aae01 100644
733--- a/debian/swtpm-tools.install
734+++ b/debian/swtpm-tools.install
735@@ -2,17 +2,20 @@
736 /usr/bin/swtpm_cert
737 /usr/bin/swtpm_setup
738 /usr/bin/swtpm_ioctl
739+/usr/bin/swtpm_localca
740 /usr/share/man/man8/swtpm_bios.8*
741 /usr/share/man/man8/swtpm_cert.8*
742 /usr/share/man/man8/swtpm_ioctl.8*
743+/usr/share/man/man8/swtpm_localca.8*
744+/usr/share/man/man8/swtpm-create-tpmca.8*
745 /usr/share/man/man8/swtpm-localca.conf.8*
746 /usr/share/man/man8/swtpm-localca.options.8*
747 /usr/share/man/man8/swtpm-localca.8*
748 /usr/share/man/man8/swtpm_setup.8*
749 /usr/share/man/man8/swtpm_setup.conf.8*
750-/usr/share/man/man8/swtpm_setup.sh.8*
751-/usr/lib/*/swtpm/swtpm-localca
752+/usr/share/swtpm/swtpm-create-tpmca
753 /usr/share/swtpm/swtpm-create-user-config-files
754+/usr/share/swtpm/swtpm-localca
755 /etc/swtpm-localca.conf
756 /etc/swtpm-localca.options
757 /etc/swtpm_setup.conf
758diff --git a/etc/Makefile.am b/etc/Makefile.am
759deleted file mode 100644
760index 94db65b..0000000
761--- a/etc/Makefile.am
762+++ /dev/null
763@@ -1,13 +0,0 @@
764-#
765-# etc/Makefile.am
766-#
767-# For the license, see the LICENSE file in the root directory.
768-#
769-
770-swtpmsysconfdir = $(sysconfdir)
771-
772-swtpmsysconf_DATA = \
773- swtpm_setup.conf
774-
775-EXTRA_DIST= \
776- swtpm_setup.conf
777diff --git a/include/Makefile.am b/include/Makefile.am
778index 584cf4b..80c1c34 100644
779--- a/include/Makefile.am
780+++ b/include/Makefile.am
781@@ -7,7 +7,9 @@
782 SUBDIRS = swtpm
783
784 noinst_HEADERS = \
785+ compiler_dependencies.h \
786 sys_dependencies.h
787
788 EXTRA_DIST = \
789+ compiler_dependencies.h \
790 sys_dependencies.h
791diff --git a/include/compiler_dependencies.h b/include/compiler_dependencies.h
792new file mode 100644
793index 0000000..97129f1
794--- /dev/null
795+++ b/include/compiler_dependencies.h
796@@ -0,0 +1,17 @@
797+/* SPDX-License-Identifier: BSD-3-Clause */
798+/*
799+ * compiler_dependencies.h: Compiler-dependent defines etc.
800+ *
801+ * Author: Stefan Berger, stefanb@linux.ibm.com
802+ *
803+ * Copyright (c) IBM Corporation, 2021
804+ */
805+
806+#ifndef _SWTPM_COMPILER_DEPENDENCIES_H
807+#define _SWTPM_COMPILER_DEPENDENCIES_H
808+
809+#ifdef __GNUC__ /* gcc and clang */
810+# define SWTPM_ATTR_UNUSED __attribute__((unused))
811+#endif
812+
813+#endif /* _SWTPM_COMPILER_DEPENDENCIES_H */
814diff --git a/include/swtpm/tpm_ioctl.h b/include/swtpm/tpm_ioctl.h
815index 4316a1f..0093a7c 100644
816--- a/include/swtpm/tpm_ioctl.h
817+++ b/include/swtpm/tpm_ioctl.h
818@@ -8,6 +8,10 @@
819 #ifndef _TPM_IOCTL_H_
820 #define _TPM_IOCTL_H_
821
822+#if defined(__CYGWIN__)
823+# define __USE_LINUX_IOCTL_DEFS
824+#endif
825+
826 #include <stdint.h>
827 #include <sys/uio.h>
828 #include <sys/types.h>
829diff --git a/include/sys_dependencies.h b/include/sys_dependencies.h
830index dbda445..7871c08 100644
831--- a/include/sys_dependencies.h
832+++ b/include/sys_dependencies.h
833@@ -58,6 +58,14 @@
834 # define htobe32(x) OSSwapHostToBigInt32(x)
835 # define htobe64(x) OSSwapHostToBigInt64(x)
836
837+# define le16toh(x) OSSwapLittleToHostInt16(x)
838+# define le32toh(x) OSSwapLittleToHostInt32(x)
839+# define le64toh(x) OSSwapLittleToHostInt64(x)
840+
841+# define htole16(x) OSSwapHostToLittleInt16(x)
842+# define htole32(x) OSSwapHostToLittleInt32(x)
843+# define htole64(x) OSSwapHostToLittleInt64(x)
844+
845 #else
846 # include <endian.h>
847 #endif
848diff --git a/man/man8/Makefile.am b/man/man8/Makefile.am
849index 5644a46..1869b3d 100644
850--- a/man/man8/Makefile.am
851+++ b/man/man8/Makefile.am
852@@ -11,37 +11,43 @@ man8_PODS = \
853 swtpm_cert.pod \
854 swtpm_cuse.pod \
855 swtpm_ioctl.pod \
856+ swtpm_localca.pod \
857 swtpm_setup.pod \
858- swtpm_setup.conf.pod
859+ swtpm_setup.conf.pod \
860 swtpm-create-tpmca.pod \
861- swtpm-localca.pod \
862 swtpm-localca.options.pod \
863 swtpm-localca.conf.pod
864
865-man8_MANS = \
866+man8_generated_MANS = \
867 swtpm.8 \
868 swtpm_bios.8 \
869 swtpm_cert.8 \
870 swtpm_ioctl.8 \
871+ swtpm_localca.8 \
872 swtpm_setup.8 \
873 swtpm_setup.conf.8 \
874- swtpm_setup.sh.8 \
875 swtpm-create-tpmca.8 \
876- swtpm-localca.8 \
877 swtpm-localca.options.8 \
878 swtpm-localca.conf.8
879
880 if WITH_CUSE
881-man8_MANS += \
882+man8_generated_MANS += \
883 swtpm_cuse.8
884 endif
885
886+man8_static_MANS = \
887+ swtpm-localca.8
888+
889+man8_MANS = \
890+ $(man8_generated_MANS) \
891+ $(man8_static_MANS)
892+
893 %.8 : %.pod
894 @pod2man -r "swtpm" \
895 -c "" \
896 -n $(basename $@) \
897 --section=8 $< > $@
898
899-EXTRA_DIST = $(man8_MANS) $(man8_PODS)
900+EXTRA_DIST = $(man8_static_MANS) $(man8_PODS)
901
902-CLEANFILES = swtpm_cuse.8
903+CLEANFILES = $(man8_generated_MANS)
904diff --git a/man/man8/swtpm-create-tpmca.pod b/man/man8/swtpm-create-tpmca.pod
905index 13647ff..36caad6 100644
906--- a/man/man8/swtpm-create-tpmca.pod
907+++ b/man/man8/swtpm-create-tpmca.pod
908@@ -1,6 +1,6 @@
909 =head1 NAME
910
911-swtpm-create-tpmca
912+swtpm-create-tpmca - Tool to create a local CA for swtpm_localca
913
914 =head1 SYNOPSIS
915
916@@ -9,7 +9,7 @@ B<swtpm-create-tpmca [OPTIONS]>
917 =head1 DESCRIPTION
918
919 B<swtpm-create-tpmca> is a tool to create a TPM 1.2 based CA that
920-can be used by B<swtpm-localca> to sign EK and platform certificates.
921+can be used by B<swtpm_localca> to sign EK and platform certificates.
922 The CA uses a GnuTLS key to sign certificates. To do this,
923 GnuTLS talks to the TPM 1.2 using the B<tcsd> (TrouSerS) daemon.
924
925@@ -41,7 +41,7 @@ Overwrite the contents of the output directory.
926 =item B<--register>
927
928 Register the key with TCSD. For the key to be available for signing,
929-the same user that created the TPM CA has to run the swtpm-localca
930+the same user that created the TPM CA has to run the swtpm_localca tool
931 later on. If this option is not passed, the private key is written
932 into a file and can be used by others as well.
933
934@@ -109,7 +109,7 @@ Display the help screen and exit.
935 =head1 EXAMPLE
936
937 The following example creates an intermediate TPM CA and writes the keys
938-into /var/lib/swtpm-localca and the swtpm-localca configuration to
939+into /var/lib/swtpm-localca and the swtpm_localca configuration to
940 /etc/swtpm-localca.conf. It can then be used for signing certificates of
941 newly created B<swtpm> TPMs.
942
943@@ -161,7 +161,7 @@ parameter.
944
945 To test either one of the above TPM CAs, run the following command:
946
947- #> /usr/share/swtpm/swtpm-localca \
948+ #> swtpm_localca \
949 --type ek --ek x=11,y=13 \
950 --dir /tmp --vmid test --tpm2 \
951 --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \
952@@ -185,7 +185,7 @@ certificates since the TPM does not accept authenticated commands.
953
954 =head1 SEE ALSO
955
956-B<swtpm-localca>, B<swtpm-localca.conf>, B<tcsd>
957+B<swtpm_localca>, B<swtpm-localca.conf>, B<tcsd>
958
959 =head1 REPORTING BUGS
960
961diff --git a/man/man8/swtpm-localca.8 b/man/man8/swtpm-localca.8
962new file mode 100644
963index 0000000..a9d3f4b
964--- /dev/null
965+++ b/man/man8/swtpm-localca.8
966@@ -0,0 +1 @@
967+.so man8/swtpm_localca.8
968diff --git a/man/man8/swtpm-localca.conf.pod b/man/man8/swtpm-localca.conf.pod
969index a0e3ac3..10933dc 100644
970--- a/man/man8/swtpm-localca.conf.pod
971+++ b/man/man8/swtpm-localca.conf.pod
972@@ -1,11 +1,11 @@
973 =head1 NAME
974
975-swtpm-localca.conf - Configuration file for swtpm-localca
976+swtpm-localca.conf - Configuration file for swtpm_localca
977
978 =head1 DESCRIPTION
979
980 The file I</etc/swtpm-localca.conf> contains configuration variables
981-for the I<swtpm-localca> program.
982+for the I<swtpm_localca> program.
983
984 Entries may contain environment variables that will be resolved. All
985 environment variables must be formatted like this: '${varname}'.
986@@ -82,7 +82,7 @@ With a PKCS11 URI it may look like this:
987
988 =head1 SEE ALSO
989
990-B<swtpm-localca>
991+B<swtpm_localca>
992
993 =head1 REPORTING BUGS
994
995diff --git a/man/man8/swtpm-localca.options.pod b/man/man8/swtpm-localca.options.pod
996index f2f2872..ff71277 100644
997--- a/man/man8/swtpm-localca.options.pod
998+++ b/man/man8/swtpm-localca.options.pod
999@@ -1,6 +1,6 @@
1000 =head1 NAME
1001
1002-swtpm-localca.options - Options file for swtpm-localca
1003+swtpm-localca.options - Options file for swtpm_localca
1004
1005 =head1 DESCRIPTION
1006
1007@@ -23,7 +23,7 @@ An example I<swtpm-localca.options> file may look as follows:
1008
1009 =head1 SEE ALSO
1010
1011-B<swtpm-localca>
1012+B<swtpm_localca>
1013
1014 =head1 REPORTING BUGS
1015
1016diff --git a/man/man8/swtpm.pod b/man/man8/swtpm.pod
1017index b5e72f5..7879d7c 100644
1018--- a/man/man8/swtpm.pod
1019+++ b/man/man8/swtpm.pod
1020@@ -150,14 +150,23 @@ The following options are support by all interfaces:
1021
1022 =over 4
1023
1024-=item B<--tpmstate dir=E<lt>dirE<gt>[,mode=E<lt>0...E<gt>]>
1025+=item B<--tpmstate dir=E<lt>dirE<gt>[,mode=E<lt>0...E<gt>]|backend-uri=E<lt>uriE<gt>>
1026
1027 Use the given path rather than using the environment variable TPM_PATH.
1028
1029-The TPM state files will be written with the given file mode bits.
1030-This value must be given as an octal number starting with a '0'.
1031+If I<dir> is specified, the TPM state files will be written to the I<dir> with
1032+the given file I<mode> bits. This value must be given as an octal number starting with a '0'.
1033 The default value is 0640.
1034
1035+If I<backend-uri> is specified, the TPM state data will be stored to the URI.
1036+Currently I<backend-uri=dir://<path_to_dir>> and I<backend-uri=file://<path_to_dir>>
1037+are available. For 'dir://', the URI should specify the path to the directory where
1038+files are stored. If I<path_to_dir> starts with a '/' then the path is interpreted
1039+as an absolute path, otherwise it is a path relative to the current directory.
1040+For 'file://', the URI should specify a single file or block device where TPM state
1041+will be stored. A blockdevice must exist already and be big enough to store all
1042+state. (since v0.7)
1043+
1044 =item B<--tpm2>
1045
1046 Choose TPM 2 functionality; by default a TPM 1.2 is chosen.
1047@@ -290,51 +299,107 @@ may contain the following:
1048 {
1049 "type": "swtpm",
1050 "features": [
1051+ "tpm-1.2",
1052+ "tpm-2.0",
1053 "cmdarg-seccomp",
1054 "cmdarg-key-fd",
1055 "cmdarg-pwd-fd",
1056+ "cmdarg-print-states",
1057+ "nvram-backend-dir",
1058+ "nvram-backend-file",
1059 "tpm-send-command-header",
1060 "flags-opt-startup",
1061 "rsa-keysize-1024",
1062 "rsa-keysize-2048",
1063 "rsa-keysize-3072"
1064- ]
1065+ ],
1066+ "version": "0.7.0"
1067 }
1068
1069+The version field is available since v0.7.
1070+
1071 The meaning of the feature verbs is as follows:
1072
1073 =over 4
1074
1075-=item B<cmdarg-seccomp>
1076+=item B<tpm-1.2> (since v0.7)
1077+
1078+TPM 1.2 emulation is supported (libtpms is compiled with 1.2 support).
1079+
1080+=item B<tpm-2.0> (since v0.7)
1081+
1082+TPM 2 emulation is supported (libtpms is compiled with 2.0 support).
1083+
1084+(the I<--tpm2> option is supported)
1085+
1086+=item B<cmdarg-seccomp> (since v0.2)
1087
1088 The I<--seccomp> option is supported.
1089
1090-=item B<cmdarg-key-fd>
1091+=item B<cmdarg-key-fd> (since v0.2)
1092
1093 The I<--key> option supports the I<fd=> parameter.
1094
1095-=item B<cmdarg-pwd-fd>
1096+=item B<cmdarg-pwd-fd> (since v0.2)
1097
1098 The I<--key> option supports the I<pwdfd=> parameter.
1099
1100-=item B<tpm-send-command-header>
1101+=item B<cmdarg-print-states> (since v0.7)
1102+
1103+The I<--print-states> option is supported.
1104+
1105+=item B<nvram-backend-dir> (since v0.7)
1106+
1107+The I<--tpmstate> option supports the I<backend-uri=dir://...>
1108+parameter.
1109+
1110+=item B<nvram-backend-file> (since v0.7)
1111+
1112+The I<--tpmstate> option supports the I<backend-uri=file://...>
1113+parameter.
1114+
1115+=item B<tpm-send-command-header> (since v0.2)
1116
1117 The TPM 2 commands may be prefixed by a header that carries a 4-byte
1118 command, 1 byte for locality, and 4-byte TPM 2 command length indicator.
1119 The TPM 2 will respond by preprending a 4-byte response indicator and a
1120 4-byte trailer. All data is sent in big endian format.
1121
1122-=item B<flags-opt-startup>
1123+=item B<flags-opt-startup> (since v0.3)
1124
1125 The I<--flags> option supports the I<startup-...> options.
1126
1127-=item B<rsa-keysize-2048>
1128+=item B<rsa-keysize-2048> (since v0.4)
1129
1130 The TPM 2 supports the shown RSA key sizes. If none of the
1131 rsa-keysize verbs is shown then only RSA 2048 bit keys are supported.
1132
1133 =back
1134
1135+=item B<--print-states> (since v0.7)
1136+
1137+This option allows to print out the TPM 1.2 or TPM 2 state blobs
1138+that are currently stored in a storage backend. This option requires
1139+that the storage backend be specified using the I<--tpmstate> option
1140+and if TPM 2 state blobs are supposed to be shown, the I<--tpm2>
1141+option must be passed.
1142+
1143+The following shows the JSON output of this option. It indicates that
1144+the 'permall' and 'volatile' states are available.
1145+
1146+ {
1147+ "type": "swtpm",
1148+ "states": [
1149+ {
1150+ "name": "permall",
1151+ "size": 6013
1152+ }, {
1153+ "name": "volatile",
1154+ "size": 1087
1155+ }
1156+ ]
1157+ }
1158+
1159 =item B<-h|--help>
1160
1161 Display usage info.
1162diff --git a/man/man8/swtpm_cert.pod b/man/man8/swtpm_cert.pod
1163index 62df636..2fce2ef 100644
1164--- a/man/man8/swtpm_cert.pod
1165+++ b/man/man8/swtpm_cert.pod
1166@@ -157,9 +157,12 @@ The output may contain the following:
1167 "features": [
1168 "cmdarg-signkey-pwd",
1169 "cmdarg-parentkey-pwd"
1170- ]
1171+ ],
1172+ "version": "0.7.0"
1173 }
1174
1175+The version field is available since 0.7.
1176+
1177 The maining of the feature verbs is as follows:
1178
1179 =over 4
1180diff --git a/man/man8/swtpm_cuse.pod b/man/man8/swtpm_cuse.pod
1181index 8cf981d..e2d4a77 100644
1182--- a/man/man8/swtpm_cuse.pod
1183+++ b/man/man8/swtpm_cuse.pod
1184@@ -175,9 +175,12 @@ may contain the following:
1185 "features": [
1186 "cmdarg-seccomp",
1187 "cmdarg-key-fd"
1188- ]
1189+ ],
1190+ "version": "0.7.0"
1191 }
1192
1193+The version field is available since 0.7.
1194+
1195 The meaning of the feature verbs is as follows:
1196
1197 =over 4
1198diff --git a/man/man8/swtpm-localca.pod b/man/man8/swtpm_localca.pod
1199similarity index 94%
1200rename from man/man8/swtpm-localca.pod
1201rename to man/man8/swtpm_localca.pod
1202index 202908e..dffec0c 100644
1203--- a/man/man8/swtpm-localca.pod
1204+++ b/man/man8/swtpm_localca.pod
1205@@ -1,14 +1,14 @@
1206 =head1 NAME
1207
1208-swtpm-localca - Local CA to create EK and platform certs for swtpm
1209+swtpm_localca - Local CA to create EK and platform certs for swtpm
1210
1211 =head1 SYNOPSIS
1212
1213-B<swtpm-localca [OPTIONS]>
1214+B<swtpm_localca [OPTIONS]>
1215
1216 =head1 DESCRIPTION
1217
1218-B<swtpm-localca> is a tool to create TPM Endorsement Key (EK) and platform
1219+B<swtpm_localca> is a tool to create TPM Endorsement Key (EK) and platform
1220 certificates on the host. It uses the I<swtpm_cert> program to create
1221 the certificates.
1222
1223@@ -18,7 +18,7 @@ a variable needs to be set that points to this program.
1224 It implements command line options that the I<swtpm_setup>
1225 program uses to provide the necessary parameters to it.
1226
1227-B<swtpm-localca> will automatically try to create the signing key and
1228+B<swtpm_localca> will automatically try to create the signing key and
1229 certificate if the configuration points to a missing signing key.
1230 Since this certificate must be signed by a CA, a root certificate authority
1231 will also be created and will sign this certificate. The root CA's
1232diff --git a/man/man8/swtpm_setup.conf.pod b/man/man8/swtpm_setup.conf.pod
1233index a5b237b..cb97709 100644
1234--- a/man/man8/swtpm_setup.conf.pod
1235+++ b/man/man8/swtpm_setup.conf.pod
1236@@ -89,6 +89,12 @@ that will be passed to the invoked program using the --optsfile
1237 option described above. If omitted, the invoked program will use
1238 the default options file.
1239
1240+=item B<active_pcr_banks> (since v0.7)
1241+
1242+This keyword is to be followed by a comma-separated list
1243+of names of PCR banks. The list must not contain any spaces.
1244+Valid PCR bank names are sha1, sha256, sha384, and sha512.
1245+
1246 =back
1247
1248 =head1 SEE ALSO
1249diff --git a/man/man8/swtpm_setup.pod b/man/man8/swtpm_setup.pod
1250index 13e8464..636e35d 100644
1251--- a/man/man8/swtpm_setup.pod
1252+++ b/man/man8/swtpm_setup.pod
1253@@ -17,7 +17,7 @@ The following options are supported:
1254
1255 =item B<--runas <userid>>
1256
1257-Use this userid to run swtpm_setup.sh as. Only 'root' can use this option.
1258+Use this userid to run swtpm_setup as. Only 'root' can use this option.
1259
1260 =item B<--config <file>>
1261
1262@@ -34,8 +34,8 @@ will be used.
1263
1264 =item B<--tpm-state <dir>> or B<--tpmstate <dir>>
1265
1266-Path to a directory where the TPM's state will be written into;
1267-this is a mandatory argument
1268+Path where the TPM's state will be written to; this is a mandatory argument.
1269+Prefix with dir:// to use directory backend, or file:// to use linear file.
1270
1271 =item B<--tpm <path to executable>>
1272
1273@@ -164,8 +164,12 @@ used for creating the certificates and may be required by that tool.
1274 =item B<--pcr-banks <PCR banks>>
1275
1276 Optional comma-separated list of PCR banks to activate. Providing '-'
1277-allows a user to skip the selection and activates all PCR banks. By default
1278-the sha1 and sha256 banks are activated.
1279+allows a user to skip the selection and activates all PCR banks.
1280+If this option is not provided, the I<swtpm_setup.conf> configuration
1281+file will be consulted for the active_pcr_banks entry. If no such
1282+entry is found then the default set of PCR banks will be activated.
1283+The default set of PCR banks can be determined using the I<--help>
1284+option.
1285
1286 =item B<--swtpm_ioctl <executable>>
1287
1288@@ -184,6 +188,11 @@ the I<--print-capabilities> option. The default size is 2048 bits for
1289 both TPM 1.2 and TPM 2. If 'max' is passed, the largest possible key
1290 size is used.
1291
1292+=item B<--reconfigure> (since v0.7)
1293+
1294+This option allows the reconfiguration of the active PCR banks of a
1295+TPM 2 using the I<--pcr-banks> option.
1296+
1297 =item B<--print-capabilities> (since v0.2)
1298
1299 Print capabilities that were added to swtpm_setup after version 0.1.
1300@@ -194,37 +203,114 @@ The output may contain the following:
1301 "features": [
1302 "cmdarg-keyfile-fd",
1303 "cmdarg-pwdfile-fd",
1304+ "cmdarg-write-ek-cert-files",
1305+ "cmdarg-create-config-files",
1306+ "cmdarg-reconfigure-pcr-banks",
1307 "tpm2-rsa-keysize-2048",
1308 "tpm2-rsa-keysize-3072",
1309- "tpm12-not-need-root"
1310- ]
1311+ "tpm12-not-need-root",
1312+ "tpm-1.2",
1313+ "tpm-2.0"
1314+ ],
1315+ "version": "0.7.0"
1316 }
1317
1318+The version field is available since v0.7.
1319+
1320 The meaning of the feature verbs is as follows:
1321
1322 =over 4
1323
1324-=item B<cmdarg-key-fd>
1325+=item B<cmdarg-key-fd> (since v0.2)
1326
1327 The I<--keyfile-fd> option is supported.
1328
1329-=item B<cmdarg-pwd-fd>
1330+=item B<cmdarg-pwd-fd> (since v0.2)
1331
1332 The I<--pwdfile-fd> option is supported.
1333
1334-=item B<tpm2-rsa-keysize-2048, ...>
1335+=item B<cmdarg-write-ek-cert-files> (since v0.7)
1336+
1337+The I<--write-ek-cert-files> option is supported.
1338+
1339+=item B<cmdarg-create-config-files> (since v0.7)
1340+
1341+The I<--create-config-files> option is supported.
1342+
1343+=item B<cmdarg-reconfigure-pcr-banks> (since v0.7)
1344+
1345+The I<--reconfigure> option is supported and allows the reconfiguration of
1346+the active PCR banks.
1347+
1348+=item B<tpm2-rsa-keysize-2048, ...> (since v0.4)
1349
1350 The shown RSA key sizes are supported for a TPM 2's EK key. If none of the
1351 tpm2-rsa-keysize verbs is shown then only RSA 2048 bit keys are supported.
1352
1353-=item B<tpm12-not-need-root> (since 0.4.0)
1354+=item B<tpm12-not-need-root> (since v0.4)
1355
1356 This option implies that any user can setup a TPM 1.2. Previously only root
1357 or the 'tss' user, depending on configuration and availability of this account,
1358 could do that.
1359
1360+=item B<tpm-1.2> (since v0.7)
1361+
1362+TPM 1.2 setup is supported (libtpms is compiled with TPM 1.2 support).
1363+
1364+=item B<tpm-2.0> (since v0.7)
1365+
1366+TPM 2 setup is supported (libtpms is compiled with TPM 2 support).
1367+
1368 =back
1369
1370+=item B<--write-ek-cert-files <directory>> (since v0.7)
1371+
1372+This option causes endorsement key (EK) files to be written into the provided
1373+directory. The files contain the DER-formatted EKs that were written into the
1374+NVRAM locations of the TPM 1.2 or TPM 2. The EK files have the filename pattern
1375+of ek-<key type>.crt. Example for filenames are ek-rsa2048.crt, ek-rsa3072.crt,
1376+and ek-secp384r1.crt.
1377+
1378+The keys that are written for a TPM 2 may change over time as the default
1379+strength of the EK keys changes. This means that one should look for all
1380+files with the above filename pattern when looking for the EKs.
1381+
1382+=item B<--create-config-files [[overwrite][,root][,skip-if-exist]]> (since v0.7)
1383+
1384+This option allows a user to create configuration files for swtpm_setup and
1385+swtpm-localca under the $XDG_CONFIG_HOME or $HOME/.config directories.
1386+
1387+The configuration files will not be created if any one of them already
1388+exists and in this case the program will report the first file it finds
1389+and exit with an error code.
1390+
1391+The meaning of the options is as follows:
1392+
1393+=over 4
1394+
1395+=item B<overwrite>
1396+
1397+Overwrite any existing configuration files.
1398+
1399+=item B<root>
1400+
1401+Create the configuration files even under the root account. These
1402+configuration files may then shadow any other existing configuration files,
1403+such as /etc/swtpm-localca.conf for example.
1404+
1405+=item B<skip-if-exist>
1406+
1407+Do nothing if any one of the configuration files that would be created already
1408+exists. The program will exit without error code.
1409+
1410+=back
1411+
1412+Note: The case when a user is part of the group that is allowed to access
1413+the default configuration files' paths is currently not handled. On many
1414+systems this may be the case when a user is part of the 'tss' group. In
1415+this case it is recommended that the user replace the swtpm-localca.conf
1416+created with this command with a symbolic link to /etc/swtpm-localca.conf.
1417+
1418 =item B<--help, -h>
1419
1420 Display the help screen
1421@@ -241,7 +327,7 @@ To simulate manufacturing of a TPM, one would typically run the following comman
1422 Note: since v0.4 TPM 1.2 setup does not require root rights anymore.
1423
1424 Any user can also simulate the manufacturing of a TPM using the
1425-swtpm-localca plugin. The following example assumes that the user has
1426+swtpm_localca utility. The following example assumes that the user has
1427 set the environment variable XDG_CONFIG_HOME as follows (using bash for
1428 example):
1429
1430diff --git a/man/man8/swtpm_setup.sh.8 b/man/man8/swtpm_setup.sh.8
1431deleted file mode 100644
1432index 7574f18..0000000
1433--- a/man/man8/swtpm_setup.sh.8
1434+++ /dev/null
1435@@ -1 +0,0 @@
1436-.so man8/swtpm_setup.8
1437diff --git a/samples/Makefile.am b/samples/Makefile.am
1438index dcbc9b6..383c395 100644
1439--- a/samples/Makefile.am
1440+++ b/samples/Makefile.am
1441@@ -6,47 +6,20 @@
1442
1443 samplesconfdir = $(datadir)/@PACKAGE@
1444 samplessysconfdir = $(sysconfdir)
1445-# swtpm-localca was always installed in /usr/samples/swtpm-localca
1446-bindir = $(samplesconfdir)
1447
1448 samplesconf_SCRIPTS = \
1449 swtpm-create-tpmca \
1450- swtpm-create-user-config-files
1451+ swtpm-create-user-config-files \
1452+ swtpm-localca
1453
1454 samplessysconf_DATA = \
1455 swtpm-localca.conf \
1456- swtpm-localca.options
1457-
1458-noinst_HEADERS = \
1459- swtpm_localca.h \
1460- swtpm_localca_utils.h
1461-
1462-bin_PROGRAMS = \
1463- swtpm-localca
1464+ swtpm-localca.options \
1465+ swtpm_setup.conf
1466
1467 $(top_builddir)/src/utils/libswtpm_utils.la:
1468 $(MAKE) -C$(dir $@)
1469
1470-swtpm_localca_DEPENDENCIES = \
1471- $(top_builddir)/src/utils/libswtpm_utils.la
1472-
1473-swtpm_localca_SOURCES = \
1474- swtpm_localca.c \
1475- swtpm_localca_utils.c
1476-
1477-swtpm_localca_LDADD = \
1478- $(top_builddir)/src/utils/libswtpm_utils.la
1479-
1480-swtpm_localca_LDFLAGS = \
1481- -L$(top_builddir)/src/utils -lswtpm_utils \
1482- $(HARDENING_LDFLAGS) \
1483- $(GLIB_LIBS)
1484-
1485-swtpm_localca_CFLAGS = \
1486- -I$(top_srcdir)/src/utils \
1487- $(HARDENING_CFLAGS) \
1488- $(GLIB_CFLAGS)
1489-
1490 install-data-local:
1491 $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/swtpm-localca
1492 if test -z $(DESTDIR); then \
1493@@ -58,4 +31,5 @@ EXTRA_DIST= \
1494 swtpm-create-tpmca \
1495 swtpm-create-user-config-files \
1496 swtpm-localca.conf \
1497- swtpm-localca.options
1498+ swtpm-localca.options \
1499+ swtpm_setup.conf
1500diff --git a/samples/swtpm-create-user-config-files.in b/samples/swtpm-create-user-config-files.in
1501index b86a4b7..f38f45c 100755
1502--- a/samples/swtpm-create-user-config-files.in
1503+++ b/samples/swtpm-create-user-config-files.in
1504@@ -1,19 +1,5 @@
1505 #!/usr/bin/env bash
1506
1507-if [ -z "${XDG_CONFIG_HOME}" ]; then
1508- echo "Environment variable XDG_CONFIG_HOME is not set. Using \${HOME}/.config."
1509- XDG_CONFIG_HOME="${HOME}/.config"
1510-fi
1511-
1512-SWTPM_LOCALCA_DIR="${XDG_CONFIG_HOME}/var/lib/swtpm-localca"
1513-
1514-SWTPM_SETUP_CONF="${XDG_CONFIG_HOME}/swtpm_setup.conf"
1515-SWTPM_LOCALCA_CONF="${XDG_CONFIG_HOME}/swtpm-localca.conf"
1516-SWTPM_LOCALCA_OPTIONS="${XDG_CONFIG_HOME}/swtpm-localca.options"
1517-
1518-FLAG_OVERWRITE=1
1519-FLAG_ROOT=2
1520-
1521 function help() {
1522 cat <<_EOF_
1523 Usage: $1 [options]
1524@@ -30,62 +16,23 @@ _EOF_
1525 }
1526
1527 function main() {
1528- local flags=0
1529+ local flags=""
1530
1531 while [ $# -ne 0 ]; do
1532 case "$1" in
1533- --overwrite) flags=$((flags | FLAG_OVERWRITE));;
1534- --root) flags=$((flags | FLAG_ROOT));;
1535+ --overwrite) flags="${flags},overwrite";;
1536+ --root) flags="${flags},root";;
1537+ --skip-if-exist) flags="${flags},skip-if-exist";;
1538 --help|-h|-?) help $0; exit 0;;
1539 *) echo -e "Unknown option $1\n" >&2; help $0; exit 1;;
1540 esac
1541 shift
1542 done
1543
1544- if [ "$(id -u)" = "0" ]; then
1545- if [[ $((flags & FLAG_ROOT)) -eq 0 ]]; then
1546- echo "Requiring the --root flag since the configuration files will shadow"
1547- echo "those in @SYSCONFDIR@."
1548- exit 1
1549- fi
1550- fi
1551-
1552- if [[ $((flags & FLAG_OVERWRITE)) -eq 0 ]]; then
1553- for f in "${SWTPM_SETUP_CONF}" \
1554- "${SWTPM_LOCALCA_CONF}" \
1555- "${SWTPM_LOCALCA_OPTIONS}"; do
1556- if [ -f "${f}" ]; then
1557- echo "File ${f} already exists. Refusing to overwrite." >&2
1558- exit 1
1559- fi
1560- done
1561- fi
1562-
1563- mkdir -p "${SWTPM_LOCALCA_DIR}"
1564-
1565- echo "Writing ${SWTPM_SETUP_CONF}."
1566- cat <<_EOF_ > "${SWTPM_SETUP_CONF}"
1567-create_certs_tool = @DATAROOTDIR@/swtpm/swtpm-localca
1568-create_certs_tool_config = ${SWTPM_LOCALCA_CONF}
1569-create_certs_tool_options = ${SWTPM_LOCALCA_OPTIONS}
1570-_EOF_
1571-
1572- echo "Writing ${SWTPM_LOCALCA_CONF}."
1573- cat <<_EOF_ > "${SWTPM_LOCALCA_CONF}"
1574-statedir = ${SWTPM_LOCALCA_DIR}
1575-signingkey = ${SWTPM_LOCALCA_DIR}/signkey.pem
1576-issuercert = ${SWTPM_LOCALCA_DIR}/issuercert.pem
1577-certserial = ${SWTPM_LOCALCA_DIR}/certserial
1578-_EOF_
1579-
1580- echo "Writing ${SWTPM_LOCALCA_OPTIONS}."
1581- cat <<_EOF_ > "${SWTPM_LOCALCA_OPTIONS}"
1582---platform-manufacturer $(uname -s | tr " " "_")
1583---platform-version $(uname -r | tr " " "_")
1584---platform-model $(uname -s | tr " " "_")
1585-_EOF_
1586+ [ "${flags:0:1}" = "," ] && flags=${flags:1}
1587
1588- exit 0
1589+ @BINDIR@/swtpm_setup --create-config-files ${flags}
1590+ exit $?
1591 }
1592
1593 main "$@"
1594diff --git a/samples/swtpm-localca.in b/samples/swtpm-localca.in
1595new file mode 100755
1596index 0000000..ee90695
1597--- /dev/null
1598+++ b/samples/swtpm-localca.in
1599@@ -0,0 +1,5 @@
1600+#!/usr/bin/env sh
1601+
1602+@BINDIR@/swtpm_localca "$@"
1603+
1604+exit $?
1605diff --git a/etc/swtpm_setup.conf.in b/samples/swtpm_setup.conf.in
1606similarity index 60%
1607rename from etc/swtpm_setup.conf.in
1608rename to samples/swtpm_setup.conf.in
1609index 68d7e6f..3ae77e4 100644
1610--- a/etc/swtpm_setup.conf.in
1611+++ b/samples/swtpm_setup.conf.in
1612@@ -1,4 +1,6 @@
1613 # Program invoked for creating certificates
1614-create_certs_tool= @DATAROOTDIR@/swtpm/swtpm-localca
1615+create_certs_tool= @BINDIR@/swtpm_localca
1616 create_certs_tool_config = @SYSCONFDIR@/swtpm-localca.conf
1617 create_certs_tool_options = @SYSCONFDIR@/swtpm-localca.options
1618+# Comma-separated list (no spaces) of PCR banks to activate by default
1619+active_pcr_banks = @DEFAULT_PCR_BANKS@
1620diff --git a/src/Makefile.am b/src/Makefile.am
1621index dba32c8..9e03c78 100644
1622--- a/src/Makefile.am
1623+++ b/src/Makefile.am
1624@@ -10,6 +10,7 @@ SUBDIRS = \
1625 swtpm_bios \
1626 swtpm_cert \
1627 swtpm_ioctl \
1628+ swtpm_localca \
1629 swtpm_setup
1630
1631 if WITH_SELINUX
1632diff --git a/src/selinux/Makefile.am b/src/selinux/Makefile.am
1633index 7c1f63c..4bf1d8d 100644
1634--- a/src/selinux/Makefile.am
1635+++ b/src/selinux/Makefile.am
1636@@ -71,7 +71,7 @@ selinux-uninstall:
1637 cp $^ ./ 2>/dev/null || true
1638 make -f /usr/share/selinux/devel/Makefile $@
1639 $(RM) -r ./tmp/
1640- if test $(shell pwd) != $(abspath $(top_srcdir)/src/selinux); then \
1641+ if test $(abspath $(shell pwd)) != $(abspath $(top_srcdir)/src/selinux); then \
1642 $(RM) *.te *.fc *.if; \
1643 fi
1644
1645diff --git a/src/swtpm/Makefile.am b/src/swtpm/Makefile.am
1646index 8f6c6d8..5454a6f 100644
1647--- a/src/swtpm/Makefile.am
1648+++ b/src/swtpm/Makefile.am
1649@@ -17,14 +17,15 @@ noinst_HEADERS = \
1650 main.h \
1651 mainloop.h \
1652 options.h \
1653- osx.h \
1654+ daemonize.h \
1655 pidfile.h \
1656 seccomp_profile.h \
1657 server.h \
1658 swtpm_aes.h \
1659 swtpm_debug.h \
1660 swtpm_io.h \
1661- swtpm_nvfile.h \
1662+ swtpm_nvstore.h \
1663+ swtpm_nvstore_linear.h \
1664 threadpool.h \
1665 tlv.h \
1666 tpmlib.h \
1667@@ -49,7 +50,10 @@ libswtpm_libtpms_la_SOURCES = \
1668 swtpm_aes.c \
1669 swtpm_debug.c \
1670 swtpm_io.c \
1671- swtpm_nvfile.c \
1672+ swtpm_nvstore.c \
1673+ swtpm_nvstore_dir.c \
1674+ swtpm_nvstore_linear.c \
1675+ swtpm_nvstore_linear_file.c \
1676 tlv.c \
1677 tpmlib.c \
1678 tpmstate.c \
1679@@ -64,12 +68,12 @@ libswtpm_libtpms_la_CFLAGS = \
1680 -I$(top_builddir)/include \
1681 -I$(top_srcdir)/include \
1682 -I$(top_srcdir)/include/swtpm \
1683+ -I$(top_srcdir)/src/utils \
1684 $(MY_CFLAGS) \
1685 $(CFLAGS) \
1686 $(HARDENING_CFLAGS) \
1687 $(GLIB_CFLAGS) \
1688- $(LIBSECCOMP_CFLAGS) \
1689- $(LIBCRYPTO_EXTRA_CFLAGS)
1690+ $(LIBSECCOMP_CFLAGS)
1691
1692 libswtpm_libtpms_la_LDFLAGS = \
1693 $(MY_LDFLAGS) \
1694@@ -91,7 +95,7 @@ swtpm_DEPENDENCIES = $(privlib_LTLIBRARIES)
1695
1696 swtpm_SOURCES = \
1697 main.c \
1698- osx.c \
1699+ daemonize.c \
1700 swtpm.c \
1701 swtpm_chardev.c
1702 if WITH_CUSE
1703@@ -102,6 +106,7 @@ swtpm_CFLAGS = \
1704 -I$(top_builddir)/include \
1705 -I$(top_srcdir)/include \
1706 -I$(top_srcdir)/include/swtpm \
1707+ -I$(top_srcdir)/src/utils \
1708 $(MY_CFLAGS) \
1709 $(HARDENING_CFLAGS) \
1710 $(GLIB_CFLAGS) \
1711@@ -126,7 +131,9 @@ swtpm_cuse_SOURCES = \
1712
1713 swtpm_cuse_CFLAGS = \
1714 -I$(top_builddir)/include \
1715+ -I$(top_srcdir)/include \
1716 -I$(top_srcdir)/include/swtpm \
1717+ -I$(top_srcdir)/src/utils \
1718 $(MY_CFLAGS) \
1719 $(GLIB_CFLAGS) \
1720 $(LIBFUSE_CFLAGS) \
1721diff --git a/src/swtpm/capabilities.c b/src/swtpm/capabilities.c
1722index c6e358f..c528a8c 100644
1723--- a/src/swtpm/capabilities.c
1724+++ b/src/swtpm/capabilities.c
1725@@ -43,9 +43,11 @@
1726 #include <string.h>
1727
1728 #include <libtpms/tpm_library.h>
1729+#include <libtpms/tpm_error.h>
1730
1731 #include "capabilities.h"
1732 #include "logging.h"
1733+#include "swtpm_nvstore.h"
1734
1735 /* Convert the RSA key size indicators supported by libtpms into capability
1736 * strings.
1737@@ -68,7 +70,7 @@ static int get_rsa_keysize_caps(char **keysizecaps)
1738 int n;
1739
1740 if (!info_data)
1741- goto oom;
1742+ goto cleanup;
1743
1744 start = strstr(info_data, needle);
1745 if (start) {
1746@@ -122,24 +124,39 @@ int capabilities_print_json(bool cusetpm)
1747 #else
1748 const char *cmdarg_seccomp = "";
1749 #endif
1750+ const char *with_tpm1 = "";
1751+ const char *with_tpm2 = "";
1752 char *keysizecaps = NULL;
1753+ const char *nvram_backend_dir = "\"nvram-backend-dir\", ";
1754+ const char *nvram_backend_file = "\"nvram-backend-file\"";
1755
1756 ret = get_rsa_keysize_caps(&keysizecaps);
1757 if (ret < 0)
1758 goto cleanup;
1759
1760+ if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_1_2) == TPM_SUCCESS)
1761+ with_tpm1 = "\"tpm-1.2\", ";
1762+ if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2) == TPM_SUCCESS)
1763+ with_tpm2 = "\"tpm-2.0\", ";
1764+
1765 n = asprintf(&string,
1766 "{ "
1767 "\"type\": \"swtpm\", "
1768 "\"features\": [ "
1769- "%s%s%s%s%s%s"
1770- " ] "
1771+ "%s%s%s%s%s%s%s%s%s%s%s"
1772+ " ], "
1773+ "\"version\": \"" VERSION "\" "
1774 "}",
1775+ with_tpm1,
1776+ with_tpm2,
1777 !cusetpm ? "\"tpm-send-command-header\", ": "",
1778 !cusetpm ? "\"flags-opt-startup\", " : "",
1779 cmdarg_seccomp,
1780 true ? "\"cmdarg-key-fd\", " : "",
1781- true ? "\"cmdarg-pwd-fd\"" : "",
1782+ true ? "\"cmdarg-pwd-fd\", " : "",
1783+ true ? "\"cmdarg-print-states\", " : "",
1784+ nvram_backend_dir,
1785+ nvram_backend_file,
1786 keysizecaps ? keysizecaps : ""
1787 );
1788
1789diff --git a/src/swtpm/common.c b/src/swtpm/common.c
1790index fcbf2c9..722ff65 100644
1791--- a/src/swtpm/common.c
1792+++ b/src/swtpm/common.c
1793@@ -37,6 +37,7 @@
1794
1795 #include "config.h"
1796
1797+#define _GNU_SOURCE
1798 #include <stdio.h>
1799 #include <string.h>
1800 #include <errno.h>
1801@@ -62,7 +63,7 @@
1802 #include "key.h"
1803 #include "locality.h"
1804 #include "logging.h"
1805-#include "swtpm_nvfile.h"
1806+#include "swtpm_nvstore.h"
1807 #include "pidfile.h"
1808 #include "tpmstate.h"
1809 #include "ctrlchannel.h"
1810@@ -144,6 +145,10 @@ static const OptionDesc tpmstate_opt_desc[] = {
1811 .name = "mode",
1812 .type = OPT_TYPE_MODE_T,
1813 },
1814+ {
1815+ .name = "backend-uri",
1816+ .type = OPT_TYPE_STRING,
1817+ },
1818 END_OPTION_DESC
1819 };
1820
1821@@ -618,15 +623,18 @@ handle_pid_options(char *options)
1822 * @options: the 'pid' options to parse
1823 * @tpmstatedir: Point to pointer for tpmstatedir
1824 * @mode: the mode of the TPM's state files
1825+ * @tpmbackend_uri: Point to pointer for backend URI
1826 *
1827 * Returns 0 on success, -1 on failure.
1828 */
1829 static int
1830-parse_tpmstate_options(char *options, char **tpmstatedir, mode_t *mode)
1831+parse_tpmstate_options(char *options, char **tpmstatedir, mode_t *mode,
1832+ char **tpmbackend_uri)
1833 {
1834 OptionValues *ovs = NULL;
1835 char *error = NULL;
1836 const char *directory = NULL;
1837+ const char *backend_uri = NULL;
1838
1839 ovs = options_parse(options, tpmstate_opt_desc, &error);
1840 if (!ovs) {
1841@@ -636,16 +644,25 @@ parse_tpmstate_options(char *options, char **tpmstatedir, mode_t *mode)
1842 }
1843
1844 directory = option_get_string(ovs, "dir", NULL);
1845- if (!directory) {
1846- logprintf(STDERR_FILENO,
1847- "The file parameter is required for the tpmstate option.\n");
1848- goto error;
1849- }
1850 *mode = option_get_mode_t(ovs, "mode", 0640);
1851+ backend_uri = option_get_string(ovs, "backend-uri", NULL);
1852
1853- *tpmstatedir = strdup(directory);
1854- if (!*tpmstatedir) {
1855- logprintf(STDERR_FILENO, "Out of memory.");
1856+ if (directory) {
1857+ *tpmstatedir = strdup(directory);
1858+ if (!*tpmstatedir) {
1859+ logprintf(STDERR_FILENO, "Out of memory.");
1860+ goto error;
1861+ }
1862+ } else if (backend_uri) {
1863+ *tpmbackend_uri = strdup(backend_uri);
1864+ if (!*tpmbackend_uri) {
1865+ logprintf(STDERR_FILENO, "Out of memory.");
1866+ goto error;
1867+ }
1868+ } else {
1869+ logprintf(STDERR_FILENO,
1870+ "The dir or backend-uri parameters is required "
1871+ "for the tpmstate option.\n");
1872 goto error;
1873 }
1874
1875@@ -672,20 +689,52 @@ int
1876 handle_tpmstate_options(char *options)
1877 {
1878 char *tpmstatedir = NULL;
1879+ char *tpmbackend_uri = NULL;
1880+ char *temp_uri = NULL;
1881 int ret = 0;
1882 mode_t mode;
1883
1884 if (!options)
1885 return 0;
1886
1887- if (parse_tpmstate_options(options, &tpmstatedir, &mode) < 0)
1888- return -1;
1889-
1890- if (tpmstate_set_dir(tpmstatedir) < 0 ||
1891- tpmstate_set_mode(mode) < 0)
1892+ if (parse_tpmstate_options(options, &tpmstatedir, &mode,
1893+ &tpmbackend_uri) < 0) {
1894 ret = -1;
1895+ goto error;
1896+ }
1897+
1898+ if (tpmstatedir) {
1899+ /* Default tpmstate store dir backend */
1900+ if (asprintf(&temp_uri, "dir://%s", tpmstatedir) < 0) {
1901+ logprintf(STDERR_FILENO,
1902+ "Could not asprintf TPM backend uri\n");
1903+ ret = -1;
1904+ temp_uri = NULL;
1905+ goto error;
1906+ }
1907+
1908+ if (tpmstate_set_backend_uri(temp_uri) < 0 ||
1909+ tpmstate_set_mode(mode) < 0) {
1910+ ret = -1;
1911+ goto error;
1912+ }
1913+ } else {
1914+ if (tpmstate_set_backend_uri(tpmbackend_uri) < 0) {
1915+ ret = -1;
1916+ goto error;
1917+ }
1918+ if ((strncmp(tpmbackend_uri, "dir://", 6) == 0 ||
1919+ strncmp(tpmbackend_uri, "file://", 7)) &&
1920+ tpmstate_set_mode(mode) < 0) {
1921+ ret = -1;
1922+ goto error;
1923+ }
1924+ }
1925
1926+error:
1927 free(tpmstatedir);
1928+ free(tpmbackend_uri);
1929+ free(temp_uri);
1930
1931 return ret;
1932 }
1933@@ -1310,4 +1359,4 @@ int handle_seccomp_options(char *options, unsigned int *seccomp_action)
1934
1935 return 0;
1936 }
1937-#endif /* WITH_SECCOMP */
1938\ No newline at end of file
1939+#endif /* WITH_SECCOMP */
1940diff --git a/src/swtpm/common.h b/src/swtpm/common.h
1941index e1c20a3..f284028 100644
1942--- a/src/swtpm/common.h
1943+++ b/src/swtpm/common.h
1944@@ -41,6 +41,8 @@
1945
1946 #include <stdbool.h>
1947
1948+#include "compiler_dependencies.h"
1949+
1950 int handle_log_options(char *options);
1951 int handle_key_options(char *options);
1952 int handle_migration_key_options(char *options);
1953@@ -56,8 +58,8 @@ int handle_flags_options(char *options, bool *need_init_cmd,
1954 #ifdef WITH_SECCOMP
1955 int handle_seccomp_options(char *options, unsigned int *seccomp_action);
1956 #else
1957-static inline int handle_seccomp_options(char *options,
1958- unsigned int *seccomp_action)
1959+static inline int handle_seccomp_options(char *options SWTPM_ATTR_UNUSED,
1960+ unsigned int *seccomp_action SWTPM_ATTR_UNUSED)
1961 {
1962 return 0;
1963 }
1964diff --git a/src/swtpm/ctrlchannel.c b/src/swtpm/ctrlchannel.c
1965index 1f26233..d50c6f3 100644
1966--- a/src/swtpm/ctrlchannel.c
1967+++ b/src/swtpm/ctrlchannel.c
1968@@ -56,11 +56,12 @@
1969 #include "logging.h"
1970 #include "tpm_ioctl.h"
1971 #include "tpmlib.h"
1972-#include "swtpm_nvfile.h"
1973+#include "swtpm_nvstore.h"
1974 #include "locality.h"
1975 #include "mainloop.h"
1976 #include "utils.h"
1977 #include "swtpm_debug.h"
1978+#include "swtpm_utils.h"
1979
1980 /* local variables */
1981
1982@@ -790,8 +791,7 @@ int ctrlchannel_process_fd(int fd,
1983 goto err_bad_input;
1984 }
1985
1986- mlp->flags = MAIN_LOOP_FLAG_USE_FD | MAIN_LOOP_FLAG_KEEP_CONNECTION |
1987- MAIN_LOOP_FLAG_END_ON_HUP;
1988+ mlp->flags |= MAIN_LOOP_FLAG_USE_FD | MAIN_LOOP_FLAG_KEEP_CONNECTION;
1989 mlp->fd = *data_fd;
1990
1991 *res_p = htobe32(TPM_SUCCESS);
1992diff --git a/src/swtpm/cuse_tpm.c b/src/swtpm/cuse_tpm.c
1993index fbf4d86..d577d88 100644
1994--- a/src/swtpm/cuse_tpm.c
1995+++ b/src/swtpm/cuse_tpm.c
1996@@ -70,7 +70,7 @@
1997 #include "locality.h"
1998 #include "logging.h"
1999 #include "tpm_ioctl.h"
2000-#include "swtpm_nvfile.h"
2001+#include "swtpm_nvstore.h"
2002 #include "tpmlib.h"
2003 #include "main.h"
2004 #include "utils.h"
2005@@ -78,6 +78,7 @@
2006 #include "seccomp_profile.h"
2007 #include "options.h"
2008 #include "capabilities.h"
2009+#include "swtpm_utils.h"
2010
2011 /* maximum size of request buffer */
2012 #define TPM_REQ_MAX 4096
2013@@ -218,10 +219,10 @@ static const char *usage =
2014 " the log file can be reset (truncate)\n"
2015 "--pid file=<path>|fd=<filedescriptor>\n"
2016 " : write the process ID into the given file\n"
2017-"--tpmstate dir=<dir>[,mode=0...]\n"
2018-" : set the directory where the TPM's state will be written\n"
2019+"--tpmstate dir=<dir>[,mode=0...]|backend-uri=<uri>\n"
2020+" : set the directory or uri where the TPM's state will be written\n"
2021 " into; the TPM_PATH environment variable can be used\n"
2022-" instead;\n"
2023+" instead of dir option;\n"
2024 " mode allows a user to set the file mode bits of the state\n"
2025 " files; the default mode is 0640;\n"
2026 "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none]\n"
2027@@ -241,11 +242,13 @@ static const char *usage =
2028 " blacklisted syscall is executed; default is kill\n"
2029 #endif
2030 "--print-capabilites : print capabilities and terminate\n"
2031+"--print-states : print existing TPM states and terminate\n"
2032 "-h|--help : display this help screen and terminate\n"
2033 "\n";
2034
2035 static TPM_RESULT
2036-ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum)
2037+ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc,
2038+ uint32_t tpmnum SWTPM_ATTR_UNUSED)
2039 {
2040 *loc = locality;
2041 return TPM_SUCCESS;
2042@@ -396,7 +399,7 @@ static int cached_stateblob_copy(void *dest, size_t destlen,
2043 /*
2044 * worker_thread: the worker thread
2045 */
2046-static void worker_thread(gpointer data, gpointer user_data)
2047+static void worker_thread(gpointer data, gpointer user_data SWTPM_ATTR_UNUSED)
2048 {
2049 struct thread_message *msg = (struct thread_message *)data;
2050
2051@@ -431,7 +434,8 @@ static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion,
2052 TPM_RESULT *res)
2053 {
2054 DIR *dir;
2055- const char *tpmdir = tpmstate_get_dir();
2056+ const char *uri = tpmstate_get_backend_uri();
2057+ const char *tpmdir = uri + strlen("dir://");
2058
2059 *res = TPM_FAIL;
2060
2061@@ -499,7 +503,8 @@ static void ptm_write_fatal_error_response(TPMLIB_TPMVersion l_tpmversion)
2062 /*
2063 * ptm_send_startup: Send a TPM/TPM2_Startup
2064 */
2065-static int ptm_send_startup(uint16_t startupType, TPMLIB_TPMVersion l_tpmversion)
2066+static int ptm_send_startup(uint16_t startupType,
2067+ TPMLIB_TPMVersion l_tpmversion SWTPM_ATTR_UNUSED)
2068 {
2069 uint32_t command_length;
2070 unsigned char command[sizeof(struct tpm_startup)];
2071@@ -597,8 +602,8 @@ static void ptm_read_stateblob(fuse_req_t req, size_t size)
2072 * Depending on the current state of the transfer interface (read/write)
2073 * return either the results of TPM commands or a data of a TPM state blob.
2074 */
2075-static void ptm_read(fuse_req_t req, size_t size, off_t off,
2076- struct fuse_file_info *fi)
2077+static void ptm_read(fuse_req_t req, size_t size, off_t off SWTPM_ATTR_UNUSED,
2078+ struct fuse_file_info *fi SWTPM_ATTR_UNUSED)
2079 {
2080 switch (tx_state.state) {
2081 case TX_STATE_RW_COMMAND:
2082@@ -918,7 +923,8 @@ cleanup:
2083 * on what is being transferred using the write()
2084 */
2085 static void ptm_write(fuse_req_t req, const char *buf, size_t size,
2086- off_t off, struct fuse_file_info *fi)
2087+ off_t off SWTPM_ATTR_UNUSED,
2088+ struct fuse_file_info *fi SWTPM_ATTR_UNUSED)
2089 {
2090 switch (tx_state.state) {
2091 case TX_STATE_RW_COMMAND:
2092@@ -959,7 +965,8 @@ static void ptm_open(fuse_req_t req, struct fuse_file_info *fi)
2093 * needed buffer
2094 */
2095 static void ptm_ioctl(fuse_req_t req, int cmd, void *arg,
2096- struct fuse_file_info *fi, unsigned flags,
2097+ struct fuse_file_info *fi SWTPM_ATTR_UNUSED,
2098+ unsigned flags SWTPM_ATTR_UNUSED,
2099 const void *in_buf, size_t in_bufsz, size_t out_bufsz)
2100 {
2101 TPM_RESULT res = TPM_FAIL;
2102@@ -1448,6 +1455,7 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac
2103 #endif
2104 {"print-capabilities"
2105 , no_argument, 0, 'a'},
2106+ {"print-states" , no_argument, 0, 'e'},
2107 {NULL , 0 , 0, 0 },
2108 };
2109 struct cuse_info cinfo;
2110@@ -1458,11 +1466,12 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac
2111 char *cinfo_argv[1] = { 0 };
2112 unsigned int num;
2113 struct passwd *passwd;
2114- const char *tpmdir;
2115+ const char *uri = NULL;
2116 int n, tpmfd;
2117 char path[PATH_MAX];
2118 int ret = 0;
2119 bool printcapabilities = false;
2120+ bool printstates = false;
2121 bool need_init_cmd = true;
2122 TPM_RESULT res;
2123
2124@@ -1561,6 +1570,9 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac
2125 case 'a':
2126 printcapabilities = true;
2127 break;
2128+ case 'e':
2129+ printstates = true;
2130+ break;
2131 case 'v': /* version */
2132 fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, "
2133 "Copyright (c) 2014-2015 IBM Corp.\n",
2134@@ -1578,23 +1590,61 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac
2135 goto exit;
2136 }
2137
2138- /*
2139- * choose the TPM version early so that getting/setting
2140- * buffer size works.
2141- */
2142- if (TPMLIB_ChooseTPMVersion(tpmversion) != TPM_SUCCESS) {
2143- logprintf(STDERR_FILENO,
2144- "Error: Could not choose TPM version.\n");
2145+ if (setuid(0)) {
2146+ logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
2147+ "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
2148+ ret = -4;
2149+ goto exit;
2150+ }
2151+
2152+ if (param.runas) {
2153+ if (!(passwd = getpwnam(param.runas))) {
2154+ logprintf(STDERR_FILENO, "User '%s' does not exist\n",
2155+ param.runas);
2156+ ret = -5;
2157+ goto exit;
2158+ }
2159+ }
2160+
2161+ if (handle_log_options(param.logging) < 0) {
2162 ret = EXIT_FAILURE;
2163 goto exit;
2164 }
2165
2166 if (printcapabilities) {
2167+ /*
2168+ * Choose the TPM version so that getting/setting buffer size works.
2169+ * Ignore failure, for backward compatibility when TPM 1.2 is disabled.
2170+ */
2171+ TPMLIB_ChooseTPMVersion(tpmversion);
2172 ret = capabilities_print_json(true) ? EXIT_FAILURE : EXIT_SUCCESS;
2173 goto exit;
2174 }
2175
2176- SWTPM_NVRAM_Set_TPMVersion(tpmversion);
2177+ if (TPMLIB_ChooseTPMVersion(tpmversion) != TPM_SUCCESS) {
2178+ logprintf(STDERR_FILENO,
2179+ "Error: Could not choose TPM version.\n");
2180+ ret = EXIT_FAILURE;
2181+ goto exit;
2182+ }
2183+
2184+ tpmstate_set_version(tpmversion);
2185+
2186+ if (printstates) {
2187+ if (handle_tpmstate_options(param.tpmstatedata) < 0) {
2188+ ret = EXIT_FAILURE;
2189+ goto exit;
2190+ }
2191+ if (param.tpmstatedata == NULL) {
2192+ logprintf(STDERR_FILENO,
2193+ "Error: --tpmstate option is required for --print-states\n");
2194+ ret = EXIT_FAILURE;
2195+ goto exit;
2196+ }
2197+ ret = SWTPM_NVRAM_PrintJson();
2198+ ret = ret ? EXIT_FAILURE : EXIT_SUCCESS;
2199+ goto exit;
2200+ }
2201
2202 if (!cinfo.dev_info_argv) {
2203 logprintf(STDERR_FILENO, "Error: device name missing\n");
2204@@ -1602,8 +1652,7 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac
2205 goto exit;
2206 }
2207
2208- if (handle_log_options(param.logging) < 0 ||
2209- handle_key_options(param.keydata) < 0 ||
2210+ if (handle_key_options(param.keydata) < 0 ||
2211 handle_migration_key_options(param.migkeydata) < 0 ||
2212 handle_pid_options(param.piddata) < 0 ||
2213 handle_tpmstate_options(param.tpmstatedata) < 0 ||
2214@@ -1615,24 +1664,8 @@ int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *ifac
2215 goto exit;
2216 }
2217
2218- if (setuid(0)) {
2219- logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, "
2220- "euid = %d, gid = %d\n", getuid(), geteuid(), getgid());
2221- ret = -4;
2222- goto exit;
2223- }
2224-
2225- if (param.runas) {
2226- if (!(passwd = getpwnam(param.runas))) {
2227- logprintf(STDERR_FILENO, "User '%s' does not exist\n",
2228- param.runas);
2229- ret = -5;
2230- goto exit;
2231- }
2232- }
2233-
2234- tpmdir = tpmstate_get_dir();
2235- if (tpmdir == NULL) {
2236+ uri = tpmstate_get_backend_uri();
2237+ if (uri == NULL) {
2238 logprintf(STDERR_FILENO,
2239 "Error: No TPM state directory is defined; "
2240 "TPM_PATH is not set\n");
2241diff --git a/src/swtpm/daemonize.c b/src/swtpm/daemonize.c
2242new file mode 100644
2243index 0000000..5ded2c8
2244--- /dev/null
2245+++ b/src/swtpm/daemonize.c
2246@@ -0,0 +1,302 @@
2247+/*
2248+ * daemonize.c -- Utility functions for race-free daemonization
2249+ *
2250+ * (c) Two Sigma Open Source, LLC 2021.
2251+ *
2252+ * Author: Nicolas Williams <nico@twosigma.com>
2253+ *
2254+ * All rights reserved.
2255+ *
2256+ * Redistribution and use in source and binary forms, with or without
2257+ * modification, are permitted provided that the following conditions are
2258+ * met:
2259+ *
2260+ * Redistributions of source code must retain the above copyright notice,
2261+ * this list of conditions and the following disclaimer.
2262+ *
2263+ * Redistributions in binary form must reproduce the above copyright
2264+ * notice, this list of conditions and the following disclaimer in the
2265+ * documentation and/or other materials provided with the distribution.
2266+ *
2267+ * Neither the names of the IBM Corporation nor the names of its
2268+ * contributors may be used to endorse or promote products derived from
2269+ * this software without specific prior written permission.
2270+ *
2271+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2272+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2273+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2274+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2275+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2276+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2277+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2278+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2279+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2280+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2281+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2282+ */
2283+
2284+#include "config.h"
2285+
2286+#include "daemonize.h"
2287+#include <sys/types.h>
2288+#include <sys/stat.h>
2289+#include <sys/wait.h>
2290+#include <fcntl.h>
2291+#include <errno.h>
2292+#include <signal.h>
2293+#include <stdio.h>
2294+#include <stdlib.h>
2295+#include <string.h>
2296+#include <unistd.h>
2297+
2298+/*
2299+ * daemon(3) is racy because it fork()s and exits in the parent before the
2300+ * child can get ready to provide its services.
2301+ *
2302+ * Not every daemon can set up services before calling daemon(3), as some
2303+ * APIs are not fork-safe and must be called in the child-side of the
2304+ * daemon(3)'s fork() calls.
2305+ *
2306+ * Even if a daemon can set up services before calling daemon(3), it will not
2307+ * be able to write the correct PID into a pidfile until after daemon(3)
2308+ * returns.
2309+ *
2310+ * E.g.,
2311+ *
2312+ * #!/bin/bash
2313+ *
2314+ * # Start a service:
2315+ * some-serviced --daemon --pid=... ...
2316+ *
2317+ * # Call it:
2318+ * call-some-service ping || echo "oops, we won the race but lost the game"
2319+ *
2320+ * To address this we split daemon(3) into two functions, daemonize_prep() and
2321+ * daemonize_finish(). A daemon program should call daemonize_prep() early
2322+ * when it knows it will have to daemonize (e.g., because of a --daemon
2323+ * command-line option), then it should do all the setup required to start
2324+ * providing its services, then it should call daemonize_finish().
2325+ *
2326+ * These two functions do all that daemon(3) does, but in two phases so that
2327+ * the original process that calls daemonize_prep() does not exit until the
2328+ * service is ready.
2329+ *
2330+ * daemonize_prep() calls fork(), setsid(), and then forks again, and returns
2331+ * in the grandchild, but exits in the original and middle processes when the
2332+ * grandchild calls daemonize_finish().
2333+ *
2334+ * How to use this:
2335+ *
2336+ * if (daemonize) {
2337+ * pid_t old_pid, new_pid;
2338+ *
2339+ * old_pid = getpid();
2340+ * if (daemonize_prep() == -1)
2341+ * err(1, "Failed to daemonize");
2342+ *
2343+ * // We're now in a grandchild, but the original parent should still be
2344+ * // waiting.
2345+ * new_pid = getpid();
2346+ * assert(old_pid != new_pid);
2347+ * }
2348+ *
2349+ * // setup sockets, listen() on them, etc...
2350+ * my_setup_service_and_listen_on_sockets();
2351+ *
2352+ * // Tell the waiting parent and grandparent that we're ready:
2353+ * // (doing this even if daemonize_prep() wasn't called is ok)
2354+ * daemonize_finish();
2355+ *
2356+ * // daemonize_finish() did not fork() again:
2357+ * assert(new_pid == getpid());
2358+ *
2359+ * Note: the processes that exit will use _exit(). The process that
2360+ * daemonize_prep() returns to should be able to use exit().
2361+ */
2362+
2363+static int devnullfd = -1;
2364+static int pfd = -1;
2365+
2366+static int
2367+wait_or_die_like_it(pid_t pid)
2368+{
2369+ int status;
2370+
2371+ while (waitpid(pid, &status, 0) == -1) {
2372+ if (errno == EINTR)
2373+ continue;
2374+ /* XXX Should just use err(3). */
2375+ fprintf(stderr, "waitpid() failed: %s\n", strerror(errno));
2376+ fflush(stderr);
2377+ _exit(1);
2378+ }
2379+ if (WIFSIGNALED(status)) {
2380+ /*
2381+ * Child died in a fire; die like it so the parent sees the same exit
2382+ * status.
2383+ */
2384+ kill(getpid(), WTERMSIG(status));
2385+ }
2386+ if (!WIFEXITED(status)) {
2387+ /* If fire doesn't kill us, _exit(). */
2388+ _exit(1);
2389+ }
2390+ /* Child exited willingly. */
2391+ return WEXITSTATUS(status);
2392+}
2393+
2394+/*
2395+ * Prepare to daemonize. When ready, the caller should call
2396+ * daemonize_finish().
2397+ *
2398+ * This arranges for the parent to exit when and only when the child is ready
2399+ * to service clients.
2400+ *
2401+ * This forks a grandchild and returns in the grandchild
2402+ * but exits in the parent and grandparent, but only once the child calls
2403+ * daemonize_finish() (or exits/dies, whichever comes first).
2404+ *
2405+ * Because the parent side of the fork() calls _exit(), the child can exit().
2406+ *
2407+ * Returns -1 on error (sets errno), 0 on success.
2408+ */
2409+int
2410+daemonize_prep(void)
2411+{
2412+ ssize_t bytes;
2413+ char buf;
2414+ int save_errno = errno;
2415+ int pfds[2] = { -1, -1 };
2416+ pid_t pid;
2417+
2418+ /*
2419+ * Be idempotent. If called twice because, e.g., --daemon is given twice,
2420+ * do nothing the second time.
2421+ */
2422+ if (pfd != -1)
2423+ return 0;
2424+
2425+ /* Grand parent process. */
2426+ fflush(stdout);
2427+ fflush(stderr);
2428+ pid = fork();
2429+ if (pid == (pid_t)-1) {
2430+ fprintf(stderr, "Failed to daemonize: Failed to fork: %s\n",
2431+ strerror(errno));
2432+ return -1;
2433+ }
2434+
2435+ if (pid != 0) {
2436+ /*
2437+ * Grand parent process: exit when the grandchild is ready or die in
2438+ * the same way.
2439+ */
2440+ _exit(wait_or_die_like_it(pid));
2441+ }
2442+
2443+ /* Intermediate process. Detach from tty, fork() again. */
2444+ if (setsid() == -1) {
2445+ fprintf(stderr, "Failed to daemonize: Failed to detach from tty: %s\n",
2446+ strerror(errno));
2447+ _exit(1);
2448+ }
2449+
2450+ /* Set things up so the grandchild can finish daemonizing. */
2451+ devnullfd = open("/dev/null", O_RDWR);
2452+ if (devnullfd == -1) {
2453+ fprintf(stderr, "Failed to daemonize: Could not open /dev/null: %s\n",
2454+ strerror(errno));
2455+ _exit(1);
2456+ }
2457+ if (pipe(pfds) == -1) {
2458+ fprintf(stderr, "Failed to daemonize: Could not make a pipe: %s\n",
2459+ strerror(errno));
2460+ _exit(1);
2461+ }
2462+ pfd = pfds[1];
2463+
2464+ /* Fork the grandchild so it cannot get a controlling tty by accident. */
2465+ pid = fork();
2466+ if (pid == (pid_t)-1) {
2467+ fprintf(stderr, "Failed to daemonize: Could not fork: %s\n",
2468+ strerror(errno));
2469+ _exit(1);
2470+ }
2471+ if (pid != 0) {
2472+ /*
2473+ * Middle process.
2474+ *
2475+ * Wait for ready notification from the child, then _exit()
2476+ * accordingly.
2477+ */
2478+ (void) close(pfds[1]);
2479+ do {
2480+ bytes = read(pfds[0], &buf, sizeof(buf));
2481+ } while (bytes == -1 && errno == EINTR);
2482+ if (bytes < 0) {
2483+ fprintf(stderr, "Failed to daemonize: "
2484+ "Error reading from pipe: %s\n", strerror(errno));
2485+ /* Let init reap the grandchild. */
2486+ _exit(1);
2487+ }
2488+ if (bytes == 0) {
2489+ /* Die like the grandchild. */
2490+ _exit(wait_or_die_like_it(pid));
2491+ }
2492+ /* Ready! */
2493+ _exit(0);
2494+ }
2495+
2496+ /*
2497+ * We're on the grandchild side now, and we'll return with the expectation
2498+ * that the caller will call daemonize_finish(). The parent, which will
2499+ * continue executing this function, will _exit() when the child indicates
2500+ * that it is ready.
2501+ */
2502+ (void) close(pfds[0]);
2503+ errno = save_errno;
2504+ return 0;
2505+}
2506+
2507+/*
2508+ * Indicate that the service is now ready.
2509+ *
2510+ * Will cause the ancestor processes waiting in daemonize_prep() to _exit().
2511+ */
2512+void
2513+daemonize_finish(void)
2514+{
2515+ ssize_t bytes;
2516+ int save_errno = errno;
2517+
2518+ /* pfds[1] will be > -1 IFF daemonize_prep() was called */
2519+ if (pfd == -1) {
2520+ return;
2521+ }
2522+
2523+ if (dup2(devnullfd, STDOUT_FILENO) == -1) {
2524+ fprintf(stderr, "Failed to redirect output stream to /dev/null: %s\n",
2525+ strerror(errno));
2526+ fflush(stderr);
2527+ exit(1);
2528+ }
2529+ if (dup2(devnullfd, STDERR_FILENO) == -1) {
2530+ fprintf(stderr, "Failed to redirect error stream to /dev/null: %s\n",
2531+ strerror(errno));
2532+ fflush(stderr);
2533+ exit(1);
2534+ }
2535+ (void) close(devnullfd);
2536+ devnullfd = -1;
2537+
2538+ do {
2539+ bytes = write(pfd, "", sizeof(""));
2540+ } while (bytes == -1 && errno == EINTR);
2541+ if (bytes <= 0) {
2542+ /* There's no point writing to stderr now that it goes to /dev/null */
2543+ exit(1);
2544+ }
2545+ (void) close(pfd);
2546+ pfd = -1;
2547+ errno = save_errno;
2548+}
2549diff --git a/src/swtpm/osx.h b/src/swtpm/daemonize.h
2550similarity index 88%
2551rename from src/swtpm/osx.h
2552rename to src/swtpm/daemonize.h
2553index 1b569fa..92b4eda 100644
2554--- a/src/swtpm/osx.h
2555+++ b/src/swtpm/daemonize.h
2556@@ -1,9 +1,9 @@
2557 /*
2558- * osx.h -- OS X specifics
2559+ * daemonize.h -- Race-free daemoninization utilities
2560 *
2561- * (c) Copyright IBM Corporation 2018.
2562+ * (c) Copyright IBM Corporation 2021.
2563 *
2564- * Author: Stefan Berger <stefanb@us.ibm.com>
2565+ * Author: Nicolas Williams <nico@twosigma.com>
2566 *
2567 * All rights reserved.
2568 *
2569@@ -38,6 +38,7 @@
2570 #ifndef SWTPM_OSX
2571 #define SWTPM_OSX
2572
2573-int osx_daemon(int nochdir, int noclose);
2574+int daemonize_prep(void);
2575+void daemonize_finish(void);
2576
2577-#endif /* SWTPM_OSX */
2578\ No newline at end of file
2579+#endif /* SWTPM_OSX */
2580diff --git a/src/swtpm/mainloop.c b/src/swtpm/mainloop.c
2581index 04ffa6a..44d67b7 100644
2582--- a/src/swtpm/mainloop.c
2583+++ b/src/swtpm/mainloop.c
2584@@ -64,6 +64,8 @@
2585 #include "mainloop.h"
2586 #include "utils.h"
2587 #include "sys_dependencies.h"
2588+#include "compiler_dependencies.h"
2589+#include "swtpm_utils.h"
2590
2591 /* local variables */
2592 static TPM_MODIFIER_INDICATOR locality;
2593@@ -73,7 +75,7 @@ bool mainloop_terminate;
2594
2595 TPM_RESULT
2596 mainloop_cb_get_locality(TPM_MODIFIER_INDICATOR *loc,
2597- uint32_t tpmnum)
2598+ uint32_t tpmnum SWTPM_ATTR_UNUSED)
2599 {
2600 *loc = locality;
2601
2602@@ -157,23 +159,27 @@ int mainLoop(struct mainLoopParams *mlp,
2603 connection_fd.fd = mlp->fd;
2604
2605 struct pollfd pollfds[] = {
2606- {
2607+ [DATA_CLIENT_FD] = {
2608 .fd = connection_fd.fd,
2609 .events = POLLIN | POLLHUP,
2610 .revents = 0,
2611- }, {
2612+ },
2613+ [NOTIFY_FD] = {
2614 .fd = notify_fd,
2615 .events = POLLIN,
2616 .revents = 0,
2617- }, {
2618+ },
2619+ [CTRL_SERVER_FD] = {
2620 .fd = -1,
2621 .events = POLLIN,
2622 .revents = 0,
2623- } , {
2624+ },
2625+ [CTRL_CLIENT_FD] = {
2626 .fd = ctrlclntfd,
2627 .events = POLLIN | POLLHUP,
2628 .revents = 0,
2629- } , {
2630+ },
2631+ [DATA_SERVER_FD] = {
2632 /* listen socket for accepting clients */
2633 .fd = -1,
2634 .events = POLLIN,
2635diff --git a/src/swtpm/osx.c b/src/swtpm/osx.c
2636deleted file mode 100644
2637index e06853b..0000000
2638--- a/src/swtpm/osx.c
2639+++ /dev/null
2640@@ -1,51 +0,0 @@
2641-/*
2642- * osx.c -- OS X specifics
2643- *
2644- * (c) Copyright IBM Corporation 2018.
2645- *
2646- * Author: Stefan Berger <stefanb@us.ibm.com>
2647- *
2648- * All rights reserved.
2649- *
2650- * Redistribution and use in source and binary forms, with or without
2651- * modification, are permitted provided that the following conditions are
2652- * met:
2653- *
2654- * Redistributions of source code must retain the above copyright notice,
2655- * this list of conditions and the following disclaimer.
2656- *
2657- * Redistributions in binary form must reproduce the above copyright
2658- * notice, this list of conditions and the following disclaimer in the
2659- * documentation and/or other materials provided with the distribution.
2660- *
2661- * Neither the names of the IBM Corporation nor the names of its
2662- * contributors may be used to endorse or promote products derived from
2663- * this software without specific prior written permission.
2664- *
2665- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2666- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2667- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2668- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2669- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2670- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2671- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2672- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2673- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2674- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2675- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2676- */
2677-
2678-#include "config.h"
2679-
2680-#include "osx.h"
2681-
2682-#if defined __APPLE__
2683-
2684-int daemon(int, int); /* OS X deprecates it */
2685-
2686-int osx_daemon(int nochdir, int noclose)
2687-{
2688- return daemon(nochdir, noclose);
2689-}
2690-
2691-#endif /* __APPLE__ */
2692\ No newline at end of file
2693diff --git a/src/swtpm/seccomp_profile.c b/src/swtpm/seccomp_profile.c
2694index 8ada407..e2684f3 100644
2695--- a/src/swtpm/seccomp_profile.c
2696+++ b/src/swtpm/seccomp_profile.c
2697@@ -47,6 +47,7 @@
2698 #include "logging.h"
2699 #include "utils.h"
2700 #include "seccomp_profile.h"
2701+#include "swtpm_utils.h"
2702
2703 #ifdef WITH_SECCOMP
2704 static int create_seccomp_profile_add_rules(scmp_filter_ctx ctx,
2705@@ -148,7 +149,6 @@ int create_seccomp_profile(bool cusetpm, unsigned int action)
2706 SCMP_SYS(sched_setparam),
2707 SCMP_SYS(sched_setscheduler),
2708 SCMP_SYS(sched_setaffinity),
2709- SCMP_SYS(sched_setattr),
2710 SCMP_SYS(vhangup),
2711 SCMP_SYS(sethostname),
2712 SCMP_SYS(setdomainname),
2713@@ -253,6 +253,8 @@ int create_seccomp_profile(bool cusetpm, unsigned int action)
2714 #ifdef __NR_clone3
2715 SCMP_SYS(clone3),
2716 #endif
2717+ /* misc */
2718+ SCMP_SYS(sched_setattr), /* caller: g_thread_pool_new() glib v2.68 */
2719 };
2720 scmp_filter_ctx ctx;
2721 int ret;
2722diff --git a/src/swtpm/swtpm.c b/src/swtpm/swtpm.c
2723index 8e6f52a..d4ad682 100644
2724--- a/src/swtpm/swtpm.c
2725+++ b/src/swtpm/swtpm.c
2726@@ -57,7 +57,7 @@
2727 #include "main.h"
2728 #include "swtpm_debug.h"
2729 #include "swtpm_io.h"
2730-#include "swtpm_nvfile.h"
2731+#include "swtpm_nvstore.h"
2732 #include "server.h"
2733 #include "common.h"
2734 #include "logging.h"
2735@@ -68,7 +68,7 @@
2736 #include "ctrlchannel.h"
2737 #include "tpmstate.h"
2738 #include "sys_dependencies.h"
2739-#include "osx.h"
2740+#include "daemonize.h"
2741 #include "seccomp_profile.h"
2742 #include "options.h"
2743 #include "capabilities.h"
2744@@ -149,10 +149,10 @@ static void usage(FILE *file, const char *prgname, const char *iface)
2745 " allow-set-locality: accept SetLocality command\n"
2746 "--pid file=<path>|fd=<filedescriptor>\n"
2747 " : write the process ID into the given file\n"
2748- "--tpmstate dir=<dir>[,mode=0...]\n"
2749- " : set the directory where the TPM's state will be written\n"
2750+ "--tpmstate dir=<dir>[,mode=0...]|backend-uri=<uri>\n"
2751+ " : set the directory or uri where the TPM's state will be written\n"
2752 " into; the TPM_PATH environment variable can be used\n"
2753- " instead;\n"
2754+ " instead dir option;\n"
2755 " mode allows a user to set the file mode bits of the state files;\n"
2756 " the default mode is 0640;\n"
2757 "--server [type=tcp][,port=port[,bindaddr=address[,ifname=ifname]]][,fd=fd][,disconnect]\n"
2758@@ -185,6 +185,8 @@ static void usage(FILE *file, const char *prgname, const char *iface)
2759 #endif
2760 "--print-capabilites\n"
2761 " : print capabilities and terminate\n"
2762+ "--print-states\n"
2763+ " : print existing TPM states and terminate\n"
2764 "-h|--help : display this help screen and terminate\n"
2765 "\n",
2766 prgname, iface);
2767@@ -235,6 +237,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2768 #endif
2769 unsigned int seccomp_action;
2770 bool printcapabilities = false;
2771+ bool printstates = false;
2772 static struct option longopts[] = {
2773 {"daemon" , no_argument, 0, 'd'},
2774 {"help" , no_argument, 0, 'h'},
2775@@ -257,6 +260,7 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2776 #endif
2777 {"print-capabilities"
2778 , no_argument, 0, 'a'},
2779+ {"print-states", no_argument, 0, 'e'},
2780 {NULL , 0 , 0, 0 },
2781 };
2782
2783@@ -271,6 +275,11 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2784 switch (opt) {
2785 case 'd':
2786 daemonize = TRUE;
2787+ if (daemonize_prep() == -1) {
2788+ logprintf(STDERR_FILENO,
2789+ "Could not prepare to daemonize: %s\n", strerror(errno));
2790+ exit(EXIT_FAILURE);
2791+ }
2792 break;
2793
2794 case 'p':
2795@@ -378,6 +387,10 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2796 printcapabilities = true;
2797 break;
2798
2799+ case 'e':
2800+ printstates = true;
2801+ break;
2802+
2803 case 'r':
2804 runas = optarg;
2805 break;
2806@@ -398,6 +411,15 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2807 exit(EXIT_FAILURE);
2808 }
2809
2810+ /* change process ownership before accessing files */
2811+ if (runas) {
2812+ if (change_process_owner(runas) < 0)
2813+ exit(EXIT_FAILURE);
2814+ }
2815+
2816+ if (handle_log_options(logdata) < 0)
2817+ exit(EXIT_FAILURE);
2818+
2819 if (mlp.fd >= 0 && mlp.fd < 3) {
2820 /* no std{in,out,err} */
2821 logprintf(STDERR_FILENO,
2822@@ -405,36 +427,45 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2823 exit(EXIT_FAILURE);
2824 }
2825
2826- /*
2827- * choose the TPM version early so that getting/setting
2828- * buffer size works.
2829- */
2830+ if (printcapabilities) {
2831+ /*
2832+ * Choose the TPM version so that getting/setting buffer size works.
2833+ * Ignore failure, for backward compatibility when TPM 1.2 is disabled.
2834+ */
2835+ TPMLIB_ChooseTPMVersion(mlp.tpmversion);
2836+ ret = capabilities_print_json(false);
2837+ exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
2838+ }
2839+
2840 if (TPMLIB_ChooseTPMVersion(mlp.tpmversion) != TPM_SUCCESS) {
2841 logprintf(STDERR_FILENO,
2842 "Error: Could not choose TPM version.\n");
2843 exit(EXIT_FAILURE);
2844 }
2845
2846- if (printcapabilities) {
2847- ret = capabilities_print_json(false);
2848- exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
2849- }
2850-
2851 if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc) < 0 ||
2852 handle_server_options(serverdata, &server) < 0) {
2853 goto exit_failure;
2854 }
2855
2856- /* change process ownership before accessing files */
2857- if (runas) {
2858- if (change_process_owner(runas) < 0)
2859+ tpmstate_set_version(mlp.tpmversion);
2860+
2861+ if (printstates) {
2862+ if (handle_tpmstate_options(tpmstatedata) < 0)
2863+ goto exit_failure;
2864+ if (tpmstatedata == NULL) {
2865+ logprintf(STDERR_FILENO,
2866+ "Error: --tpmstate option is required for --print-states\n");
2867+ goto exit_failure;
2868+ }
2869+ ret = SWTPM_NVRAM_PrintJson();
2870+ if (ret == 0)
2871+ goto exit_success;
2872+ else
2873 goto exit_failure;
2874 }
2875
2876- SWTPM_NVRAM_Set_TPMVersion(mlp.tpmversion);
2877-
2878- if (handle_log_options(logdata) < 0 ||
2879- handle_key_options(keydata) < 0 ||
2880+ if (handle_key_options(keydata) < 0 ||
2881 handle_migration_key_options(migkeydata) < 0 ||
2882 handle_pid_options(piddata) < 0 ||
2883 handle_locality_options(localitydata, &mlp.locality_flags) < 0 ||
2884@@ -459,17 +490,6 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2885 mlp.flags |= MAIN_LOOP_FLAG_TERMINATE | MAIN_LOOP_FLAG_USE_FD;
2886 }
2887
2888- if (daemonize) {
2889-#ifdef __APPLE__
2890- if (0 != osx_daemon(1, 0)) {
2891-#else
2892- if (0 != daemon(1, 0)) {
2893-#endif
2894- logprintf(STDERR_FILENO, "Error: Could not daemonize.\n");
2895- goto exit_failure;
2896- }
2897- }
2898-
2899 if (pidfile_write(getpid()) < 0) {
2900 goto exit_failure;
2901 }
2902@@ -500,6 +520,10 @@ int swtpm_main(int argc, char **argv, const char *prgname, const char *iface)
2903 if (create_seccomp_profile(false, seccomp_action) < 0)
2904 goto error_seccomp_profile;
2905
2906+ if (daemonize) {
2907+ daemonize_finish();
2908+ }
2909+
2910 rc = mainLoop(&mlp, notify_fd[0]);
2911
2912 error_seccomp_profile:
2913@@ -529,4 +553,9 @@ exit_failure:
2914 swtpm_cleanup(mlp.cc, server);
2915
2916 exit(EXIT_FAILURE);
2917+
2918+exit_success:
2919+ swtpm_cleanup(mlp.cc, server);
2920+
2921+ exit(EXIT_SUCCESS);
2922 }
2923diff --git a/src/swtpm/swtpm_aes.c b/src/swtpm/swtpm_aes.c
2924index 69f2101..5f74bf2 100644
2925--- a/src/swtpm/swtpm_aes.c
2926+++ b/src/swtpm/swtpm_aes.c
2927@@ -43,7 +43,7 @@
2928 #include <stdlib.h>
2929 #include <string.h>
2930
2931-#include <openssl/aes.h>
2932+#include <openssl/evp.h>
2933
2934 #include <libtpms/tpm_types.h>
2935 #include <libtpms/tpm_error.h>
2936@@ -52,9 +52,21 @@
2937 #include "swtpm_aes.h"
2938 #include "logging.h"
2939
2940-#define printf(X ...)
2941+typedef const EVP_CIPHER *(*evpfunc)(void);
2942
2943-/* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to encrypt 'decrypt_data' to
2944+static evpfunc SWTPM_Get_AES_EVPFn(unsigned int bits)
2945+{
2946+ switch (bits) {
2947+ case 128:
2948+ return EVP_aes_128_cbc;
2949+ case 256:
2950+ return EVP_aes_256_cbc;
2951+ default:
2952+ return NULL;
2953+ }
2954+}
2955+
2956+/* SWTPM_SymmetricKeyData_Encrypt() is AES non-portable code to encrypt 'decrypt_data' to
2957 'encrypt_data'
2958
2959 The stream is padded as per PKCS#7 / RFC2630
2960@@ -77,17 +89,18 @@ TPM_RESULT SWTPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* out
2961 unsigned char ivec[SWTPM_AES256_BLOCK_SIZE]; /* initial chaining vector */
2962 TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data =
2963 (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token;
2964- AES_KEY key;
2965 size_t userKeyLength = tpm_symmetric_key_token->userKeyLength;
2966+ EVP_CIPHER_CTX *ctx = NULL;
2967+ evpfunc evpfn;
2968
2969- printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length);
2970 decrypt_data_pad = NULL; /* freed @1 */
2971
2972 if (rc == 0) {
2973 if (u_ivec != NULL && u_ivec_length != userKeyLength) {
2974- printf("TPM_SymmetricKeyData_Encrypt: IV is %u bytes, "
2975- "but expected %u bytes\n", u_ivec_length,
2976- tpm_symmetric_key_token->userKeyLength);
2977+ logprintf(STDERR_FILENO,
2978+ "SWTPM_SymmetricKeyData_Encrypt: IV is %u bytes, "
2979+ "but expected %u bytes\n", u_ivec_length,
2980+ tpm_symmetric_key_token->userKeyLength);
2981 rc = TPM_ENCRYPT_ERROR;
2982 } else {
2983 if (u_ivec) {
2984@@ -103,8 +116,6 @@ TPM_RESULT SWTPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* out
2985 /* calculate the pad length and padded data length */
2986 pad_length = userKeyLength - (decrypt_length % userKeyLength);
2987 *encrypt_length = decrypt_length + pad_length;
2988- printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n",
2989- *encrypt_length, pad_length);
2990 /* allocate memory for the encrypted response */
2991 *encrypt_data = malloc(*encrypt_length);
2992 if (!*encrypt_data) {
2993@@ -124,35 +135,48 @@ TPM_RESULT SWTPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* out
2994 }
2995
2996 if (rc == 0) {
2997- memset(&key, 0, sizeof(key)); /* coverity */
2998- if (AES_set_encrypt_key(tpm_symmetric_key_data->userKey,
2999- userKeyLength * 8,
3000- &key) < 0) {
3001+ evpfn = SWTPM_Get_AES_EVPFn(userKeyLength * 8);
3002+ ctx = EVP_CIPHER_CTX_new();
3003+ if (!evpfn || !ctx ||
3004+ EVP_EncryptInit_ex(ctx, evpfn(), NULL,
3005+ tpm_symmetric_key_data->userKey, ivec) != 1 ||
3006+ EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
3007+ logprintf(STDERR_FILENO,
3008+ "Could not setup context for encryption.\n");
3009 rc = TPM_FAIL;
3010 }
3011 }
3012
3013 /* pad the decrypted clear text data */
3014 if (rc == 0) {
3015+ int outlen1 = 0;
3016+ int outlen2 = 0;
3017+
3018 /* unpadded original data */
3019 memcpy(decrypt_data_pad, decrypt_data, decrypt_length);
3020 /* last gets pad = pad length */
3021 memset(decrypt_data_pad + decrypt_length, pad_length, pad_length);
3022 /* encrypt the padded input to the output */
3023- //TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad);
3024- AES_cbc_encrypt(decrypt_data_pad,
3025- *encrypt_data,
3026- *encrypt_length,
3027- &key,
3028- ivec,
3029- AES_ENCRYPT);
3030- //TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data);
3031+ //TPM_PrintFour(" SWTPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad);
3032+ if (EVP_EncryptUpdate(ctx,
3033+ *encrypt_data, &outlen1,
3034+ decrypt_data_pad, *encrypt_length) != 1 ||
3035+ EVP_EncryptFinal_ex(ctx, *encrypt_data + outlen1, &outlen2) != 1 ||
3036+ (uint32_t)(outlen1 + outlen2) != *encrypt_length) {
3037+ logprintf(STDERR_FILENO,
3038+ "Could not encrypt %u bytes. outlen1=%d, outlen2=%d.\n",
3039+ *encrypt_length, outlen1, outlen2);
3040+ rc = TPM_FAIL;
3041+ }
3042+ //TPM_PrintFour(" SWTPM_SymmetricKeyData_Encrypt: Output", *encrypt_data);
3043 }
3044 free(decrypt_data_pad); /* @1 */
3045+ EVP_CIPHER_CTX_free(ctx);
3046+
3047 return rc;
3048 }
3049
3050-/* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to decrypt 'encrypt_data' to
3051+/* SWTPM_SymmetricKeyData_Decrypt() is AES non-portable code to decrypt 'encrypt_data' to
3052 'decrypt_data'
3053
3054 The stream must be padded as per PKCS#7 / RFC2630
3055@@ -176,21 +200,23 @@ TPM_RESULT SWTPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* out
3056 unsigned char ivec[SWTPM_AES256_BLOCK_SIZE]; /* initial chaining vector */
3057 TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data =
3058 (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token;
3059- AES_KEY key;
3060 size_t userKeyLength = tpm_symmetric_key_token->userKeyLength;
3061+ EVP_CIPHER_CTX *ctx = NULL;
3062+ evpfunc evpfn;
3063
3064- printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length);
3065 /* sanity check encrypted length */
3066 if (rc == 0) {
3067 if (encrypt_length < userKeyLength) {
3068- printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n");
3069+ logprintf(STDERR_FILENO,
3070+ "SWTPM_SymmetricKeyData_Decrypt: Error, bad length\n");
3071 rc = TPM_DECRYPT_ERROR;
3072 }
3073 }
3074 if (rc == 0) {
3075 if (u_ivec != NULL && u_ivec_length != userKeyLength) {
3076- printf("TPM_SymmetricKeyData_Decrypt: IV is %u bytes, "
3077- "but expected %u bytes\n", u_ivec_length, userKeyLength);
3078+ logprintf(STDERR_FILENO,
3079+ "SWTPM_SymmetricKeyData_Decrypt: IV is %u bytes, "
3080+ "but expected %u bytes\n", u_ivec_length, userKeyLength);
3081 rc = TPM_DECRYPT_ERROR;
3082 } else {
3083 if (u_ivec) {
3084@@ -212,35 +238,46 @@ TPM_RESULT SWTPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* out
3085 }
3086
3087 if (rc == 0) {
3088- memset(&key, 0, sizeof(key)); /* coverity */
3089- if (AES_set_decrypt_key(tpm_symmetric_key_data->userKey,
3090- userKeyLength * 8,
3091- &key) < 0) {
3092+ evpfn = SWTPM_Get_AES_EVPFn(userKeyLength * 8);
3093+ ctx = EVP_CIPHER_CTX_new();
3094+ if (!evpfn || !ctx ||
3095+ EVP_DecryptInit_ex(ctx, evpfn(), NULL,
3096+ tpm_symmetric_key_data->userKey, ivec) != 1 ||
3097+ EVP_CIPHER_CTX_set_padding(ctx, 0) != 1) {
3098+ logprintf(STDERR_FILENO,
3099+ "Could not setup context for decryption.\n");
3100 rc = TPM_FAIL;
3101 }
3102 }
3103
3104 /* decrypt the input to the padded output */
3105 if (rc == 0) {
3106+ int outlen1 = 0;
3107+ int outlen2 = 0;
3108+
3109 /* decrypt the padded input to the output */
3110- //TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data);
3111- AES_cbc_encrypt(encrypt_data,
3112- *decrypt_data,
3113- encrypt_length,
3114- &key,
3115- ivec,
3116- AES_DECRYPT);
3117- //TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data);
3118+ //TPM_PrintFour(" SWTPM_SymmetricKeyData_Decrypt: Input", encrypt_data);
3119+ if (EVP_DecryptUpdate(ctx,
3120+ *decrypt_data, &outlen1,
3121+ encrypt_data, encrypt_length) != 1 ||
3122+ EVP_DecryptFinal_ex(ctx, *decrypt_data + outlen1, &outlen2) != 1 ||
3123+ (uint32_t)(outlen1 + outlen2) != encrypt_length) {
3124+ logprintf(STDERR_FILENO,
3125+ "Could not decrypt %u bytes. outlen1=%d, outlen2=%d.\n",
3126+ encrypt_length, outlen1, outlen2);
3127+ rc = TPM_FAIL;
3128+ }
3129+ //TPM_PrintFour(" SWTPM_SymmetricKeyData_Decrypt: Output", *decrypt_data);
3130 }
3131 /* get the pad length */
3132 if (rc == 0) {
3133 /* get the pad length from the last byte */
3134 pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1);
3135 /* sanity check the pad length */
3136- printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length);
3137 if ((pad_length == 0) ||
3138 (pad_length > userKeyLength)) {
3139- printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n");
3140+ logprintf(STDERR_FILENO,
3141+ "SWTPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n");
3142 rc = TPM_DECRYPT_ERROR;
3143 }
3144 }
3145@@ -252,11 +289,14 @@ TPM_RESULT SWTPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* out
3146 /* sanity check the pad */
3147 for (i = 0 ; i < pad_length ; i++, pad_data++) {
3148 if (*pad_data != pad_length) {
3149- printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n",
3150- *pad_data, i);
3151+ logprintf(STDERR_FILENO,
3152+ "SWTPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n",
3153+ *pad_data, i);
3154 rc = TPM_DECRYPT_ERROR;
3155 }
3156 }
3157 }
3158+ EVP_CIPHER_CTX_free(ctx);
3159+
3160 return rc;
3161 }
3162diff --git a/src/swtpm/swtpm_chardev.c b/src/swtpm/swtpm_chardev.c
3163index 2fa2668..165d568 100644
3164--- a/src/swtpm/swtpm_chardev.c
3165+++ b/src/swtpm/swtpm_chardev.c
3166@@ -57,7 +57,7 @@
3167 #include "main.h"
3168 #include "swtpm_debug.h"
3169 #include "swtpm_io.h"
3170-#include "swtpm_nvfile.h"
3171+#include "swtpm_nvstore.h"
3172 #include "common.h"
3173 #include "locality.h"
3174 #include "logging.h"
3175@@ -70,7 +70,7 @@
3176 #include "vtpm_proxy.h"
3177 #endif
3178 #include "tpmstate.h"
3179-#include "osx.h"
3180+#include "daemonize.h"
3181 #include "seccomp_profile.h"
3182 #include "options.h"
3183 #include "capabilities.h"
3184@@ -175,10 +175,10 @@ static void usage(FILE *file, const char *prgname, const char *iface)
3185 " derived from this passphrase; default kdf is PBKDF2\n"
3186 "--pid file=<path>|fd=<filedescriptor>\n"
3187 " : write the process ID into the given file\n"
3188- "--tpmstate dir=<dir>[,mode=0...]\n"
3189- " : set the directory where the TPM's state will be written\n"
3190+ "--tpmstate dir=<dir>[,mode=0...]|backend-uri=<uri>\n"
3191+ " : set the directory or uri where the TPM's state will be written\n"
3192 " into; the TPM_PATH environment variable can be used\n"
3193- " instead;\n"
3194+ " instead of dir option;\n"
3195 " mode allows a user to set the file mode bits of the state files;\n"
3196 " the default mode is 0640;\n"
3197 "-r|--runas <user>: change to the given user\n"
3198@@ -207,6 +207,8 @@ static void usage(FILE *file, const char *prgname, const char *iface)
3199 #endif
3200 "--print-capabilites\n"
3201 " : print capabilities and terminate\n"
3202+ "--print-states\n"
3203+ " : print existing TPM states and terminate\n"
3204 "-h|--help : display this help screen and terminate\n"
3205 "\n",
3206 prgname, iface);
3207@@ -294,6 +296,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3208 bool need_init_cmd = true;
3209 unsigned int seccomp_action;
3210 bool printcapabilities = false;
3211+ bool printstates = false;
3212 static struct option longopts[] = {
3213 {"daemon" , no_argument, 0, 'd'},
3214 {"help" , no_argument, 0, 'h'},
3215@@ -317,6 +320,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3216 #endif
3217 {"print-capabilities"
3218 , no_argument, 0, 'a'},
3219+ {"print-states", no_argument, 0, 'e'},
3220 {NULL , 0 , 0, 0 },
3221 };
3222
3223@@ -331,6 +335,11 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3224 switch (opt) {
3225 case 'd':
3226 daemonize = TRUE;
3227+ if (daemonize_prep() == -1) {
3228+ logprintf(STDERR_FILENO,
3229+ "Could not prepare to daemonize: %s\n", strerror(errno));
3230+ exit(EXIT_FAILURE);
3231+ }
3232 break;
3233
3234 case 'c':
3235@@ -423,6 +432,10 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3236 printcapabilities = true;
3237 break;
3238
3239+ case 'e':
3240+ printstates = true;
3241+ break;
3242+
3243 case 'r':
3244 runas = optarg;
3245 break;
3246@@ -449,6 +462,15 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3247 exit(EXIT_FAILURE);
3248 }
3249
3250+ /* change process ownership before accessing files */
3251+ if (runas) {
3252+ if (change_process_owner(runas) < 0)
3253+ exit(EXIT_FAILURE);
3254+ }
3255+
3256+ if (handle_log_options(logdata) < 0)
3257+ exit(EXIT_FAILURE);
3258+
3259 if (handle_locality_options(localitydata, &mlp.locality_flags) < 0)
3260 exit(EXIT_FAILURE);
3261
3262@@ -459,22 +481,38 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3263 }
3264 #endif
3265
3266- /*
3267- * choose the TPM version early so that getting/setting
3268- * buffer size works.
3269- */
3270+ if (printcapabilities) {
3271+ /*
3272+ * Choose the TPM version so that getting/setting buffer size works.
3273+ * Ignore failure, for backward compatibility when TPM 1.2 is disabled.
3274+ */
3275+ TPMLIB_ChooseTPMVersion(mlp.tpmversion);
3276+ ret = capabilities_print_json(false);
3277+ exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
3278+ }
3279+
3280 if (TPMLIB_ChooseTPMVersion(mlp.tpmversion) != TPM_SUCCESS) {
3281 logprintf(STDERR_FILENO,
3282 "Error: Could not choose TPM version.\n");
3283 exit(EXIT_FAILURE);
3284 }
3285
3286- if (printcapabilities) {
3287- ret = capabilities_print_json(false);
3288- exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
3289- }
3290+ tpmstate_set_version(mlp.tpmversion);
3291
3292- SWTPM_NVRAM_Set_TPMVersion(mlp.tpmversion);
3293+ if (printstates) {
3294+ if (handle_tpmstate_options(tpmstatedata) < 0)
3295+ exit(EXIT_FAILURE);
3296+ if (tpmstatedata == NULL) {
3297+ logprintf(STDERR_FILENO,
3298+ "Error: --tpmstate option is required for --print-states\n");
3299+ exit(EXIT_FAILURE);
3300+ }
3301+ ret = SWTPM_NVRAM_PrintJson();
3302+ if (ret)
3303+ goto exit_failure;
3304+ else
3305+ goto exit_success;
3306+ }
3307
3308 if (mlp.fd < 0) {
3309 logprintf(STDERR_FILENO,
3310@@ -491,14 +529,7 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3311 goto exit_failure;
3312 }
3313
3314- /* change process ownership before accessing files */
3315- if (runas) {
3316- if (change_process_owner(runas) < 0)
3317- goto exit_failure;
3318- }
3319-
3320- if (handle_log_options(logdata) < 0 ||
3321- handle_key_options(keydata) < 0 ||
3322+ if (handle_key_options(keydata) < 0 ||
3323 handle_migration_key_options(migkeydata) < 0 ||
3324 handle_pid_options(piddata) < 0 ||
3325 handle_tpmstate_options(tpmstatedata) < 0 ||
3326@@ -508,17 +539,6 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3327 goto exit_failure;
3328 }
3329
3330- if (daemonize) {
3331-#if defined __APPLE__
3332- if (0 != osx_daemon(1, 0)) {
3333-#else
3334- if (0 != daemon(1, 0)) {
3335-#endif
3336- logprintf(STDERR_FILENO, "Error: Could not daemonize.\n");
3337- goto exit_failure;
3338- }
3339- }
3340-
3341 if (pidfile_write(getpid()) < 0) {
3342 goto exit_failure;
3343 }
3344@@ -552,6 +572,10 @@ int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *i
3345 mlp.flags |= MAIN_LOOP_FLAG_USE_FD | MAIN_LOOP_FLAG_KEEP_CONNECTION | \
3346 MAIN_LOOP_FLAG_END_ON_HUP;
3347
3348+ if (daemonize) {
3349+ daemonize_finish();
3350+ }
3351+
3352 rc = mainLoop(&mlp, notify_fd[0]);
3353
3354 error_seccomp_profile:
3355@@ -581,4 +605,9 @@ exit_failure:
3356 swtpm_cleanup(mlp.cc);
3357
3358 exit(EXIT_FAILURE);
3359+
3360+exit_success:
3361+ swtpm_cleanup(mlp.cc);
3362+
3363+ exit(EXIT_SUCCESS);
3364 }
3365diff --git a/src/swtpm/swtpm_nvfile.c b/src/swtpm/swtpm_nvstore.c
3366similarity index 74%
3367rename from src/swtpm/swtpm_nvfile.c
3368rename to src/swtpm/swtpm_nvstore.c
3369index 7f69cbd..144d897 100644
3370--- a/src/swtpm/swtpm_nvfile.c
3371+++ b/src/swtpm/swtpm_nvstore.c
3372@@ -68,8 +68,12 @@
3373 #include <libtpms/tpm_library.h>
3374
3375 #include <openssl/sha.h>
3376-#include <openssl/hmac.h>
3377 #include <openssl/rand.h>
3378+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3379+# include <openssl/core_names.h>
3380+#else
3381+# include <openssl/hmac.h>
3382+#endif
3383
3384 #if defined(__OpenBSD__)
3385 # define OPENSSL_OLD_API
3386@@ -82,13 +86,15 @@
3387 #include "swtpm.h"
3388 #include "swtpm_aes.h"
3389 #include "swtpm_debug.h"
3390-#include "swtpm_nvfile.h"
3391+#include "swtpm_nvstore.h"
3392+#include "swtpm_utils.h"
3393 #include "key.h"
3394 #include "logging.h"
3395 #include "tpmstate.h"
3396 #include "tpmlib.h"
3397 #include "tlv.h"
3398 #include "utils.h"
3399+#include "compiler_dependencies.h"
3400
3401 /* local structures */
3402 typedef struct {
3403@@ -127,15 +133,10 @@ static encryptionkey migrationkey = {
3404
3405 static uint32_t g_ivec_length;
3406 static unsigned char *g_ivec;
3407+static struct nvram_backend_ops *g_nvram_backend_ops;
3408
3409 /* local prototypes */
3410
3411-static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename,
3412- size_t bufsize,
3413- uint32_t tpm_number,
3414- const char *name,
3415- bool is_tempfile);
3416-
3417 static TPM_RESULT SWTPM_NVRAM_EncryptData(const encryptionkey *key,
3418 tlv_data *td,
3419 size_t *td_len,
3420@@ -166,124 +167,86 @@ static TPM_RESULT SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,
3421 uint8_t *hdrversion,
3422 bool quiet);
3423
3424-/* A file name in NVRAM is composed of 3 parts:
3425-
3426- 1 - 'state_directory' is the rooted path to the TPM state home directory
3427- 2 = 'tpm_number' is the TPM instance, 00 for a single TPM
3428- 2 - the file name
3429+/* SWTPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization.
3430
3431- For the IBM cryptographic coprocessor version, the root path is hard coded.
3432-
3433- For the Linux and Windows versions, the path comes from an environment variable. This variable is
3434- used once in TPM_NVRAM_Init().
3435-
3436- One root path is used for all virtual TPM's, so it can be a static variable.
3437+ This function sets some static variables that are used by all TPM's.
3438 */
3439
3440-static int lockfile_fd = -1;
3441-
3442-char state_directory[FILENAME_MAX];
3443-static TPMLIB_TPMVersion tpmversion = TPMLIB_TPM_VERSION_1_2;
3444-
3445-/*
3446- * SWTPM_NVRAM_Set_TPMVersion() - set the version of the TPM being used
3447- */
3448-void SWTPM_NVRAM_Set_TPMVersion(TPMLIB_TPMVersion version)
3449-{
3450- tpmversion = version;
3451-}
3452-
3453-static TPM_RESULT SWTPM_NVRAM_Lock_Lockfile(const char *directory,
3454- int *fd)
3455+TPM_RESULT SWTPM_NVRAM_Init(void)
3456 {
3457- TPM_RESULT rc = 0;
3458- char *lockfile = NULL;
3459- struct flock flock = {
3460- .l_type = F_WRLCK,
3461- .l_whence = SEEK_SET,
3462- .l_start = 0,
3463- .l_len = 0,
3464- };
3465-
3466- if (asprintf(&lockfile, "%s/.lock", directory) < 0) {
3467- logprintf(STDERR_FILENO,
3468- "SWTPM_NVRAM_Lock_Lockfile: Could not asprintf lock filename\n");
3469- return TPM_FAIL;
3470- }
3471+ const char *backend_uri;
3472+ TPM_RESULT rc = 0;
3473+ TPM_DEBUG(" SWTPM_NVRAM_Init:\n");
3474
3475- *fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0660);
3476- if (*fd < 0) {
3477+ backend_uri = tpmstate_get_backend_uri();
3478+ if (!backend_uri) {
3479 logprintf(STDERR_FILENO,
3480- "SWTPM_NVRAM_Lock_Lockfile: Could not open lockfile: %s\n",
3481- strerror(errno));
3482+ "SWTPM_NVRAM_Init: Missing backend URI.\n");
3483 rc = TPM_FAIL;
3484- goto exit;
3485- }
3486-
3487- if (fcntl(*fd, F_SETLK, &flock) < 0) {
3488+ } else if (strncmp(backend_uri, "dir://", 6) == 0) {
3489+ g_nvram_backend_ops = &nvram_dir_ops;
3490+ } else if (strncmp(backend_uri, "file://", 7) == 0) {
3491+ g_nvram_backend_ops = &nvram_linear_ops;
3492+ } else {
3493 logprintf(STDERR_FILENO,
3494- "SWTPM_NVRAM_Lock_Lockfile: Could not lock access to lockfile: %s\n",
3495- strerror(errno));
3496+ "SWTPM_NVRAM_Init: Unsupported backend.\n");
3497 rc = TPM_FAIL;
3498- close(*fd);
3499- *fd = -1;
3500 }
3501-exit:
3502- free(lockfile);
3503+
3504+ if (rc == 0)
3505+ rc = g_nvram_backend_ops->prepare(backend_uri);
3506
3507 return rc;
3508 }
3509
3510-/* TPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization.
3511+void SWTPM_NVRAM_Shutdown(void)
3512+{
3513+ if (g_nvram_backend_ops)
3514+ g_nvram_backend_ops->cleanup();
3515+ memset(&filekey, 0, sizeof(filekey));
3516+ memset(&migrationkey, 0, sizeof(migrationkey));
3517+}
3518
3519- This function sets some static variables that are used by all TPM's.
3520-*/
3521+/* SWTPM_NVRAM_GetFilenameForName() constructs a file name from the name.
3522+ * A temporary filename used to write to may be created. It should be rename()'d to
3523+ * the non-temporary filename.
3524+ */
3525
3526-TPM_RESULT SWTPM_NVRAM_Init(void)
3527+TPM_RESULT
3528+SWTPM_NVRAM_GetFilenameForName(char *filename, /* output: filename */
3529+ size_t bufsize,
3530+ uint32_t tpm_number,
3531+ const char *name, /* input: abstract name */
3532+ TPM_BOOL is_tempfile) /* input: is temporary file? */
3533 {
3534- TPM_RESULT rc = 0;
3535- const char *tpm_state_path;
3536- size_t length;
3537+ TPM_RESULT res = TPM_SUCCESS;
3538+ int n;
3539+ const char *suffix = "";
3540
3541- TPM_DEBUG(" SWTPM_NVRAM_Init:\n");
3542+ TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: For name %s\n", name);
3543
3544- /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */
3545- if (rc == 0) {
3546- tpm_state_path = tpmstate_get_dir();
3547- if (tpm_state_path == NULL) {
3548- logprintf(STDERR_FILENO,
3549- "SWTPM_NVRAM_Init: Error (fatal), TPM_PATH environment "
3550- "variable not set\n");
3551- rc = TPM_FAIL;
3552- }
3553+ switch (tpmstate_get_version()) {
3554+ case TPMLIB_TPM_VERSION_1_2:
3555+ break;
3556+ case TPMLIB_TPM_VERSION_2:
3557+ suffix = "2";
3558+ break;
3559 }
3560
3561- /* check that the directory name plus a file name will not overflow FILENAME_MAX */
3562- if (rc == 0) {
3563- length = strlen(tpm_state_path);
3564- if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) {
3565- logprintf(STDERR_FILENO,
3566- "SWTPM_NVRAM_Init: Error (fatal), TPM state path name "
3567- "%s too large\n", tpm_state_path);
3568- rc = TPM_FAIL;
3569- }
3570+ if (is_tempfile) {
3571+ n = snprintf(filename, bufsize, "TMP%s-%02lx.%s", suffix, (unsigned long)tpm_number, name);
3572+ } else {
3573+ n = snprintf(filename, bufsize, "tpm%s-%02lx.%s", suffix, (unsigned long)tpm_number, name);
3574 }
3575- if (rc == 0) {
3576- strcpy(state_directory, tpm_state_path);
3577- TPM_DEBUG("TPM_NVRAM_Init: Rooted state path %s\n", state_directory);
3578+ if ((size_t)n > bufsize) {
3579+ res = TPM_FAIL;
3580 }
3581
3582- if (rc == 0 && lockfile_fd < 0)
3583- rc = SWTPM_NVRAM_Lock_Lockfile(state_directory, &lockfile_fd);
3584+ TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: File name %s\n", filename);
3585
3586- return rc;
3587+ return res;
3588 }
3589
3590-void SWTPM_NVRAM_Shutdown(void)
3591-{
3592- memset(&filekey, 0, sizeof(filekey));
3593- memset(&migrationkey, 0, sizeof(migrationkey));
3594-}
3595
3596 /* Load 'data' of 'length' from the 'name'.
3597
3598@@ -302,101 +265,22 @@ SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */
3599 const char *name)
3600 {
3601 TPM_RESULT rc = 0;
3602- size_t src;
3603 int irc;
3604- int fd = -1;
3605- char filename[FILENAME_MAX]; /* rooted file name from name */
3606 unsigned char *decrypt_data = NULL;
3607 uint32_t decrypt_length;
3608 uint32_t dataoffset = 0;
3609 uint8_t hdrversion = 0;
3610 uint16_t hdrflags;
3611- struct stat statbuf;
3612+ const char *backend_uri = NULL;
3613
3614 TPM_DEBUG(" SWTPM_NVRAM_LoadData: From file %s\n", name);
3615 *data = NULL;
3616 *length = 0;
3617- /* open the file */
3618- if (rc == 0) {
3619- /* map name to the rooted filename */
3620- rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
3621- tpm_number, name, false);
3622- }
3623
3624 if (rc == 0) {
3625- TPM_DEBUG(" SWTPM_NVRAM_LoadData: Opening file %s\n", filename);
3626- fd = open(filename, O_RDONLY); /* closed @1 */
3627- if (fd < 0) { /* if failure, determine cause */
3628- if (errno == ENOENT) {
3629- TPM_DEBUG("SWTPM_NVRAM_LoadData: No such file %s\n",
3630- filename);
3631- rc = TPM_RETRY; /* first time start up */
3632- }
3633- else {
3634- logprintf(STDERR_FILENO,
3635- "SWTPM_NVRAM_LoadData: Error (fatal) opening "
3636- "%s for read, %s\n", filename, strerror(errno));
3637- rc = TPM_FAIL;
3638- }
3639- }
3640- }
3641-
3642- if (rc == 0) {
3643- if (fchmod(fd, tpmstate_get_mode()) < 0) {
3644- logprintf(STDERR_FILENO,
3645- "SWTPM_NVRAM_LoadData: Could not fchmod %s : %s\n",
3646- filename, strerror(errno));
3647- rc = TPM_FAIL;
3648- }
3649- }
3650-
3651- /* determine the file length */
3652- if (rc == 0) {
3653- irc = fstat(fd, &statbuf);
3654- if (irc == -1L) {
3655- logprintf(STDERR_FILENO,
3656- "SWTPM_NVRAM_LoadData: Error (fatal) fstat'ing %s, %s\n",
3657- filename, strerror(errno));
3658- rc = TPM_FAIL;
3659- }
3660- }
3661- if (rc == 0) {
3662- *length = statbuf.st_size; /* save the length */
3663- }
3664- /* allocate a buffer for the actual data */
3665- if ((rc == 0) && *length != 0) {
3666- TPM_DEBUG(" SWTPM_NVRAM_LoadData: Reading %u bytes of data\n", *length);
3667- *data = malloc(*length);
3668- if (!*data) {
3669- logprintf(STDERR_FILENO,
3670- "SWTPM_NVRAM_LoadData: Error (fatal) allocating %u "
3671- "bytes\n", *length);
3672- rc = TPM_FAIL;
3673- }
3674- }
3675- /* read the contents of the file into the data buffer */
3676- if ((rc == 0) && *length != 0) {
3677- src = read(fd, *data, *length);
3678- if (src != *length) {
3679- logprintf(STDERR_FILENO,
3680- "SWTPM_NVRAM_LoadData: Error (fatal), data read of %u "
3681- "only read %lu\n", *length, (unsigned long)src);
3682- rc = TPM_FAIL;
3683- }
3684- }
3685- /* close the file */
3686- if (fd >= 0) {
3687- TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closing file %s\n", filename);
3688- irc = close(fd); /* @1 */
3689- if (irc != 0) {
3690- logprintf(STDERR_FILENO,
3691- "SWTPM_NVRAM_LoadData: Error (fatal) closing file %s\n",
3692- filename);
3693- rc = TPM_FAIL;
3694- }
3695- else {
3696- TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closed file %s\n", filename);
3697- }
3698+ backend_uri = tpmstate_get_backend_uri();
3699+ rc = g_nvram_backend_ops->load(data, length, tpm_number, name,
3700+ backend_uri);
3701 }
3702
3703 if (rc == 0) {
3704@@ -460,43 +344,14 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data,
3705 TPM_BOOL encrypt /* encrypt if key is set */)
3706 {
3707 TPM_RESULT rc = 0;
3708- uint32_t lrc;
3709- int irc;
3710- int fd = -1;
3711- char tmpfile[FILENAME_MAX]; /* rooted temporary file */
3712- char filename[FILENAME_MAX]; /* rooted file name from name */
3713 unsigned char *filedata = NULL;
3714 uint32_t filedata_length = 0;
3715 tlv_data td[3];
3716 size_t td_len = 0;
3717 uint16_t flags = 0;
3718+ const char *backend_uri = NULL;
3719
3720 TPM_DEBUG(" SWTPM_NVRAM_StoreData: To name %s\n", name);
3721- if (rc == 0) {
3722- /* map name to the rooted filename */
3723- rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
3724- tpm_number, name, false);
3725- }
3726-
3727- if (rc == 0) {
3728- /* map name to the rooted temporary file */
3729- rc = SWTPM_NVRAM_GetFilenameForName(tmpfile, sizeof(tmpfile),
3730- tpm_number, name, true);
3731- }
3732-
3733-
3734- if (rc == 0) {
3735- /* open the file */
3736- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile);
3737- fd = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW,
3738- tpmstate_get_mode()); /* closed @1 */
3739- if (fd < 0) {
3740- logprintf(STDERR_FILENO,
3741- "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for "
3742- "write failed, %s\n", tmpfile, strerror(errno));
3743- rc = TPM_FAIL;
3744- }
3745- }
3746
3747 if (rc == 0) {
3748 if (encrypt && SWTPM_NVRAM_Has_FileKey()) {
3749@@ -527,44 +382,10 @@ SWTPM_NVRAM_StoreData_Intern(const unsigned char *data,
3750 if (rc == 0)
3751 rc = SWTPM_NVRAM_PrependHeader(&filedata, &filedata_length, flags);
3752
3753- /* write the data to the file */
3754 if (rc == 0) {
3755- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Writing %u bytes of data\n", length);
3756- lrc = write_full(fd, filedata, filedata_length);
3757- if (lrc != filedata_length) {
3758- logprintf(STDERR_FILENO,
3759- "TPM_NVRAM_StoreData: Error (fatal), data write "
3760- "of %u only wrote %u\n", filedata_length, lrc);
3761- rc = TPM_FAIL;
3762- }
3763- }
3764- if (fd >= 0) {
3765- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile);
3766- irc = close(fd); /* @1 */
3767- if (irc != 0) {
3768- logprintf(STDERR_FILENO,
3769- "SWTPM_NVRAM_StoreData: Error (fatal) closing file\n");
3770- rc = TPM_FAIL;
3771- }
3772- else {
3773- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", tmpfile);
3774- }
3775- }
3776-
3777- if (rc == 0 && fd >= 0) {
3778- irc = rename(tmpfile, filename);
3779- if (irc != 0) {
3780- logprintf(STDERR_FILENO,
3781- "SWTPM_NVRAM_StoreData: Error (fatal) renaming file: %s\n",
3782- strerror(errno));
3783- rc = TPM_FAIL;
3784- } else {
3785- TPM_DEBUG(" SWTPM_NVRAM_StoreData: Renamed file to %s\n", filename);
3786- }
3787- }
3788-
3789- if (rc != 0 && fd >= 0) {
3790- unlink(tmpfile);
3791+ backend_uri = tpmstate_get_backend_uri();
3792+ rc = g_nvram_backend_ops->store(filedata, filedata_length, tpm_number, name,
3793+ backend_uri);
3794 }
3795
3796 tlv_data_free(td, td_len);
3797@@ -583,53 +404,7 @@ TPM_RESULT SWTPM_NVRAM_StoreData(const unsigned char *data,
3798 return SWTPM_NVRAM_StoreData_Intern(data, length, tpm_number, name, TRUE);
3799 }
3800
3801-/* SWTPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name.
3802-
3803- The filename is of the form:
3804-
3805- state_directory/tpm_number.name
3806-
3807- A temporary filename used to write to may be created. It shold be rename()'d to
3808- the non-temporary filename.
3809-*/
3810-
3811-static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */
3812- size_t bufsize,
3813- uint32_t tpm_number,
3814- const char *name, /* input: abstract name */
3815- bool is_tempfile) /* input: is temporary file? */
3816-{
3817- TPM_RESULT res = TPM_SUCCESS;
3818- int n;
3819- const char *suffix = "";
3820-
3821- TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: For name %s\n", name);
3822-
3823- switch (tpmversion) {
3824- case TPMLIB_TPM_VERSION_1_2:
3825- break;
3826- case TPMLIB_TPM_VERSION_2:
3827- suffix = "2";
3828- break;
3829- }
3830-
3831- if (is_tempfile) {
3832- n = snprintf(filename, bufsize, "%s/TMP%s-%02lx.%s",
3833- state_directory, suffix, (unsigned long)tpm_number, name);
3834- } else {
3835- n = snprintf(filename, bufsize, "%s/tpm%s-%02lx.%s",
3836- state_directory, suffix, (unsigned long)tpm_number, name);
3837- }
3838- if ((size_t)n > bufsize) {
3839- res = TPM_FAIL;
3840- }
3841-
3842- TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: File name %s\n", filename);
3843-
3844- return res;
3845-}
3846-
3847-/* TPM_NVRAM_DeleteName() deletes the 'name' from NVRAM
3848+/* SWTPM_NVRAM_DeleteName() deletes the 'name' from NVRAM
3849
3850 Returns:
3851 0 on success, or if the file does not exist and mustExist is FALSE
3852@@ -643,26 +418,11 @@ TPM_RESULT SWTPM_NVRAM_DeleteName(uint32_t tpm_number,
3853 const char *name,
3854 TPM_BOOL mustExist)
3855 {
3856- TPM_RESULT rc = 0;
3857- int irc;
3858- char filename[FILENAME_MAX]; /* rooted file name from name */
3859+ const char *backend_uri = NULL;
3860+ backend_uri = tpmstate_get_backend_uri();
3861
3862- TPM_DEBUG(" SWTPM_NVRAM_DeleteName: Name %s\n", name);
3863- /* map name to the rooted filename */
3864- rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
3865- tpm_number, name, false);
3866- if (rc == 0) {
3867- irc = remove(filename);
3868- if ((irc != 0) && /* if the remove failed */
3869- (mustExist || /* if any error is a failure, or */
3870- (errno != ENOENT))) { /* if error other than no such file */
3871- logprintf(STDERR_FILENO,
3872- "SWTPM_NVRAM_DeleteName: Error, (fatal) file "
3873- "remove failed, errno %d\n", errno);
3874- rc = TPM_FAIL;
3875- }
3876- }
3877- return rc;
3878+ return g_nvram_backend_ops->delete(tpm_number, name, mustExist,
3879+ backend_uri);
3880 }
3881
3882
3883@@ -751,6 +511,54 @@ TPM_RESULT SWTPM_NVRAM_Set_MigrationKey(const unsigned char *key,
3884 return rc;
3885 }
3886
3887+# if OPENSSL_VERSION_NUMBER >= 0x30000000L
3888+
3889+static int SWTPM_HMAC(unsigned char *md, unsigned int *md_len,
3890+ const void *key, int key_len,
3891+ const unsigned char *in, uint32_t in_length,
3892+ const unsigned char *ivec, uint32_t ivec_length)
3893+{
3894+ OSSL_PARAM params[2];
3895+ EVP_MAC_CTX *ctx;
3896+ EVP_MAC *hmac;
3897+ size_t outl;
3898+ int ret = 0;
3899+
3900+ hmac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL);
3901+ if (!hmac)
3902+ return 0;
3903+
3904+ ctx = EVP_MAC_CTX_new(hmac);
3905+ if (!ctx)
3906+ goto err;
3907+
3908+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST,
3909+ "sha256", 0);
3910+ params[1] = OSSL_PARAM_construct_end();
3911+
3912+ if (!EVP_MAC_init(ctx, key, key_len, params) ||
3913+ !EVP_MAC_update(ctx, in, in_length))
3914+ goto err;
3915+
3916+ if (ivec &&
3917+ !EVP_MAC_update(ctx, ivec, ivec_length))
3918+ goto err;
3919+
3920+ if (!EVP_MAC_final(ctx, md, &outl, *md_len))
3921+ goto err;
3922+ *md_len = outl;
3923+
3924+ ret = 1;
3925+
3926+err:
3927+ EVP_MAC_CTX_free(ctx);
3928+ EVP_MAC_free(hmac);
3929+
3930+ return ret;
3931+}
3932+
3933+#else
3934+
3935 static int SWTPM_HMAC(unsigned char *md, unsigned int *md_len,
3936 const void *key, int key_len,
3937 const unsigned char *in, uint32_t in_length,
3938@@ -792,6 +600,7 @@ err:
3939
3940 return ret;
3941 }
3942+#endif /* if OPENSSL_VERSION_NUMBER >= 0x30000000L */
3943
3944 /*
3945 * SWTPM_RollAndSetGlobalIvec: Create an IV for the AES CBC algorithm to use
3946@@ -878,8 +687,8 @@ SWTPM_CalcHMAC(const unsigned char *in, uint32_t in_length,
3947 const unsigned char *ivec, uint32_t ivec_length)
3948 {
3949 TPM_RESULT rc = 0;
3950- unsigned int md_len;
3951 unsigned char md[EVP_MAX_MD_SIZE];
3952+ unsigned int md_len = sizeof(md);
3953 unsigned char *buffer = NULL;
3954
3955 if (!SWTPM_HMAC(md, &md_len,
3956@@ -1409,7 +1218,7 @@ err_exit:
3957 TPM_RESULT SWTPM_NVRAM_SetStateBlob(unsigned char *data,
3958 uint32_t length,
3959 TPM_BOOL is_encrypted,
3960- uint32_t tpm_number,
3961+ uint32_t tpm_number SWTPM_ATTR_UNUSED,
3962 uint32_t blobtype)
3963 {
3964 TPM_RESULT res;
3965@@ -1519,3 +1328,51 @@ cleanup:
3966
3967 return res;
3968 }
3969+
3970+/* Example JSON output:
3971+ * { "type": "swtpm",
3972+ * "states": [ "permall", "volatilestate", "savestate" ]
3973+ * }
3974+ */
3975+int SWTPM_NVRAM_PrintJson(void)
3976+{
3977+ TPM_RESULT rc = 0;
3978+ const char *backend_uri;
3979+ const char *states[] = {
3980+ TPM_PERMANENT_ALL_NAME,
3981+ TPM_VOLATILESTATE_NAME,
3982+ TPM_SAVESTATE_NAME,
3983+ };
3984+ char state_str[200] = "";
3985+ size_t i, n, o, blobsize;
3986+ int ret = -1;
3987+
3988+ rc = SWTPM_NVRAM_Init();
3989+ if (rc == 0) {
3990+ o = 0;
3991+ backend_uri = tpmstate_get_backend_uri();
3992+
3993+ for (i = 0; i < ARRAY_LEN(states); i++) {
3994+ rc = g_nvram_backend_ops->check_state(backend_uri, states[i],
3995+ &blobsize);
3996+ if (rc == TPM_SUCCESS) {
3997+ n = snprintf(&state_str[o], sizeof(state_str) - o,
3998+ "%s {\"name\": \"%s\", \"size\": %zu}",
3999+ (o > 0) ? "," : "",
4000+ states[i], blobsize);
4001+ if (n >= sizeof(state_str) - o)
4002+ goto exit;
4003+ o += n;
4004+ } else if (rc != TPM_RETRY) {
4005+ /* Error other than ENOENT */
4006+ goto exit;
4007+ }
4008+ }
4009+ printf("{ \"type\": \"swtpm\", \"states\": [%s%s] }",
4010+ state_str, (o > 0) ? " ": "");
4011+ ret = 0;
4012+ }
4013+
4014+exit:
4015+ return ret;
4016+}
4017diff --git a/src/swtpm/swtpm_nvfile.h b/src/swtpm/swtpm_nvstore.h
4018similarity index 80%
4019rename from src/swtpm/swtpm_nvfile.h
4020rename to src/swtpm/swtpm_nvstore.h
4021index 25c18a9..6e34891 100644
4022--- a/src/swtpm/swtpm_nvfile.h
4023+++ b/src/swtpm/swtpm_nvstore.h
4024@@ -36,29 +36,19 @@
4025 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
4026 /********************************************************************************/
4027
4028-#ifndef _SWTPM_NVFILE_H
4029-#define _SWTPM_NVFILE_H
4030+#ifndef _SWTPM_NVSTORE_H
4031+#define _SWTPM_NVSTORE_H
4032
4033+#include <stdio.h>
4034 #include <libtpms/tpm_types.h>
4035+#include <libtpms/tpm_library.h>
4036
4037 #include "key.h"
4038
4039-/* characters in the TPM base file name, 14 for file name, slash, NUL terminator, etc.
4040-
4041- This macro is used once during initialization to ensure that the TPM_PATH environment variable
4042- length will not cause the rooted file name to overflow file name buffers.
4043-*/
4044-
4045-#define TPM_FILENAME_MAX 20
4046-
4047-#include <libtpms/tpm_library.h>
4048-
4049 TPM_RESULT SWTPM_NVRAM_Init(void);
4050
4051 void SWTPM_NVRAM_Shutdown(void);
4052
4053-void SWTPM_NVRAM_Set_TPMVersion(TPMLIB_TPMVersion version);
4054-
4055 /*
4056 Basic abstraction for read and write
4057 */
4058@@ -97,6 +87,12 @@ TPM_RESULT SWTPM_NVRAM_SetStateBlob(unsigned char *data,
4059 uint32_t tpm_number,
4060 uint32_t blobtype);
4061
4062+TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename,
4063+ size_t bufsize,
4064+ uint32_t tpm_number,
4065+ const char *name,
4066+ TPM_BOOL is_tempfile);
4067+
4068 size_t SWTPM_NVRAM_FileKey_Size(void);
4069 static inline TPM_BOOL SWTPM_NVRAM_Has_FileKey(void)
4070 {
4071@@ -109,5 +105,33 @@ static inline TPM_BOOL SWTPM_NVRAM_Has_MigrationKey(void)
4072 return SWTPM_NVRAM_MigrationKey_Size() > 0;
4073 }
4074
4075-#endif /* _SWTPM_NVFILE_H */
4076-
4077+struct nvram_backend_ops {
4078+ TPM_RESULT (*prepare)(const char *uri);
4079+ TPM_RESULT (*load)(unsigned char **data,
4080+ uint32_t *length,
4081+ uint32_t tpm_number,
4082+ const char *name,
4083+ const char *uri);
4084+ TPM_RESULT (*store)(unsigned char *edata,
4085+ uint32_t data_length,
4086+ uint32_t tpm_number,
4087+ const char *name,
4088+ const char *uri);
4089+ TPM_RESULT (*delete)(uint32_t tpm_number,
4090+ const char *name,
4091+ TPM_BOOL mustExist,
4092+ const char *uri);
4093+ TPM_RESULT (*check_state)(const char *uri,
4094+ const char *name,
4095+ size_t *blobsize);
4096+ void (*cleanup)(void);
4097+};
4098+
4099+/* backend interfaces */
4100+extern struct nvram_backend_ops nvram_dir_ops;
4101+extern struct nvram_backend_ops nvram_linear_ops;
4102+
4103+
4104+int SWTPM_NVRAM_PrintJson(void);
4105+
4106+#endif /* _SWTPM_NVSTORE_H */
4107diff --git a/src/swtpm/swtpm_nvstore_dir.c b/src/swtpm/swtpm_nvstore_dir.c
4108new file mode 100644
4109index 0000000..ba7bd62
4110--- /dev/null
4111+++ b/src/swtpm/swtpm_nvstore_dir.c
4112@@ -0,0 +1,527 @@
4113+/********************************************************************************/
4114+/* */
4115+/* NVRAM File Abstraction Layer */
4116+/* Written by Ken Goldman */
4117+/* Adapted to SWTPM by Stefan Berger */
4118+/* IBM Thomas J. Watson Research Center */
4119+/* */
4120+/* (c) Copyright IBM Corporation 2006, 2010, 2014, 2015. */
4121+/* */
4122+/* All rights reserved. */
4123+/* */
4124+/* Redistribution and use in source and binary forms, with or without */
4125+/* modification, are permitted provided that the following conditions are */
4126+/* met: */
4127+/* */
4128+/* Redistributions of source code must retain the above copyright notice, */
4129+/* this list of conditions and the following disclaimer. */
4130+/* */
4131+/* Redistributions in binary form must reproduce the above copyright */
4132+/* notice, this list of conditions and the following disclaimer in the */
4133+/* documentation and/or other materials provided with the distribution. */
4134+/* */
4135+/* Neither the names of the IBM Corporation nor the names of its */
4136+/* contributors may be used to endorse or promote products derived from */
4137+/* this software without specific prior written permission. */
4138+/* */
4139+/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
4140+/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
4141+/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
4142+/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
4143+/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
4144+/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
4145+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
4146+/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
4147+/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
4148+/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
4149+/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
4150+/********************************************************************************/
4151+
4152+#include "config.h"
4153+
4154+#define _GNU_SOURCE
4155+#include <stdio.h>
4156+#include <string.h>
4157+#include <stdlib.h>
4158+#include <errno.h>
4159+#include <sys/stat.h>
4160+#include <fcntl.h>
4161+
4162+#include <libtpms/tpm_error.h>
4163+
4164+#include "swtpm.h"
4165+#include "swtpm_debug.h"
4166+#include "swtpm_nvstore.h"
4167+#include "key.h"
4168+#include "logging.h"
4169+#include "tpmstate.h"
4170+#include "utils.h"
4171+
4172+#define TPM_FILENAME_MAX 20
4173+
4174+static int lock_fd = -1;
4175+
4176+static const char *
4177+SWTPM_NVRAM_Uri_to_Dir(const char *uri)
4178+{
4179+ return uri + strlen("dir://");
4180+}
4181+
4182+static TPM_RESULT
4183+SWTPM_NVRAM_Validate_Dir(const char *tpm_state_path)
4184+{
4185+ TPM_RESULT rc = 0;
4186+ size_t length;
4187+
4188+ /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */
4189+ if (rc == 0) {
4190+ if (tpm_state_path == NULL) {
4191+ logprintf(STDERR_FILENO,
4192+ "SWTPM_NVRAM_Validate_Dir: Error (fatal), TPM_PATH environment "
4193+ "variable not set\n");
4194+ rc = TPM_FAIL;
4195+ }
4196+ }
4197+
4198+ /* check that the directory name plus a file name will not overflow FILENAME_MAX */
4199+ if (rc == 0) {
4200+ length = strlen(tpm_state_path);
4201+ if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) {
4202+ logprintf(STDERR_FILENO,
4203+ "SWTPM_NVRAM_Validate_Dir: Error (fatal), TPM state path name "
4204+ "%s too large\n", tpm_state_path);
4205+ rc = TPM_FAIL;
4206+ }
4207+ }
4208+ if (rc == 0) {
4209+ TPM_DEBUG("SWTPM_NVRAM_Validate_Dir: Rooted state path %s\n", tpm_state_path);
4210+ }
4211+
4212+ return rc;
4213+}
4214+
4215+static void
4216+SWTPM_NVRAM_Unlock_Dir(void)
4217+{
4218+ if (lock_fd >= 0) {
4219+ close(lock_fd);
4220+ lock_fd = -1;
4221+ }
4222+}
4223+
4224+static TPM_RESULT
4225+SWTPM_NVRAM_Lock_Dir(const char *tpm_state_path)
4226+{
4227+ TPM_RESULT rc = 0;
4228+ char *lockfile = NULL;
4229+ struct flock flock = {
4230+ .l_type = F_WRLCK,
4231+ .l_whence = SEEK_SET,
4232+ .l_start = 0,
4233+ .l_len = 0,
4234+ };
4235+
4236+ if (asprintf(&lockfile, "%s/.lock", tpm_state_path) < 0) {
4237+ logprintf(STDERR_FILENO,
4238+ "SWTPM_NVRAM_Lock_Dir: Could not asprintf lock filename\n");
4239+ return TPM_FAIL;
4240+ }
4241+
4242+ lock_fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0660);
4243+ if (lock_fd < 0) {
4244+ logprintf(STDERR_FILENO,
4245+ "SWTPM_NVRAM_Lock_Dir: Could not open lockfile: %s\n",
4246+ strerror(errno));
4247+ rc = TPM_FAIL;
4248+ goto exit;
4249+ }
4250+
4251+ if (fcntl(lock_fd, F_SETLK, &flock) < 0) {
4252+ logprintf(STDERR_FILENO,
4253+ "SWTPM_NVRAM_Lock_Dir: Could not lock access to lockfile: %s\n",
4254+ strerror(errno));
4255+ rc = TPM_FAIL;
4256+ SWTPM_NVRAM_Unlock_Dir();
4257+ }
4258+exit:
4259+ free(lockfile);
4260+
4261+ return rc;
4262+}
4263+
4264+static TPM_RESULT
4265+SWTPM_NVRAM_GetFilepathForName(char *filepath, /* output: rooted file path */
4266+ size_t bufsize,
4267+ uint32_t tpm_number,
4268+ const char *name, /* input: abstract name */
4269+ TPM_BOOL is_tempfile, /* input: is temporary file? */
4270+ const char *tpm_state_path)
4271+{
4272+ TPM_RESULT rc = 0;
4273+ int n;
4274+ char filename[FILENAME_MAX];
4275+
4276+ if (rc == 0)
4277+ rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename),
4278+ tpm_number, name, is_tempfile);
4279+ if (rc == 0) {
4280+ n = snprintf(filepath, bufsize, "%s/%s", tpm_state_path, filename);
4281+ if ((size_t) n > bufsize)
4282+ rc = TPM_FAIL;
4283+ }
4284+
4285+ return rc;
4286+}
4287+
4288+static TPM_RESULT
4289+SWTPM_NVRAM_CheckState_Dir(const char *uri,
4290+ const char *name,
4291+ size_t *blobsize)
4292+{
4293+ TPM_RESULT rc = 0;
4294+ char filepath[FILENAME_MAX]; /* rooted file path from name */
4295+ struct stat statbuf;
4296+ const char *tpm_state_path = NULL;
4297+ uint32_t tpm_number = 0;
4298+ int rc2;
4299+
4300+ tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri);
4301+ if (rc == 0) {
4302+ /* map name to the rooted file path */
4303+ rc = SWTPM_NVRAM_GetFilepathForName(filepath, sizeof(filepath),
4304+ tpm_number, name, false,
4305+ tpm_state_path);
4306+ }
4307+
4308+ if (rc == 0) {
4309+ rc2 = stat(filepath, &statbuf);
4310+ if (rc2 != 0 && errno == ENOENT)
4311+ rc = TPM_RETRY;
4312+ else if (rc2 != 0)
4313+ rc = TPM_FAIL;
4314+ else if (!S_ISREG(statbuf.st_mode))
4315+ rc = TPM_FAIL;
4316+
4317+ if (rc == 0)
4318+ *blobsize = statbuf.st_size;
4319+ }
4320+
4321+ return rc;
4322+}
4323+
4324+static TPM_RESULT
4325+SWTPM_NVRAM_Prepare_Dir(const char *uri)
4326+{
4327+ TPM_RESULT rc = 0;
4328+ const char *tpm_state_path = NULL;
4329+
4330+ tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri);
4331+ if (rc == 0)
4332+ rc = SWTPM_NVRAM_Validate_Dir(tpm_state_path);
4333+ if (rc == 0)
4334+ rc = SWTPM_NVRAM_Lock_Dir(tpm_state_path);
4335+
4336+ return rc;
4337+}
4338+
4339+static void
4340+SWTPM_NVRAM_Cleanup_Dir(void)
4341+{
4342+ SWTPM_NVRAM_Unlock_Dir();
4343+}
4344+
4345+static TPM_RESULT
4346+SWTPM_NVRAM_LoadData_Dir(unsigned char **data,
4347+ uint32_t *length,
4348+ uint32_t tpm_number,
4349+ const char *name,
4350+ const char *uri)
4351+{
4352+ TPM_RESULT rc = 0;
4353+ int irc;
4354+ size_t src;
4355+ int fd = -1;
4356+ char filepath[FILENAME_MAX]; /* rooted file path from name */
4357+ struct stat statbuf;
4358+ const char *tpm_state_path = NULL;
4359+
4360+ tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri);
4361+
4362+ if (rc == 0) {
4363+ /* map name to the rooted file path */
4364+ rc = SWTPM_NVRAM_GetFilepathForName(filepath, sizeof(filepath),
4365+ tpm_number, name, false,
4366+ tpm_state_path);
4367+ }
4368+
4369+ /* open the file */
4370+ if (rc == 0) {
4371+ TPM_DEBUG(" SWTPM_NVRAM_LoadData: Opening file %s\n", filepath);
4372+ fd = open(filepath, O_RDONLY); /* closed @1 */
4373+ if (fd < 0) { /* if failure, determine cause */
4374+ if (errno == ENOENT) {
4375+ TPM_DEBUG("SWTPM_NVRAM_LoadData: No such file %s\n",
4376+ filepath);
4377+ rc = TPM_RETRY; /* first time start up */
4378+ }
4379+ else {
4380+ logprintf(STDERR_FILENO,
4381+ "SWTPM_NVRAM_LoadData: Error (fatal) opening "
4382+ "%s for read, %s\n", filepath, strerror(errno));
4383+ rc = TPM_FAIL;
4384+ }
4385+ }
4386+ }
4387+
4388+ if (rc == 0) {
4389+ if (fchmod(fd, tpmstate_get_mode()) < 0) {
4390+ logprintf(STDERR_FILENO,
4391+ "SWTPM_NVRAM_LoadData: Could not fchmod %s : %s\n",
4392+ filepath, strerror(errno));
4393+ rc = TPM_FAIL;
4394+ }
4395+ }
4396+
4397+ /* determine the file length */
4398+ if (rc == 0) {
4399+ irc = fstat(fd, &statbuf);
4400+ if (irc == -1L) {
4401+ logprintf(STDERR_FILENO,
4402+ "SWTPM_NVRAM_LoadData: Error (fatal) fstat'ing %s, %s\n",
4403+ filepath, strerror(errno));
4404+ rc = TPM_FAIL;
4405+ }
4406+ }
4407+ if (rc == 0) {
4408+ *length = statbuf.st_size; /* save the length */
4409+ }
4410+ /* allocate a buffer for the actual data */
4411+ if ((rc == 0) && *length != 0) {
4412+ TPM_DEBUG(" SWTPM_NVRAM_LoadData: Reading %u bytes of data\n", *length);
4413+ *data = malloc(*length);
4414+ if (!*data) {
4415+ logprintf(STDERR_FILENO,
4416+ "SWTPM_NVRAM_LoadData: Error (fatal) allocating %u "
4417+ "bytes\n", *length);
4418+ rc = TPM_FAIL;
4419+ }
4420+ }
4421+ /* read the contents of the file into the data buffer */
4422+ if ((rc == 0) && *length != 0) {
4423+ src = read(fd, *data, *length);
4424+ if (src != *length) {
4425+ logprintf(STDERR_FILENO,
4426+ "SWTPM_NVRAM_LoadData: Error (fatal), data read of %u "
4427+ "only read %lu\n", *length, (unsigned long)src);
4428+ rc = TPM_FAIL;
4429+ }
4430+ }
4431+ /* close the file */
4432+ if (fd >= 0) {
4433+ TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closing file %s\n", filepath);
4434+ irc = close(fd); /* @1 */
4435+ if (irc != 0) {
4436+ logprintf(STDERR_FILENO,
4437+ "SWTPM_NVRAM_LoadData: Error (fatal) closing file %s\n",
4438+ filepath);
4439+ rc = TPM_FAIL;
4440+ }
4441+ else {
4442+ TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closed file %s\n", filepath);
4443+ }
4444+ }
4445+
4446+ return rc;
4447+}
4448+
4449+static TPM_RESULT
4450+SWTPM_NVRAM_StoreData_Dir(unsigned char *filedata,
4451+ uint32_t filedata_length,
4452+ uint32_t tpm_number,
4453+ const char *name,
4454+ const char *uri)
4455+{
4456+ TPM_RESULT rc = 0;
4457+ int fd = -1;
4458+ int dir_fd = -1;
4459+ uint32_t lrc;
4460+ int irc;
4461+ char tmpfile[FILENAME_MAX]; /* rooted temporary file path */
4462+ char filepath[FILENAME_MAX]; /* rooted file path from name */
4463+ const char *tpm_state_path = NULL;
4464+
4465+#if 0
4466+ static bool do_dir_fsync = true; /* turn off fsync on dir if it fails,
4467+ most likely due to AppArmor */
4468+#endif
4469+ /* don't do fsync on dir since this may cause TPM command timeouts */
4470+ static bool do_dir_fsync = false;
4471+
4472+ tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri);
4473+
4474+ if (rc == 0) {
4475+ /* map name to the rooted file path */
4476+ rc = SWTPM_NVRAM_GetFilepathForName(filepath, sizeof(filepath),
4477+ tpm_number, name, false,
4478+ tpm_state_path);
4479+ }
4480+
4481+ if (rc == 0) {
4482+ /* map name to the rooted temporary file path */
4483+ rc = SWTPM_NVRAM_GetFilepathForName(tmpfile, sizeof(tmpfile),
4484+ tpm_number, name, true,
4485+ tpm_state_path);
4486+ }
4487+
4488+ if (rc == 0) {
4489+ /* open the file */
4490+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile);
4491+ fd = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW,
4492+ tpmstate_get_mode()); /* closed @1 */
4493+ if (fd < 0) {
4494+ logprintf(STDERR_FILENO,
4495+ "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for "
4496+ "write failed, %s\n", tmpfile, strerror(errno));
4497+ rc = TPM_FAIL;
4498+ }
4499+ }
4500+
4501+ /* write the data to the file */
4502+ if (rc == 0) {
4503+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Writing %u bytes of data\n",
4504+ filedata_length);
4505+ lrc = write_full(fd, filedata, filedata_length);
4506+ if (lrc != filedata_length) {
4507+ logprintf(STDERR_FILENO,
4508+ "SWTPM_NVRAM_StoreData: Error (fatal), data write "
4509+ "of %u only wrote %u\n", filedata_length, lrc);
4510+ rc = TPM_FAIL;
4511+ }
4512+ }
4513+#if 0 // disabled due to triggering TPM timeouts
4514+ if (rc == 0 && fd >= 0) {
4515+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Syncing file %s\n", tmpfile);
4516+ irc = fsync(fd);
4517+ if (irc != 0) {
4518+ logprintf(STDERR_FILENO,
4519+ "SWTPM_NVRAM_StoreData: Error (fatal) syncing file, %s\n",
4520+ strerror(errno));
4521+ rc = TPM_FAIL;
4522+ } else {
4523+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Synced file %s\n", tmpfile);
4524+ }
4525+ }
4526+#endif
4527+ if (fd >= 0) {
4528+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile);
4529+ irc = close(fd); /* @1 */
4530+ if (irc != 0) {
4531+ logprintf(STDERR_FILENO,
4532+ "SWTPM_NVRAM_StoreData: Error (fatal) closing file\n");
4533+ rc = TPM_FAIL;
4534+ }
4535+ else {
4536+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", tmpfile);
4537+ }
4538+ }
4539+
4540+ if (rc == 0 && fd >= 0) {
4541+ irc = rename(tmpfile, filepath);
4542+ if (irc != 0) {
4543+ logprintf(STDERR_FILENO,
4544+ "SWTPM_NVRAM_StoreData: Error (fatal) renaming file: %s\n",
4545+ strerror(errno));
4546+ rc = TPM_FAIL;
4547+ } else {
4548+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Renamed file to %s\n", filepath);
4549+ }
4550+ }
4551+
4552+ /*
4553+ * Quote from linux man 2 fsync:
4554+ * Calling fsync() does not necessarily ensure that the entry in the
4555+ * directory containing the file has also reached disk. For that an
4556+ * explicit fsync() on a file descriptor for the directory is also needed.
4557+ */
4558+ if (rc == 0 && fd >= 0 && do_dir_fsync) {
4559+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening dir %s\n", tpm_state_path);
4560+ dir_fd = open(tpm_state_path, O_RDONLY);
4561+ if (dir_fd < 0) {
4562+ do_dir_fsync = false;
4563+ logprintf(STDERR_FILENO,
4564+ "SWTPM_NVRAM_StoreData: Error opening %s for "
4565+ "fsync failed, %s. Continuing but check AppArmor profile.\n",
4566+ tpm_state_path, strerror(errno));
4567+ }
4568+ }
4569+ if (rc == 0 && dir_fd >= 0) {
4570+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Syncing dir %s\n", tpm_state_path);
4571+ irc = fsync(dir_fd);
4572+ if (irc != 0) {
4573+ logprintf(STDERR_FILENO,
4574+ "SWTPM_NVRAM_StoreData: Error (fatal) syncing dir, %s\n",
4575+ strerror(errno));
4576+ rc = TPM_FAIL;
4577+ } else {
4578+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Synced dir %s\n", tpm_state_path);
4579+ }
4580+ }
4581+ if (dir_fd >= 0) {
4582+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing dir %s\n", tpm_state_path);
4583+ irc = close(dir_fd);
4584+ if (irc != 0) {
4585+ logprintf(STDERR_FILENO,
4586+ "SWTPM_NVRAM_StoreData: Error (fatal) closing dir\n");
4587+ rc = TPM_FAIL;
4588+ } else {
4589+ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed dir %s\n", tpm_state_path);
4590+ }
4591+ }
4592+
4593+ if (rc != 0 && fd >= 0) {
4594+ unlink(tmpfile);
4595+ }
4596+
4597+ return rc;
4598+}
4599+
4600+static TPM_RESULT
4601+SWTPM_NVRAM_DeleteName_Dir(uint32_t tpm_number,
4602+ const char *name,
4603+ TPM_BOOL mustExist,
4604+ const char *uri)
4605+{
4606+ TPM_RESULT rc = 0;
4607+ int irc;
4608+ char filepath[FILENAME_MAX]; /* rooted file path from name */
4609+ const char *tpm_state_path = NULL;
4610+
4611+ tpm_state_path = SWTPM_NVRAM_Uri_to_Dir(uri);
4612+
4613+ TPM_DEBUG(" SWTPM_NVRAM_DeleteName: Name %s\n", name);
4614+ /* map name to the rooted file path */
4615+ rc = SWTPM_NVRAM_GetFilepathForName(filepath, sizeof(filepath),
4616+ tpm_number, name, false,
4617+ tpm_state_path);
4618+ if (rc == 0) {
4619+ irc = remove(filepath);
4620+ if ((irc != 0) && /* if the remove failed */
4621+ (mustExist || /* if any error is a failure, or */
4622+ (errno != ENOENT))) { /* if error other than no such file */
4623+ logprintf(STDERR_FILENO,
4624+ "SWTPM_NVRAM_DeleteName: Error, (fatal) file "
4625+ "remove failed, errno %d\n", errno);
4626+ rc = TPM_FAIL;
4627+ }
4628+ }
4629+ return rc;
4630+}
4631+
4632+struct nvram_backend_ops nvram_dir_ops = {
4633+ .prepare = SWTPM_NVRAM_Prepare_Dir,
4634+ .load = SWTPM_NVRAM_LoadData_Dir,
4635+ .store = SWTPM_NVRAM_StoreData_Dir,
4636+ .delete = SWTPM_NVRAM_DeleteName_Dir,
4637+ .cleanup = SWTPM_NVRAM_Cleanup_Dir,
4638+ .check_state = SWTPM_NVRAM_CheckState_Dir,
4639+};
4640diff --git a/src/swtpm/swtpm_nvstore_linear.c b/src/swtpm/swtpm_nvstore_linear.c
4641new file mode 100644
4642index 0000000..eda7793
4643--- /dev/null
4644+++ b/src/swtpm/swtpm_nvstore_linear.c
4645@@ -0,0 +1,480 @@
4646+#include "config.h"
4647+
4648+#define _GNU_SOURCE
4649+#include <stdlib.h>
4650+#include <string.h>
4651+
4652+#include <libtpms/tpm_error.h>
4653+#include <libtpms/tpm_nvfilename.h>
4654+
4655+#include "compiler_dependencies.h"
4656+#include "sys_dependencies.h"
4657+#include "swtpm.h"
4658+#include "swtpm_debug.h"
4659+#include "swtpm_nvstore.h"
4660+#include "swtpm_nvstore_linear.h"
4661+#include "logging.h"
4662+#include "utils.h"
4663+
4664+static struct {
4665+ TPM_BOOL initialized;
4666+ char *loaded_uri;
4667+ struct nvram_linear_store_ops *ops;
4668+
4669+ unsigned char *data;
4670+ uint32_t length;
4671+ struct nvram_linear_hdr *hdr; /* points into *data */
4672+} state;
4673+
4674+/*
4675+ Attempts to flush the header of the linear state, if required by the store.
4676+*/
4677+static TPM_RESULT
4678+SWTPM_NVRAM_Linear_FlushHeader(const char* uri)
4679+{
4680+ if (state.ops->flush) {
4681+ return state.ops->flush(uri, 0, le16toh(state.hdr->hdrsize));
4682+ }
4683+ return 0;
4684+}
4685+
4686+/*
4687+ Attempts a resize and ensures that state is updated correctly and the given
4688+ new_size could actually be reached.
4689+*/
4690+static TPM_RESULT
4691+SWTPM_NVRAM_Linear_SafeResize(const char* uri, uint32_t new_size)
4692+{
4693+ TPM_RESULT rc = 0;
4694+ uint32_t result;
4695+
4696+ if (!state.ops->resize) {
4697+ return new_size < state.length ? 0 : TPM_SIZE;
4698+ }
4699+
4700+ rc = state.ops->resize(uri, &state.data, &result, new_size);
4701+ if (rc) {
4702+ return rc;
4703+ }
4704+
4705+ /* base address might have changed, update pointers */
4706+ state.hdr = (struct nvram_linear_hdr*)state.data;
4707+ state.length = result;
4708+
4709+ if (result < new_size) {
4710+ return TPM_SIZE;
4711+ }
4712+
4713+ return rc;
4714+}
4715+
4716+#define FILE_NR_INVALID 0xffffffff
4717+
4718+/*
4719+ Returns the offset into the state.hdr.files array given a TPM state name and
4720+ number. Will be FILE_NR_INVALID if out of bounds or unknown name.
4721+*/
4722+static uint32_t
4723+SWTPM_NVRAM_Linear_GetFileNr(const char *name)
4724+{
4725+ uint32_t rc = 0;
4726+ if (strcmp(name, TPM_PERMANENT_ALL_NAME) == 0) {
4727+ rc += 0;
4728+ } else if (strcmp(name, TPM_VOLATILESTATE_NAME) == 0) {
4729+ rc += 1;
4730+ } else if (strcmp(name, TPM_SAVESTATE_NAME) == 0) {
4731+ rc += 2;
4732+ } else {
4733+ logprintf(STDERR_FILENO,
4734+ "SWTPM_NVRAM_Linear_GetFileOffset: Unknown name '%s'\n",
4735+ name);
4736+ return FILE_NR_INVALID;
4737+ }
4738+ if (rc >= SWTPM_NVSTORE_LINEAR_MAX_STATES) {
4739+ logprintf(STDERR_FILENO,
4740+ "SWTPM_NVRAM_Linear_GetFileOffset: File limit exceeded: %d\n",
4741+ rc);
4742+ return FILE_NR_INVALID;
4743+ }
4744+ return rc;
4745+}
4746+
4747+/*
4748+ Allocate a new file entry in the linear address space of state.data.
4749+ The new file will be placed at the end.
4750+
4751+ Importantly, this may perform a resize, so pointers into state.data or
4752+ state.hdr must not be kept over this function call.
4753+*/
4754+static TPM_RESULT
4755+SWTPM_NVRAM_Linear_AllocFile(const char *uri, uint32_t file_nr, uint32_t size)
4756+{
4757+ TPM_RESULT rc = 0;
4758+ struct nvram_linear_hdr_file *file;
4759+ uint32_t new_offset = le16toh(state.hdr->hdrsize);
4760+ uint32_t new_size;
4761+ uint32_t cur_end;
4762+ uint32_t i;
4763+ uint32_t section_size = size;
4764+ ROUND_TO_NEXT_POWER_OF_2_32(section_size);
4765+
4766+ /* find end of current last file */
4767+ for (i = 0; i < SWTPM_NVSTORE_LINEAR_MAX_STATES; i++) {
4768+ file = &state.hdr->files[i];
4769+ if (!file->offset) {
4770+ continue;
4771+ }
4772+
4773+ cur_end = le32toh(file->offset) + le32toh(file->section_length);
4774+ if (cur_end > new_offset) {
4775+ new_offset = cur_end;
4776+ }
4777+ }
4778+
4779+ new_size = new_offset + section_size;
4780+ rc = SWTPM_NVRAM_Linear_SafeResize(uri, new_size);
4781+ if (rc) {
4782+ return rc;
4783+ }
4784+
4785+ file = &state.hdr->files[file_nr];
4786+ file->section_length = htole32(section_size);
4787+ file->data_length = htole32(size);
4788+ file->offset = htole32(new_offset);
4789+
4790+ TPM_DEBUG("SWTPM_NVRAM_Linear_AllocFile: allocated file %d @ %d "
4791+ "(len=%d section=%d)\n",
4792+ file_nr, new_offset, size, section_size);
4793+
4794+ return rc;
4795+}
4796+
4797+/*
4798+ Deallocate a file from state.data. It's entry in state.hdr will be zeroed,
4799+ and the file length adjusted accordingly (if 'resize' is TRUE).
4800+ If the file was not at the end, any following files will be moved forward,
4801+ as to not leave any holes. This simplifies the allocator strategy, since it
4802+ allows new files to always be placed at the end.
4803+
4804+ If resize is true, this may perform a resize, so pointers into state.data or
4805+ state.hdr must not be kept over this function call.
4806+*/
4807+static TPM_RESULT
4808+SWTPM_NVRAM_Linear_RemoveFile(const char *uri,
4809+ uint32_t file_nr,
4810+ TPM_BOOL resize)
4811+{
4812+ TPM_RESULT rc = 0;
4813+ uint32_t next_offset = 0xffffffff;
4814+ uint32_t state_end = 0;
4815+ uint32_t new_len;
4816+ uint32_t i, cur_offset, cur_end;
4817+ struct nvram_linear_hdr_file *file;
4818+ struct nvram_linear_hdr_file old_file = state.hdr->files[file_nr];
4819+
4820+ if (old_file.offset == 0) {
4821+ return 0;
4822+ }
4823+
4824+ TPM_DEBUG("SWTPM_NVRAM_Linear_RemoveFile: removing filenr %d (resize=%d)\n",
4825+ file_nr, resize);
4826+
4827+ state.hdr->files[file_nr].offset = 0;
4828+ state.hdr->files[file_nr].data_length = 0;
4829+ state.hdr->files[file_nr].section_length = 0;
4830+
4831+ /* find offset of file right after the one we remove, and adjust offsets */
4832+ for (i = 0; i < SWTPM_NVSTORE_LINEAR_MAX_STATES; i++) {
4833+ file = &state.hdr->files[i];
4834+ if (!file->offset) {
4835+ continue;
4836+ }
4837+
4838+ cur_offset = le32toh(file->offset);
4839+ if (cur_offset > le32toh(old_file.offset)) {
4840+ if (cur_offset < next_offset) {
4841+ next_offset = cur_offset;
4842+ }
4843+ cur_end = cur_offset + le32toh(file->section_length);
4844+ if (cur_end > state_end) {
4845+ state_end = cur_end;
4846+ }
4847+ file->offset = htole32(cur_offset -
4848+ le32toh(old_file.section_length));
4849+ }
4850+ }
4851+
4852+ if (next_offset != 0xffffffff) {
4853+ TPM_DEBUG("SWTPM_NVRAM_Linear_RemoveFile: compacting\n");
4854+ /* if we weren't the end, compact by moving following files forward */
4855+ memmove(state.data + le32toh(old_file.offset),
4856+ state.data + next_offset,
4857+ state_end - next_offset);
4858+ }
4859+
4860+ if (resize) {
4861+ new_len = state.length - le32toh(old_file.section_length);
4862+ rc = SWTPM_NVRAM_Linear_SafeResize(uri, new_len);
4863+ if (rc == 0) {
4864+ state.length = new_len;
4865+ }
4866+ }
4867+
4868+ return rc;
4869+}
4870+
4871+static TPM_RESULT
4872+SWTPM_NVRAM_Prepare_Linear(const char *uri)
4873+{
4874+ TPM_RESULT rc = 0;
4875+
4876+ TPM_DEBUG("SWTPM_NVRAM_Prepare_Linear: uri='%s'\n", uri);
4877+
4878+ if (state.initialized) {
4879+ if (strcmp(state.loaded_uri, uri) == 0) {
4880+ /* same URI loaded, this is okay, nothing to be done */
4881+ return 0;
4882+ }
4883+
4884+ logprintf(STDERR_FILENO,
4885+ "SWTPM_NVRAM_PrepareLinear: Cannot prepare twice\n");
4886+ return TPM_FAIL;
4887+ }
4888+
4889+ state.loaded_uri = malloc(strlen(uri) + 1);
4890+ strcpy(state.loaded_uri, uri);
4891+
4892+ /* TODO: Parse URI prefixes ("iscsi://", "rbd://", etc...) */
4893+ state.ops = &nvram_linear_file_ops;
4894+
4895+ if ((rc = state.ops->open(uri, &state.data, &state.length))) {
4896+ return rc;
4897+ }
4898+
4899+ state.hdr = (struct nvram_linear_hdr*)state.data;
4900+
4901+ if (le64toh(state.hdr->magic) != SWTPM_NVSTORE_LINEAR_MAGIC) {
4902+ logprintf(STDOUT_FILENO,
4903+ "Formatting '%s' as new linear NVRAM store\n",
4904+ uri);
4905+
4906+ state.hdr->magic = htole64(SWTPM_NVSTORE_LINEAR_MAGIC);
4907+ state.hdr->version = SWTPM_NVSTORE_LINEAR_VERSION;
4908+ state.hdr->hdrsize = htole16(sizeof(struct nvram_linear_hdr));
4909+ memset(&state.hdr->files, 0, sizeof(state.hdr->files));
4910+
4911+ SWTPM_NVRAM_Linear_FlushHeader(uri);
4912+
4913+ } else {
4914+ /* assume valid state found */
4915+ if (state.hdr->version > SWTPM_NVSTORE_LINEAR_VERSION) {
4916+ logprintf(STDERR_FILENO,
4917+ "SWTPM_NVRAM_PrepareLinear: Unknown format version: %d\n",
4918+ state.hdr->version);
4919+ return TPM_FAIL;
4920+ }
4921+ }
4922+
4923+ state.initialized = TRUE;
4924+ return rc;
4925+}
4926+
4927+static TPM_RESULT
4928+SWTPM_NVRAM_LoadData_Linear(unsigned char **data,
4929+ uint32_t *length,
4930+ uint32_t tpm_number SWTPM_ATTR_UNUSED,
4931+ const char *name,
4932+ const char *uri SWTPM_ATTR_UNUSED)
4933+{
4934+ uint32_t file_nr;
4935+ uint32_t file_offset;
4936+ uint32_t file_data_len;
4937+ struct nvram_linear_hdr_file *file;
4938+
4939+ TPM_DEBUG("SWTPM_NVRAM_LoadData_Linear: request for %s:%d\n",
4940+ name, tpm_number);
4941+
4942+ file_nr = SWTPM_NVRAM_Linear_GetFileNr(name);
4943+ if (file_nr == FILE_NR_INVALID) {
4944+ return TPM_FAIL;
4945+ }
4946+
4947+ file = &state.hdr->files[file_nr];
4948+ file_offset = le32toh(file->offset);
4949+ file_data_len = le32toh(file->data_length);
4950+
4951+ if (!file_offset) {
4952+ return TPM_RETRY;
4953+ }
4954+
4955+ if (file_offset + file_data_len > state.length) {
4956+ /* shouldn't happen, but just to be safe */
4957+ return TPM_FAIL;
4958+ }
4959+
4960+ if (data == NULL) {
4961+ return TPM_FAIL;
4962+ }
4963+
4964+ /*
4965+ TODO: at the moment, callers require a pointer that can be 'free'd, but
4966+ for efficiency, it would be better to return the mapped area directly
4967+ */
4968+ *length = file_data_len;
4969+ *data = malloc(file_data_len);
4970+ if (*data == NULL) {
4971+ return TPM_FAIL;
4972+ }
4973+ memcpy(*data, state.data + file_offset, file_data_len);
4974+
4975+ TPM_DEBUG("SWTPM_NVRAM_LoadData_Linear: loaded %dB from %s:%d\n",
4976+ file_data_len, name, tpm_number);
4977+
4978+ return 0;
4979+}
4980+
4981+static TPM_RESULT
4982+SWTPM_NVRAM_StoreData_Linear(unsigned char *filedata,
4983+ uint32_t filedata_length,
4984+ uint32_t tpm_number SWTPM_ATTR_UNUSED,
4985+ const char *name,
4986+ const char *uri)
4987+{
4988+ TPM_RESULT rc = 0;
4989+ TPM_BOOL needs_hdr_flush = FALSE;
4990+ TPM_BOOL needs_full_flush = FALSE;
4991+ uint32_t file_nr;
4992+ uint32_t file_offset;
4993+ struct nvram_linear_hdr_file *file;
4994+
4995+ TPM_DEBUG("SWTPM_NVRAM_StoreData_Linear: request for %dB to %s:%d\n",
4996+ filedata_length, name, tpm_number);
4997+
4998+ file_nr = SWTPM_NVRAM_Linear_GetFileNr(name);
4999+ if (file_nr == FILE_NR_INVALID) {
5000+ return TPM_FAIL;
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: