Merge ~lvoytek/ubuntu/+source/swtpm:merge-0.7.3-lunar into ubuntu/+source/swtpm:ubuntu/devel
- Git
- lp:~lvoytek/ubuntu/+source/swtpm
- merge-0.7.3-lunar
- Merge into ubuntu/devel
| 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) |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| git-ubuntu bot | Approve | ||
| Robie Basak | Approve | ||
| Canonical Server Reporter | Pending | ||
|
Review via email:
|
|||
Commit message
Description of the change
Update to 0.7.3 to fix TPM secure boot in Lunar
PPA: https:/
autopkgtest results:
autopkgtest [07:48:29]: @@@@@@@
run-tests PASS
Currently working on the FFE info for the bug
| Utkarsh Gupta (utkarsh) wrote : | # |
| Lena Voytek (lvoytek) wrote : | # |
FFe filed, thanks!
| Robie Basak (racb) wrote : | # |
[Needs verifying:] In swtpm-tools, /usr/lib/
[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.
| Robie Basak (racb) wrote : | # |
(sorry Utkarsh; Christian asked in standup today that we look at this before you're back)
| 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/
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.
| 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:/
| git-ubuntu bot (git-ubuntu-bot) wrote : | # |
Approvers: racb, lvoytek
Uploaders: racb
MP auto-approved
| Robie Basak (racb) wrote : | # |
Sponsored.
Preview Diff
| 1 | diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md |
| 2 | index 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. |
| 14 | diff --git a/.gitignore b/.gitignore |
| 15 | index 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 |
| 64 | diff --git a/.travis.yml b/.travis.yml |
| 65 | index 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 |
| 76 | diff --git a/CHANGES b/CHANGES |
| 77 | index 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: |
| 162 | diff --git a/INSTALL b/INSTALL |
| 163 | index 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: |
| 192 | diff --git a/Makefile.am b/Makefile.am |
| 193 | index 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 \ |
| 204 | diff --git a/configure.ac b/configure.ac |
| 205 | index 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" |
| 405 | diff --git a/debian/changelog b/debian/changelog |
| 406 | index 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 |
| 432 | diff --git a/debian/clean b/debian/clean |
| 433 | new file mode 100644 |
| 434 | index 0000000..494005d |
| 435 | --- /dev/null |
| 436 | +++ b/debian/clean |
| 437 | @@ -0,0 +1,3 @@ |
| 438 | +include/swtpm/*.gch |
| 439 | +man/*/*.3 |
| 440 | +man/*/*.8 |
| 441 | diff --git a/debian/control b/debian/control |
| 442 | index 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, |
| 457 | diff --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 |
| 458 | deleted file mode 100644 |
| 459 | index 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 \ |
| 528 | diff --git a/debian/patches/no-autoconf-in-debian.patch b/debian/patches/no-autoconf-in-debian.patch |
| 529 | index 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 \ |
| 553 | diff --git a/debian/patches/openssl-not-certtool.patch b/debian/patches/openssl-not-certtool.patch |
| 554 | index 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 | |
| 709 | diff --git a/debian/patches/series b/debian/patches/series |
| 710 | index 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 |
| 717 | diff --git a/debian/rules b/debian/rules |
| 718 | index 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 |
| 731 | diff --git a/debian/swtpm-tools.install b/debian/swtpm-tools.install |
| 732 | index 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 |
| 758 | diff --git a/etc/Makefile.am b/etc/Makefile.am |
| 759 | deleted file mode 100644 |
| 760 | index 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 |
| 777 | diff --git a/include/Makefile.am b/include/Makefile.am |
| 778 | index 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 |
| 791 | diff --git a/include/compiler_dependencies.h b/include/compiler_dependencies.h |
| 792 | new file mode 100644 |
| 793 | index 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 */ |
| 814 | diff --git a/include/swtpm/tpm_ioctl.h b/include/swtpm/tpm_ioctl.h |
| 815 | index 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> |
| 829 | diff --git a/include/sys_dependencies.h b/include/sys_dependencies.h |
| 830 | index 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 |
| 848 | diff --git a/man/man8/Makefile.am b/man/man8/Makefile.am |
| 849 | index 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) |
| 904 | diff --git a/man/man8/swtpm-create-tpmca.pod b/man/man8/swtpm-create-tpmca.pod |
| 905 | index 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 | |
| 961 | diff --git a/man/man8/swtpm-localca.8 b/man/man8/swtpm-localca.8 |
| 962 | new file mode 100644 |
| 963 | index 0000000..a9d3f4b |
| 964 | --- /dev/null |
| 965 | +++ b/man/man8/swtpm-localca.8 |
| 966 | @@ -0,0 +1 @@ |
| 967 | +.so man8/swtpm_localca.8 |
| 968 | diff --git a/man/man8/swtpm-localca.conf.pod b/man/man8/swtpm-localca.conf.pod |
| 969 | index 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 | |
| 995 | diff --git a/man/man8/swtpm-localca.options.pod b/man/man8/swtpm-localca.options.pod |
| 996 | index 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 | |
| 1016 | diff --git a/man/man8/swtpm.pod b/man/man8/swtpm.pod |
| 1017 | index 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. |
| 1162 | diff --git a/man/man8/swtpm_cert.pod b/man/man8/swtpm_cert.pod |
| 1163 | index 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 |
| 1180 | diff --git a/man/man8/swtpm_cuse.pod b/man/man8/swtpm_cuse.pod |
| 1181 | index 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 |
| 1198 | diff --git a/man/man8/swtpm-localca.pod b/man/man8/swtpm_localca.pod |
| 1199 | similarity index 94% |
| 1200 | rename from man/man8/swtpm-localca.pod |
| 1201 | rename to man/man8/swtpm_localca.pod |
| 1202 | index 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 |
| 1232 | diff --git a/man/man8/swtpm_setup.conf.pod b/man/man8/swtpm_setup.conf.pod |
| 1233 | index 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 |
| 1249 | diff --git a/man/man8/swtpm_setup.pod b/man/man8/swtpm_setup.pod |
| 1250 | index 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 | |
| 1430 | diff --git a/man/man8/swtpm_setup.sh.8 b/man/man8/swtpm_setup.sh.8 |
| 1431 | deleted file mode 100644 |
| 1432 | index 7574f18..0000000 |
| 1433 | --- a/man/man8/swtpm_setup.sh.8 |
| 1434 | +++ /dev/null |
| 1435 | @@ -1 +0,0 @@ |
| 1436 | -.so man8/swtpm_setup.8 |
| 1437 | diff --git a/samples/Makefile.am b/samples/Makefile.am |
| 1438 | index 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 |
| 1500 | diff --git a/samples/swtpm-create-user-config-files.in b/samples/swtpm-create-user-config-files.in |
| 1501 | index 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 "$@" |
| 1594 | diff --git a/samples/swtpm-localca.in b/samples/swtpm-localca.in |
| 1595 | new file mode 100755 |
| 1596 | index 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 $? |
| 1605 | diff --git a/etc/swtpm_setup.conf.in b/samples/swtpm_setup.conf.in |
| 1606 | similarity index 60% |
| 1607 | rename from etc/swtpm_setup.conf.in |
| 1608 | rename to samples/swtpm_setup.conf.in |
| 1609 | index 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@ |
| 1620 | diff --git a/src/Makefile.am b/src/Makefile.am |
| 1621 | index 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 |
| 1632 | diff --git a/src/selinux/Makefile.am b/src/selinux/Makefile.am |
| 1633 | index 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 | |
| 1645 | diff --git a/src/swtpm/Makefile.am b/src/swtpm/Makefile.am |
| 1646 | index 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) \ |
| 1721 | diff --git a/src/swtpm/capabilities.c b/src/swtpm/capabilities.c |
| 1722 | index 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 | |
| 1789 | diff --git a/src/swtpm/common.c b/src/swtpm/common.c |
| 1790 | index 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 */ |
| 1940 | diff --git a/src/swtpm/common.h b/src/swtpm/common.h |
| 1941 | index 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 | } |
| 1964 | diff --git a/src/swtpm/ctrlchannel.c b/src/swtpm/ctrlchannel.c |
| 1965 | index 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); |
| 1992 | diff --git a/src/swtpm/cuse_tpm.c b/src/swtpm/cuse_tpm.c |
| 1993 | index 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"); |
| 2241 | diff --git a/src/swtpm/daemonize.c b/src/swtpm/daemonize.c |
| 2242 | new file mode 100644 |
| 2243 | index 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 | +} |
| 2549 | diff --git a/src/swtpm/osx.h b/src/swtpm/daemonize.h |
| 2550 | similarity index 88% |
| 2551 | rename from src/swtpm/osx.h |
| 2552 | rename to src/swtpm/daemonize.h |
| 2553 | index 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 */ |
| 2580 | diff --git a/src/swtpm/mainloop.c b/src/swtpm/mainloop.c |
| 2581 | index 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, |
| 2635 | diff --git a/src/swtpm/osx.c b/src/swtpm/osx.c |
| 2636 | deleted file mode 100644 |
| 2637 | index 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 |
| 2693 | diff --git a/src/swtpm/seccomp_profile.c b/src/swtpm/seccomp_profile.c |
| 2694 | index 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; |
| 2722 | diff --git a/src/swtpm/swtpm.c b/src/swtpm/swtpm.c |
| 2723 | index 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 | } |
| 2923 | diff --git a/src/swtpm/swtpm_aes.c b/src/swtpm/swtpm_aes.c |
| 2924 | index 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 | } |
| 3162 | diff --git a/src/swtpm/swtpm_chardev.c b/src/swtpm/swtpm_chardev.c |
| 3163 | index 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 | } |
| 3365 | diff --git a/src/swtpm/swtpm_nvfile.c b/src/swtpm/swtpm_nvstore.c |
| 3366 | similarity index 74% |
| 3367 | rename from src/swtpm/swtpm_nvfile.c |
| 3368 | rename to src/swtpm/swtpm_nvstore.c |
| 3369 | index 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 | +} |
| 4017 | diff --git a/src/swtpm/swtpm_nvfile.h b/src/swtpm/swtpm_nvstore.h |
| 4018 | similarity index 80% |
| 4019 | rename from src/swtpm/swtpm_nvfile.h |
| 4020 | rename to src/swtpm/swtpm_nvstore.h |
| 4021 | index 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 */ |
| 4107 | diff --git a/src/swtpm/swtpm_nvstore_dir.c b/src/swtpm/swtpm_nvstore_dir.c |
| 4108 | new file mode 100644 |
| 4109 | index 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 | +}; |
| 4640 | diff --git a/src/swtpm/swtpm_nvstore_linear.c b/src/swtpm/swtpm_nvstore_linear.c |
| 4641 | new file mode 100644 |
| 4642 | index 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; |

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