├── .gitignore ├── AUTHORS ├── LICENSE ├── MAINTAINERS ├── Makefile ├── NEWS ├── README ├── TODO ├── env.mk ├── rules.mk ├── scripts ├── Makefile ├── demo.sh ├── encrypt_secret.py.in ├── init.cryptfs ├── test.sh ├── test_tpm2_tools.sh ├── tpm2-lockout-status.sh └── tpm2_clear.sh ├── src ├── Makefile ├── cryptfs-tpm2 │ ├── Makefile │ ├── main.c │ ├── subcmd_evict.c │ ├── subcmd_help.c │ ├── subcmd_seal.c │ └── subcmd_unseal.c ├── include │ ├── cryptfs_tpm2.h │ └── subcommand.h ├── lib │ ├── Makefile │ ├── build_info.c.in │ ├── capability.c │ ├── create.c │ ├── da.c │ ├── evict.c │ ├── hash.c │ ├── init.c │ ├── internal.h │ ├── option.c │ ├── pcr.c │ ├── policy.c │ ├── random.c │ ├── secret.c.in │ ├── secret_area.S │ ├── session.c │ ├── subcommand.c │ ├── tcti.c │ ├── tpm2_rc.h │ ├── tss2.c │ ├── unseal.c │ └── util.c ├── luks-setup │ ├── Makefile │ └── luks-setup.sh └── tcti-probe │ ├── Makefile │ ├── main.c │ ├── subcmd_help.c │ └── subcmd_wait.c └── version.mk /.gitignore: -------------------------------------------------------------------------------- 1 | src/cryptfs-tpm2/cryptfs-tpm2 2 | src/tcti-probe/tcti-probe 3 | *.o 4 | *.so 5 | *.a 6 | *.secret 7 | src/lib/build_info.c 8 | src/lib/secret.c 9 | scripts/encrypt_secret.py 10 | *.patch 11 | *.swp 12 | *.swo 13 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Jia Zhang 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017, Wind River Systems, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted 5 | provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | - Neither the name of the copyright holder nor the names of its contributors may be used 13 | to endorse or promote products derived from this software without specific prior written 14 | permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 17 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 19 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | Jia Zhang 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include version.mk 2 | 3 | TOPDIR := $(shell pwd) 4 | export TOPDIR 5 | 6 | SUBDIRS := scripts src 7 | 8 | .DEFAULT_GOAL := all 9 | .PHONE: all clean install tag 10 | 11 | all clean install: 12 | @for x in $(SUBDIRS); do $(MAKE) -C $$x $@ || exit $?; done 13 | 14 | tag: 15 | @git tag -a cryptfs-tpm2-$(VERSION) -m $(VERSION) refs/heads/master 16 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Version 0.7.0 2 | ============= 3 | Released: 2018-09-06 4 | 5 | - Rebased to tpm2-tss 2.0 6 | 7 | Version 0.6.2 8 | ============= 9 | Released: 2018-02-16 10 | 11 | - Rebased to tpm2-tss 1.3.0 12 | 13 | Version 0.6.1 14 | ============= 15 | Released: 2017-11-30 16 | 17 | - Sync up with upstream for the recent tpm2-tss changes. 18 | - Re-licensed under BSD 3-clause. 19 | - Support to talk with the new resource manager tpm2-tabrmd. 20 | 21 | Version 0.6.0 22 | ============= 23 | Released: 2017-05-09 24 | 25 | - Disable DA protection in luks-setup.sh. 26 | - Support to set the secret info for the primary key and passphrase secret 27 | in luks-setup.sh. 28 | - Support to specify owner authentication and lockout authentication in 29 | luks-setup.sh. 30 | - Add the test cases for noDA and DA recovery. 31 | - Add --interactive option to enable the prompt of typing authentications 32 | if necessary. 33 | - Add --key-secret and --passphrase-secret options used to set the 34 | secret info for the primary key and passphrase. 35 | - Improve prompting the user to type owner and lockout authentications. 36 | - Add --no-da option for seal command in order to create the objects 37 | without causing DA lockout. 38 | - Add --owner-auth and --loutout-auth options used to specify the secret 39 | info of owner authentication and lockout authentication. 40 | - Implement automatic DA lockout recovery. 41 | - Improve startup reliability in init.cryptfs and luks-setup.sh. 42 | 43 | Version 0.5.2 44 | ============= 45 | Released: 2017-04-26 46 | 47 | - Add new tool tcti-probe used to await resourcemgr 48 | - Add support for mapping/unmapping crypto disks 49 | - Improve mounting reliability 50 | 51 | Version 0.5.1 52 | ============= 53 | Released: 2017-04-09 54 | 55 | - Fix the criticial issues in init.cryptfs. 56 | 57 | Version 0.5.0 58 | ============= 59 | Released: 2017-03-25 60 | 61 | - Completely support auto PCR bank selection. 62 | - Resolve TPM_RC_ATTRIBUTES issue for the sealed data from root cause. 63 | 64 | Version 0.4.4 65 | ============= 66 | Released: 2017-03-23 67 | 68 | - Support to specify PCR bank with "auto" to use the highest strength 69 | digest algorithm. 70 | 71 | Version 0.4.3 72 | ============= 73 | Released: 2017-03-22 74 | 75 | - Secure the secrets for accessing the primary key and passphrase. 76 | - Add the workaround for tpm2_create() with Intel fTPM. 77 | 78 | Version 0.4.2 79 | ============= 80 | Released: 2016-12-14 81 | 82 | - init.cryptfs: fix boot failures 83 | - Report build failure if failing to compile in a subdirectory. 84 | 85 | Version 0.4.1 86 | ============= 87 | Released: 2016-11-30 88 | 89 | - Don't allow to unseal the passphrase without policy session if the 90 | created passphrase requires a policy session. 91 | - script: support to use PCR binding 92 | 93 | Version 0.4.0 94 | ============= 95 | Released: 2016-11-29 96 | 97 | - Add -P option for seal/unseal command to specify the digest algorithm 98 | for PCR bank selection. 99 | - Implement PCR binding (index 7) for sealing/unsealing the passphrase. 100 | 101 | Version 0.3.0 102 | ============= 103 | Released: 2016-11-16 104 | 105 | - Add the initramfs helper script init.cryptfs. 106 | 107 | Version 0.2.1 108 | ============= 109 | Released: 2016-11-14 110 | 111 | - Fix unsealing failure. 112 | 113 | Version 0.2.0 114 | ============= 115 | Released: 2016-11-04 116 | 117 | - Allow to input passphrase externally. 118 | - Fix make clean failure. 119 | - Add the LUKS setup helper script luks-setup.sh. 120 | 121 | Version 0.1.0 122 | ============= 123 | Released: 2016-11-02 124 | 125 | - Initial implementation providing cryptfs-tpm2 and libcryptfs-tpm2.so. 126 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Cryptfs-TPM2 2 | ============ 3 | 4 | This project provides with an implementation used to create, persist, 5 | evict a passphrase for full-disk-encryption with TPM 2.0. 6 | 7 | The passphrase and its associated primary key may be created by RNG engine 8 | in TPM or manually typed. In order to avoid saving the context file on the 9 | untrustworthy media, the created passphrase and primary key are always 10 | persistent in TPM. 11 | 12 | Currently, the resulting binaries consist of cryptfs-tpm2 and 13 | libcryptfs-tpm2.so. 14 | 15 | Build 16 | ----- 17 | This package depends on tpm2-tss and tpm2-abrmd. Download them (see the 18 | section "Reference" for the download link) and run the script "bootstrap" to 19 | compile the library, then switch to root directory of cryptfs-tpm2 and run 20 | "make" to build cryptfs-tpm2. 21 | 22 | Alternately, specifying the macros tpm2_tss_includedir, tpm2_tss_libdir 23 | and tpm2_tabrmd_includedir to build cryptfs-tpm2 with tpm2-tss and tpm2-abrmd 24 | even though they were built but not installed. For example: 25 | 26 | $ export TSS2_ROOT= 27 | $ export TABRMD_ROOT= 28 | $ tpm2_tss_includedir=$TSS2_ROOT/include \ 29 | tpm2_tss_libdir="$TSS2_ROOT/sysapi/.libs $TSS2_ROOT/tcti/.libs" \ 30 | tpm2_tabrmd_includedir="$TABRMD_ROOT/include" \ 31 | make 32 | 33 | Note: define the macro "CROSS_COMPILE=" in command line if specifying cross 34 | compilation. 35 | 36 | Installation 37 | ------------ 38 | $ sudo make install 39 | $ sudo ldconfig 40 | 41 | Release 42 | ------------ 43 | $ ./release.sh 44 | 45 | The RPM package will be built into the `release` dir under current dir. 46 | 47 | Help 48 | ---- 49 | - For the available options and sub-commands: 50 | # cryptfs-tpm2 -h 51 | 52 | - For a sub-command: 53 | # cryptfs-tpm2 help 54 | 55 | Quick start 56 | ----------- 57 | - Preparation 58 | Clear TPM 2.0 device through setting the security jumper on the board or 59 | running tpm2_takeownership -c. The latter is provided by tpm2.0-tools. 60 | 61 | Note: cryptfs-tpm2 will create the primary key and passphrase in the owner 62 | hierarchy and so always specify --owner-auth option to set the authorization 63 | value for accessing owner hierarchy if required. 64 | 65 | - Create the primary key and passphrase 66 | The typical method is to create the primary key and passphrase by TPM 2.0. 67 | # cryptfs-tpm2 seal all 68 | 69 | Manually typed passphrase is also supported. 70 | # cryptfs-tpm2 seal all -p 71 | 72 | PCR (index 7) binding is more secure. 73 | # cryptfs-tpm2 seal all -P 74 | where may be "sha1" or "sha256" or anything else if supported by 75 | TPM 2.0 device, or specify "auto" which will chooses the highest strength 76 | digest algorithm as the preference. 77 | 78 | Note: if the preferred PCR bank doesn't extend PCR index 7 ever, cryptfs-tpm2 79 | will still choose a weaker PCR bank as long as its PCR index 7 was extended. 80 | For example, assuming TPM device already enabled both SHA1 and SHA256 PCR 81 | banks, and if PCR 7 in SHA256 PCR bank is not extended and PCR 7 in SHA1 PCR 82 | bank is by BIOS or bootloader, the SHA1 PCR bank is chosen. 83 | 84 | - Retrieve the passphrase 85 | # cryptfs-tpm2 unseal passphrase -o 86 | or 87 | # cryptfs-tpm2 unseal passphrase -P -o 88 | if PCR binding is used. 89 | 90 | - Evict the primary key and passphrase 91 | # cryptfs-tpm2 evict all 92 | 93 | CAUTION: beware of the permanent loss of them and assoicated data 94 | encryption if you do this. 95 | 96 | Authentication 97 | -------------- 98 | Access an object in TPM requires an authentication check. The table below 99 | records the required secret info for the operation to an object. 100 | 101 | owner-auth primary-key-secret passphrase-secret 102 | seal (primary key) Y N N 103 | seal (passphrase) Y Y N 104 | unseal (passphrase) N N Y 105 | evict (passphrase) Y N N 106 | 107 | Known issues 108 | ------------ 109 | 110 | Validation 111 | ---------- 112 | The following TPM 2.0 devices are validated with cryptfs-tpm2. 113 | 114 | dTPM: 115 | - Infineon TPM SLB 9665 116 | - STMicroelectronics ST33TPHF2ESPI 117 | 118 | fTPM: 119 | - Intel fTPM on Leaf Hill (rev C) 120 | 121 | sTPM: 122 | - IBM Software TPM 123 | http://ibmswtpm.sourceforge.net/ibmswtpm2.html 124 | 125 | Reference 126 | --------- 127 | tpm2-tss 2.0.0 - The TCG TPM2 Software Stack 128 | https://github.com/tpm2-software/tpm2-tss 129 | 130 | tpm2-abrmd 2.0.1 - The resource manager 131 | https://github.com/tpm2-software/tpm2-abrmd.git 132 | 133 | tpm2-tools 3.1.1 - The TPM 2.0 tools 134 | https://github.com/tpm2-software/tpm2-tools 135 | 136 | meta-secure-core - A practical full-disk-encryption implementation with TPM 2.0 137 | based on Pulsar Linux 138 | https://github.com/jiazhang0/meta-secure-core 139 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - Implement multiple key and passphrase. 2 | -------------------------------------------------------------------------------- /env.mk: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= 2 | CC := $(CROSS_COMPILE)gcc 3 | LD := $(CROSS_COMPILE)ld 4 | CCLD := $(CROSS_COMPILE)gcc 5 | AR := $(CROSS_COMPILE)ar 6 | INSTALL ?= install 7 | PKG_CONFIG ?= pkg-config 8 | 9 | EXTRA_CFLAGS ?= 10 | EXTRA_LDFLAGS ?= 11 | 12 | DEBUG_BUILD ?= 13 | TSS2_VER ?= 2 14 | prefix ?= /usr 15 | libdir ?= $(prefix)/lib64 16 | sbindir ?= $(prefix)/sbin 17 | includedir ?= $(prefix)/include 18 | 19 | tpm2_tss_includedir ?= $(includedir) 20 | tpm2_tss_libdir ?= $(libdir) 21 | 22 | tpm2_tabrmd_includedir ?= $(includedir) 23 | 24 | # For the installation 25 | DESTDIR ?= 26 | LIBDIR ?= $(libdir) 27 | SBINDIR ?= $(sbindir) 28 | 29 | # The authorization password for the primary key 30 | primary_key_secret ?= H31i05 31 | # The authorization password for the passphrase 32 | passphrase_secret ?= h31i05 33 | # The byte code used to encrypt/decrypt secrets 34 | secret_xor_byte_code ?= 0x48 35 | 36 | LDFLAGS := --warn-common --no-undefined --fatal-warnings \ 37 | $(patsubst $(join -Wl,,)%,%,$(EXTRA_LDFLAGS)) 38 | CFLAGS := -D_GNU_SOURCE -std=gnu99 -O2 -Wall -Werror \ 39 | $(addprefix -I, $(TOPDIR)/src/include \ 40 | $(tpm2_tss_includedir) $(tpm2_tabrmd_includedir) \ 41 | $(glib_includedir)) \ 42 | $(addprefix $(join -L,), $(tpm2_tss_libdir)) \ 43 | $(EXTRA_CFLAGS) $(addprefix $(join -Wl,,),$(LDFLAGS)) 44 | 45 | ifneq ($(TSS2_VER), 1) 46 | CFLAGS += -ldl -ltss2-sys -ltss2-tcti-mssim -ltss2-tcti-device 47 | else 48 | CFLAGS += -ldl -lsapi -ltcti-socket -ltcti-device -DTSS2_LEGACY_V1 49 | endif 50 | 51 | ifneq ($(DEBUG_BUILD),) 52 | CFLAGS += -ggdb -DDEBUG 53 | endif 54 | -------------------------------------------------------------------------------- /rules.mk: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/version.mk 2 | 3 | LIB_NAME := libcryptfs-tpm2 4 | 5 | LDFLAGS += 6 | CFLAGS += -DVERSION=\"$(VERSION)\" 7 | 8 | .DEFAULT_GOAL := all 9 | .PHONE: all clean install -------------------------------------------------------------------------------- /scripts/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/env.mk 2 | include $(TOPDIR)/rules.mk 3 | 4 | all: encrypt_secret.py Makefile 5 | 6 | install: all 7 | $(INSTALL) -d -m 755 $(DESTDIR)$(SBINDIR) 8 | 9 | clean: 10 | @$(RM) -f encrypt_secret.py 11 | 12 | encrypt_secret.py: encrypt_secret.py.in 13 | @sed -e "s/@@CRYPTFS_TPM2_SECRET_XOR_BYTE_CODE@@/$(secret_xor_byte_code)/" \ 14 | < $< > $@ 15 | @chmod +x $@ 16 | -------------------------------------------------------------------------------- /scripts/demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LUKS_DEVICE="${LUKS_DEVICE:-/dev/nvme2n1p1}" 4 | 5 | luks-setup --dev "$LUKS_DEVICE" --unmap 6 | rpm -e cryptsetup 7 | clear 8 | 9 | trap_handler() { 10 | trap - SIGINT ERR 11 | 12 | local line_no="$1" 13 | local err=$2 14 | 15 | if [ $err -ne 0 ] && [ "$line_no" != "1" ]; then 16 | echo "Error occurred on line $line_no, exit code: $err" 17 | fi 18 | 19 | exit $err 20 | } 21 | 22 | trap 'trap_handler $LINENO $?' SIGINT ERR 23 | 24 | run() { 25 | local cmd="$1" 26 | 27 | echo -e "\033[1;31m[?] ============\033[0m" 28 | echo -e "\033[1;32m# $cmd\033[0m" 29 | eval "$cmd" 30 | echo -e "\033[1;31m[!] ============\033[0m" 31 | } 32 | 33 | # Intend to see a failure 34 | run "luks-setup --dev $LUKS_DEVICE --no-tpm --recovery --verbose" 35 | 36 | run "luks-setup --dev $LUKS_DEVICE --force --unmap --no-tpm --verbose" 37 | run "cryptsetup luksDump $LUKS_DEVICE" 38 | run "lsblk" 39 | 40 | if [ -e "/dev/tpm0" ]; then 41 | run "luks-setup --dev $LUKS_DEVICE --force --verbose" 42 | run "cryptsetup luksDump $LUKS_DEVICE" 43 | run "lsblk" 44 | 45 | run "luks-setup --dev $LUKS_DEVICE --unmap --verbose" 46 | run "lsblk" 47 | 48 | run "luks-setup --dev $LUKS_DEVICE --recovery --verbose" 49 | 50 | run "luks-setup --dev $LUKS_DEVICE --force --unmap --evict-all --verbose" 51 | run "cryptsetup luksDump $LUKS_DEVICE" 52 | run "lsblk" 53 | 54 | run "luks-setup --dev $LUKS_DEVICE --recovery --verbose --unmap" 55 | run "lsblk" 56 | fi 57 | -------------------------------------------------------------------------------- /scripts/encrypt_secret.py.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #coding: UTF-8 3 | 4 | ''' 5 | The simple encryption/decryption for secret info 6 | ''' 7 | 8 | import logging 9 | import argparse 10 | import struct 11 | 12 | SECRET_XOR_BYTE_CODE = @@CRYPTFS_TPM2_SECRET_XOR_BYTE_CODE@@ 13 | 14 | class Secret: 15 | def encrypt(self, input_data): 16 | _ = SECRET_XOR_BYTE_CODE 17 | input_data = bytes(input_data, 'utf-8') 18 | out = bytearray() 19 | for b in input_data: 20 | _ = b ^ _ 21 | out += struct.pack('B', _) 22 | return bytes(out) 23 | 24 | def decrypt(self, input_data): 25 | _ = SECRET_XOR_BYTE_CODE 26 | input_data = bytes(input_data) 27 | out = bytearray() 28 | for b in input_data: 29 | out += struct.pack('B', b ^ _) 30 | _ = b 31 | return bytes(out) 32 | 33 | logging.basicConfig(level=logging.DEBUG, \ 34 | format="[%(asctime)s] %(levelname)s: %(message)s") 35 | 36 | parser = argparse.ArgumentParser(description='Simple encryption/decryption for secret info') 37 | parser.add_argument('-i', '--input', dest='secret', 38 | help='Input secret info', required=True) 39 | 40 | args = parser.parse_args() 41 | try: 42 | print(Secret().encrypt(args.secret), end='') 43 | except Exception as e: 44 | logging.error("Unable to encrypt the secret: {}".format(str(e))) 45 | -------------------------------------------------------------------------------- /scripts/init.cryptfs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Initramfs script called by /init 4 | # 5 | # This script is a helper used to decrypt and mount the rootfs 6 | # encrypted with cryptfs-tpm2. 7 | # 8 | # BSD 2-clause "Simplified" License 9 | # 10 | # Copyright (c) 2016-2024, Alibaba Cloud 11 | # Copyright (c) 2016-2023, Wind River Systems, Inc. 12 | # 13 | # Redistribution and use in source and binary forms, with or without 14 | # modification, are permitted provided that the following conditions are met: 15 | # 16 | # 1) Redistributions of source code must retain the above copyright notice, 17 | # this list of conditions and the following disclaimer. 18 | # 19 | # 2) Redistributions in binary form must reproduce the above copyright notice, 20 | # this list of conditions and the following disclaimer in the documentation 21 | # and/or other materials provided with the distribution. 22 | # 23 | # 3) Neither the name of Wind River Systems nor the names of its contributors 24 | # may be used to endorse or promote products derived from this software 25 | # without specific prior written permission. 26 | # 27 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 31 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 | # POSSIBILITY OF SUCH DAMAGE. 38 | # 39 | # Author: 40 | # Jia Zhang 41 | # 42 | 43 | # 44 | # Global constant settings 45 | # 46 | 47 | # The tmpfs filesystem used to temporarily place the 48 | # passphrase file. 49 | TMP_DIR="/tmp" 50 | 51 | # The file name of the plain passphrase. 52 | PASSPHRASE="passphrase" 53 | 54 | # The maxinum number of passphrase retry 55 | MAX_PASSPHRASE_RETRY_COUNT=3 56 | 57 | # The timeout (tenth of a second) for the rootfs device got ready 58 | MAX_TIMEOUT_FOR_WAITING_RAWDEV=60 59 | 60 | # The timeout (millisecond) upon awaiting the resource manager 61 | MAX_TIMEOUT_FOR_WAITING_RESOURCEMGR=3000 62 | 63 | # 64 | # Global variable settings 65 | # 66 | 67 | ROOTFS_DIR="${1:-/rootfs}" 68 | ROOTFS_DEV="$2" 69 | ROOTFS_MODE="${3:-rw}" 70 | # The mapping name of device-mapper crypt target for 71 | # the LUKS partition. 72 | LUKS_NAME="${4:-cryptfs_tpm2}" 73 | 74 | TPM_TIS_MODULE_LOADED=0 75 | TPM_CRB_MODULE_LOADED=0 76 | TPM_DEVICE="" 77 | TMP_DIR_MOUNTED=0 78 | 79 | print_critical() { 80 | printf "\033[1;35m" 81 | echo "$@" 82 | printf "\033[0m" 83 | } 84 | 85 | print_error() { 86 | printf "\033[1;31m" 87 | echo "$@" 88 | printf "\033[0m" 89 | } 90 | 91 | print_warning() { 92 | printf "\033[1;33m" 93 | echo "$@" 94 | printf "\033[0m" 95 | } 96 | 97 | print_info() { 98 | printf "\033[1;32m" 99 | echo "$@" 100 | printf "\033[0m" 101 | } 102 | 103 | print_verbose() { 104 | printf "\033[1;36m" 105 | echo "$@" 106 | printf "\033[0m" 107 | } 108 | 109 | create_dir() { 110 | local dir="$1" 111 | 112 | if [ ! -d "$dir" ]; then 113 | mkdir -p "$dir" || return 1 114 | fi 115 | 116 | return 0 117 | } 118 | 119 | get_dev_uuid() { 120 | blkid -t UUID=$1 -l | awk -F: '{ print $1 }' 121 | } 122 | 123 | get_dev_partuuid() { 124 | blkid 2> /dev/null | grep "PARTUUID=\"$1\"" | grep -o "^[^: ]*" 125 | } 126 | 127 | get_dev_label() { 128 | rawdev=`blkid -t LABEL=$1 -l | awk -F: '{print $1}'` 129 | # Also try the partition label for the same name if not found 130 | if [ "$rawdev" == "" ] ; then 131 | rawdev=`blkid -t PARTLABEL=$1 -l | awk -F: '{ print $1 }'` 132 | fi 133 | echo $rawdev 134 | } 135 | 136 | get_dev_rawdev() { 137 | [ -e /sys/class/block/`basename "$1"` ] && echo $1 138 | } 139 | 140 | parse_rootfs_dev_path() { 141 | local ret_type="$1" 142 | local ret_name="$2" 143 | local dev_type dev_name 144 | 145 | # Determine the type of root device 146 | for i in "UUID" "PARTUUID" "LABEL" "" ; do 147 | local word=${i:+"$i="} 148 | local root=$(grep -o "\/dev/null 212 | ! grep -q "^tpm_tis" /proc/modules && modprobe --quiet tpm_tis && TPM_TIS_MODULE_LOADED=1 213 | ! grep -q "^tpm_crb" /proc/modules && modprobe --quiet tpm_crb && TPM_CRB_MODULE_LOADED=1 214 | 215 | local tpm_devices=$(ls /sys/class/tpm) 216 | [ -z "$tpm_devices" ] && print_info "No TPM chip detected." && return 1 217 | 218 | local tpm_absent=1 219 | local name="" 220 | for name in $tpm_devices; do 221 | grep -q "TCG version: 1.2" "/sys/class/tpm/$name/device/caps" 2>/dev/null && 222 | print_info "TPM 1.2 device $name is not supported." && break 223 | 224 | grep -q "TPM 2.0 Device" "/sys/class/tpm/$name/device/description" 2>/dev/null && 225 | tpm_absent=0 && break 226 | done 227 | 228 | [ $tpm_absent -eq 1 ] && print_info "No supported TPM device found." && return 1 229 | 230 | local name_in_dev="$name" 231 | # /dev/tpm is the alias of /dev/tpm0. 232 | [ "$name_in_dev" = "tpm0" ] && name_in_dev+=" tpm" 233 | 234 | local _name="" 235 | for _name in $name_in_dev; do 236 | [ -c "/dev/$_name" ] && break 237 | 238 | local major=$(cat "/sys/class/tpm/$name/dev" | cut -d ":" -f 1) 239 | local minor=$(cat "/sys/class/tpm/$name/dev" | cut -d ":" -f 2) 240 | ! mknod "/dev/$_name" c $major $minor && 241 | print_error "Unable to create tpm device node $_name." && return 1 242 | 243 | TPM_DEVICE="/dev/$_name" 244 | 245 | break 246 | done 247 | 248 | [ -n "$ret_absent" ] && eval $ret_absent=$tpm_absent 249 | 250 | print_info "TPM device /dev/$_name detected." 251 | 252 | return 0 253 | } 254 | 255 | open_luks_part_with_encrypted_passphrase() { 256 | local luks_rawdev="$1" 257 | 258 | while [ 1 ]; do 259 | # Unseal the passphrase 260 | cryptfs-tpm2 -q unseal passphrase -P auto -o "$TMP_DIR/$PASSPHRASE" 2>/dev/null 261 | local res=$? 262 | 263 | [ $res -eq 0 ] && break 264 | 265 | print_error "Unable to unseal the passphrase with the error $res" && return 1 266 | done 267 | 268 | ! cryptsetup luksOpen --key-file "$TMP_DIR/$PASSPHRASE" "$luks_rawdev" "$LUKS_NAME" && 269 | print_error "Unable to open the LUKS partition $luks_rawdev with the encrypted passphrase" && return 1 270 | 271 | print_verbose "The LUKS partition $luks_rawdev is opened with the encrypted passphrase" 272 | 273 | # Remove the plain passphrase file 274 | ! rm -f "$TMP_DIR/$PASSPHRASE" && print_error "Unable to remove the decrypted passphrase file" && return 1 275 | 276 | return 0 277 | } 278 | 279 | open_luks_part_with_typed_passphrase() { 280 | local luks_rawdev="$1" 281 | local i=1 282 | for i in `seq $MAX_PASSPHRASE_RETRY_COUNT`; do 283 | cryptsetup luksOpen --key-file - "$luks_rawdev" "$LUKS_NAME" && 284 | print_verbose "The LUKS partition $luks_rawdev is opened with the typed passphrase" && 285 | return 0 286 | 287 | [ $(($MAX_PASSPHRASE_RETRY_COUNT - $i)) -ne 0 ] && 288 | print_warning "Passphrase incorrect. $(($MAX_PASSPHRASE_RETRY_COUNT - $i))-time remaining ..." 289 | done 290 | 291 | print_error "Failed to open the LUKS partition $luks_rawdev with the typed passphrase" 292 | 293 | return 1 294 | } 295 | 296 | # Alway attempt to map LUKS rootfs with an appropriate passphrase in 297 | # this order: 298 | # - Persistent passphrase if present in TPM 299 | # - Password prompt 300 | map_luks() { 301 | local luks_rawdev="$1" 302 | local tpm_absent=$2 303 | 304 | print_verbose "Attempting to mount the LUKS partition $luks_rawdev ..." 305 | 306 | local err=1 307 | if [ $tpm_absent -eq 0 ]; then 308 | # Delay 100ms before connecting the resource manager per attempt, and 309 | # totally await the resource manager 3s at most. 310 | tcti-probe -q wait -d 100 -t $MAX_TIMEOUT_FOR_WAITING_RESOURCEMGR 2>/dev/null 311 | err=$? 312 | 313 | if [ $err -eq 0 ]; then 314 | open_luks_part_with_encrypted_passphrase "$luks_rawdev" 315 | err=$? 316 | fi 317 | 318 | rm -f "$TMP_DIR/$PASSPHRASE" 319 | fi 320 | 321 | if [ $err -ne 0 ]; then 322 | print_verbose "Attempting to prompt with inputing passphrase ..." 323 | 324 | open_luks_part_with_typed_passphrase "$luks_rawdev" 325 | err=$? 326 | fi 327 | 328 | return $err 329 | } 330 | 331 | mount_luks() { 332 | local err=0 333 | 334 | mount -o "$ROOTFS_MODE" "/dev/mapper/$LUKS_NAME" "$ROOTFS_DIR" || 335 | (err=1 && [ -e "/dev/mapper/$LUKS_NAME" ] && cryptsetup luksClose "$LUKS_NAME") 336 | 337 | return $err 338 | } 339 | 340 | trap_handler() { 341 | local err=$? 342 | 343 | print_verbose "Cleaning up with exit code $err ..." 344 | 345 | if [ $err -ne 0 ]; then 346 | if [ -d "$ROOTFS_DIR" ]; then 347 | umount "$ROOTFS_DIR" 2>/dev/null 348 | fi 349 | 350 | cryptsetup luksClose "$LUKS_NAME" 2>/dev/null 351 | fi 352 | 353 | rm -f "$TMP_DIR/$PASSPHRASE" 2>/dev/null 354 | 355 | [ $TPM_TIS_MODULE_LOADED -eq 1 ] && modprobe --quiet -r tpm_tis 356 | [ $TPM_CRB_MODULE_LOADED -eq 1 ] && modprobe --quiet -r tpm_crb 357 | [ ! -z "$TPM_DEVICE" ] && rm -f "$TPM_DEVICE" 2>/dev/null 358 | 359 | if [ $TMP_DIR_MOUNTED -eq 1 ]; then 360 | umount "$TMP_DIR" 2>/dev/null 361 | rmdir --ignore-fail-on-non-empty "$TMP_DIR" 2>/dev/null 362 | fi 363 | 364 | unset TSS2_TCTI 365 | } 366 | 367 | 368 | trap "trap_handler $?" SIGINT EXIT 369 | 370 | # Detect the present of LUKS partition. 371 | 372 | luks_rawdev_pathes="$(blkid -s TYPE | grep crypto_LUKS | awk -F: '{ print $1 }')" 373 | [ -z "$luks_rawdev_pathes" ] && print_info "No LUKS partition detected" && exit 1 374 | 375 | ! parse_rootfs_dev_path rootfs_dev_path_type rootfs_dev_path_name && exit 1 376 | 377 | rootfs_is_luks=0 378 | get_rawdev $rootfs_dev_path_type $rootfs_dev_path_name rootfs_rawdev 379 | if [ $? -eq 0 ]; then 380 | # Check whether the rootfs device is a LUKS partition. 381 | for luks_rawdev in $luks_rawdev_pathes; do 382 | [ "$rootfs_rawdev" = "$luks_rawdev" ] && rootfs_is_luks=1 && break 383 | done 384 | 385 | if [ $rootfs_is_luks -eq 0 ]; then 386 | print_info "The specified rootfs is not a LUKS partition" 387 | exit 1 388 | fi 389 | fi 390 | 391 | # root=LABEL=xxx cannot be parsed until the LUKS partition is mounted. 392 | [ $rootfs_is_luks -eq 0 -a "$rootfs_dev_path_type" != "LABEL" ] && 393 | print_error "Unable to locate the specified rootfs" && exit 1 394 | 395 | # Overwrite LUKS_NAME if root=LABEL=xxx is specified. 396 | [ $rootfs_is_luks -eq 0 -a "$rootfs_dev_path_type" = "LABEL" -a -n "$rootfs_dev_path_name" ] && 397 | LUKS_NAME="$rootfs_dev_path_name" 398 | 399 | # Make sure the plain passphrase will be saved in a RAM-based 400 | # filesystem to avoid the risk of exposing it. 401 | 402 | if ! create_dir "$TMP_DIR"; then 403 | print_error "Unable to create $TMP_DIR for mounting tmpfs filesystem" 404 | exit 1 405 | fi 406 | 407 | if ! grep -q "$TMP_DIR" /proc/mounts; then 408 | ! mount -t tmpfs none "$TMP_DIR" 2>/dev/null && 409 | print_error "Unable to mount tmpfs filesystem" && exit 1 410 | TMP_DIR_MOUNTED=1 411 | else 412 | tmp_dir_fs_types="$(grep "$TMP_DIR" /proc/mounts | awk '{print $3}')" 413 | 414 | for fs_type in $tmp_dir_fs_types; do 415 | [ "$fs_type" != "tmpfs" ] && 416 | print_error "/tmp is mounted with $fs_type != tmpfs" && exit 1 417 | done 418 | fi 419 | 420 | # Probe TPM. 421 | 422 | tpm_absent=1 423 | if detect_tpm_chip tpm_absent; then 424 | ! ifconfig lo up && print_error "Unable to active the loop interface" && exit 1 425 | tpm_absent=0 426 | export TSS2_TCTI=device 427 | else 428 | tpm_absent=1 429 | fi 430 | 431 | ! create_dir "$ROOTFS_DIR" && print_error "Unable to create $ROOTFS_DIR" && exit 1 432 | 433 | # Check whether the LUKS partition is specified in root=. 434 | err=1 435 | for luks_rawdev in $luks_rawdev_pathes; do 436 | [ -n "$rootfs_rawdev" -a "$rootfs_rawdev" != "$luks_rawdev" ] && continue 437 | 438 | ! map_luks $luks_rawdev $tpm_absent && break 439 | ! mount_luks && break 440 | 441 | [ -z "$rootfs_rawdev" ] && ! get_rawdev $rootfs_dev_path_type \ 442 | $rootfs_dev_path_name rootfs_rawdev && { 443 | umount "$ROOTFS_DIR" 2>/dev/null 444 | cryptsetup luksClose "$LUKS_NAME" 2>/dev/null 445 | continue 446 | } 447 | 448 | err=0 449 | break 450 | done 451 | 452 | [ $err -eq 1 ] && 453 | print_info "Unable to mount the rootfs device" && exit 1 454 | 455 | print_info "The LUKS partition $luks_rawdev is mounted as rootfs successfully" 456 | 457 | exit 0 458 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Cryptfs-TPM2 testing script 4 | # 5 | # Copyright (c) 2024, Alibaba Cloud 6 | # Copyright (c) 2016-2023, Wind River Systems, Inc. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # 1) Redistributions of source code must retain the above copyright notice, 12 | # this list of conditions and the following disclaimer. 13 | # 14 | # 2) Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # 3) Neither the name of Wind River Systems nor the names of its contributors 19 | # may be used to endorse or promote products derived from this software 20 | # without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | # POSSIBILITY OF SUCH DAMAGE. 33 | # 34 | # Author: 35 | # Jia Zhang 36 | # 37 | 38 | PCRS=() 39 | 40 | function check_ownership() 41 | { 42 | tpm2_changeauth --object-context=owner 43 | [ $? != 0 ] && echo "TPM is not clear" && exit 1 44 | } 45 | 46 | function detect_pcrs() 47 | { 48 | local res="`tpm2_getcap pcrs`" 49 | local pcrs=': \[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 \]' 50 | 51 | if echo "$res" | grep -q "sha1$pcrs"; then 52 | PCRS+=("sha1") 53 | echo "TPM supports SHA1" 54 | fi 55 | 56 | if echo "$res" | grep -q "sha256$pcrs"; then 57 | PCRS+=("sha256") 58 | echo "TPM supports SHA256" 59 | fi 60 | } 61 | 62 | function seal_all() 63 | { 64 | echo "Sealing all ..." 65 | 66 | local opts="$EXTRA_SEAL_OPTS" 67 | 68 | if [ -n "$1" ]; then 69 | case $1 in 70 | sha1|sha256|auto) 71 | ;; 72 | *) 73 | echo "Unsupported PCR bak option for seal sub-command" 74 | exit 1 75 | ;; 76 | esac 77 | 78 | opts="$opts -P $1" 79 | fi 80 | 81 | cryptfs-tpm2 -q seal all $opts 82 | } 83 | 84 | function unseal_passphrase() 85 | { 86 | echo "Unsealing passphrase ..." 87 | 88 | local opts="" 89 | 90 | if [ -n "$1" ]; then 91 | case $1 in 92 | sha1|sha256|auto) 93 | ;; 94 | *) 95 | echo "Unsupported PCR bank option for unseal sub-command" 96 | exit 1 97 | ;; 98 | esac 99 | 100 | opts=" -P $1" 101 | fi 102 | 103 | cryptfs-tpm2 -q unseal passphrase $opts 104 | } 105 | 106 | function evict_all() 107 | { 108 | echo "Evicting all ..." 109 | 110 | cryptfs-tpm2 -q evict all 111 | } 112 | 113 | function test_all() 114 | { 115 | seal_all $1 || return 1 116 | unseal_passphrase $1 || return 1 117 | evict_all || return 1 118 | } 119 | 120 | check_ownership 121 | 122 | detect_pcrs 123 | 124 | evict_all >/dev/null 2>&1 125 | 126 | tpm2_flushcontext --transient-object 127 | 128 | log=`mktemp /tmp/cryptfs-tpm2-test-log-XXXX` 129 | echo "The testing log is placed at $log" 130 | 131 | echo -n "[*] testing object generation without PCR ... " 132 | test_all >$log 2>&1 && echo "[SUCCEEDED]" || echo "[FAILED]" 133 | 134 | if printf '%s\n' "${PCRs[@]}" | grep -wq "sha1"; then 135 | echo -n "[*] testing object generation with SHA1 PCR bank ... " 136 | test_all sha1 >>$log 2>&1 && echo "[SUCCEEDED]" || echo "[FAILED]" 137 | fi 138 | 139 | if printf '%s\n' "${PCRs[@]}" | grep -wq "sha256"; then 140 | echo -n "[*] testing object generation with SHA256 PCR bank ... " 141 | test_all sha256 >>$log 2>&1 && echo "[SUCCEEDED]" || echo "[FAILED]" 142 | fi 143 | 144 | echo -n "[*] testing object generation with auto PCR bank ... " 145 | test_all auto >>$log 2>&1 && echo "[SUCCEEDED]" || echo "[FAILED]" 146 | 147 | echo -n "[*] testing DA recovery ... " 148 | tpm2_changeauth --object-context=owner >>$log 2>&1 149 | tpm2_changeauth --object-context=lockout >>$log 2>&1 150 | tpm2_changeauth --object-context=owner owner >>$log 2>&1 151 | tpm2_changeauth --object-context=lockout lockout >>$log 2>&1 152 | tpm2_dictionarylockout --auth=lockout --clear-lockout >>$log 2>&1 153 | tpm2_dictionarylockout --auth=lockout --setup-parameters \ 154 | --max-tries 1 \ 155 | --recovery-time 30 \ 156 | --lockout-recovery-time 60 >>$log 2>&1 157 | 158 | echo "Sealing all with secret set ..." >>$log 2>&1 159 | cryptfs-tpm2 -q --owner-auth owner --key-secret key --passphrase-secret pass \ 160 | seal all -P auto >>$log 2>&1 161 | [ $? -ne 0 ] && echo "[FAILED]" || { 162 | echo "Unsealing passphrase with wrong secret ..." >>$log 2>&1 163 | cryptfs-tpm2 -q --passphrase-secret pass1 \ 164 | unseal passphrase -P auto 2>&1 | grep -q 0x98e 165 | 166 | [ $? -ne 0 ] && echo "[FAILED]" || { 167 | cryptfs-tpm2 -q --passphrase-secret pass1 \ 168 | unseal passphrase -P auto 2>&1 | grep -q 0x921 169 | 170 | [ $? -ne 0 ] && echo "[FAILED]" || { 171 | tpm2_dictionarylockout --auth=lockout --clear-lockout >>$log 2>&1 172 | 173 | echo "Unseal passphrase and reset DA lockout ..." >>$log 2>&1 174 | cryptfs-tpm2 -q --lockout-auth lockout \ 175 | --passphrase-secret pass \ 176 | unseal passphrase -P auto >>$log 2>&1 177 | 178 | [ $? -ne 0 ] && echo "[FAILED]" || { 179 | cryptfs-tpm2 -q --owner-auth owner evict all >>$log 2>&1 180 | [ $? -eq 0 ] && echo "[SUCCEEDED]" || echo "[FAILED]" 181 | } 182 | } 183 | } 184 | } 185 | 186 | echo -n "[*] testing object generation without DA ... " 187 | echo "Sealing all with secret set ..." >>$log 2>&1 188 | cryptfs-tpm2 -q --owner-auth owner --key-secret key --passphrase-secret pass \ 189 | seal all -P auto --no-da >>$log 2>&1 190 | [ $? -ne 0 ] && echo "[FAILED]" || { 191 | echo "Unsealing passphrase with wrong secret ..." >>$log 2>&1 192 | cryptfs-tpm2 -q --passphrase-secret pass1 \ 193 | unseal passphrase -P auto 2>&1 | grep -q 0x9a2 194 | 195 | [ $? -ne 0 ] && echo "[FAILED]" || { 196 | cryptfs-tpm2 -q --passphrase-secret pass1 \ 197 | unseal passphrase -P auto 2>&1 | grep -q 0x9a2 198 | 199 | [ $? -ne 0 ] && echo "[FAILED]" || { 200 | echo "Unseal passphrase ..." >>$log 2>&1 201 | cryptfs-tpm2 -q --passphrase-secret pass \ 202 | unseal passphrase -P auto >>$log 2>&1 203 | 204 | [ $? -ne 0 ] && echo "[FAILED]" || { 205 | cryptfs-tpm2 -q --owner-auth owner evict all >>$log 2>&1 206 | [ $? -eq 0 ] && echo "[SUCCEEDED]" || echo "[FAILED]" 207 | } 208 | } 209 | } 210 | } 211 | 212 | # For cleanup 213 | cryptfs-tpm2 -q --owner-auth owner --key-secret key --passphrase-secret pass \ 214 | evict all >/dev/null 2>&1 215 | tpm2_changeauth --object-context=lockout --object-auth=lockout >/dev/null 2>&1 216 | tpm2_changeauth --object-context=owner --object-auth=owner >/dev/null 2>&1 217 | -------------------------------------------------------------------------------- /scripts/test_tpm2_tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Cryptfs-TPM2 testing script with tpm2.0-tools 4 | # 5 | # Copyright (c) 2024, Alibaba Cloud 6 | # Copyright (c) 2016-2023, Wind River Systems, Inc. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # 1) Redistributions of source code must retain the above copyright notice, 12 | # this list of conditions and the following disclaimer. 13 | # 14 | # 2) Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # 3) Neither the name of Wind River Systems nor the names of its contributors 19 | # may be used to endorse or promote products derived from this software 20 | # without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | # POSSIBILITY OF SUCH DAMAGE. 33 | # 34 | # Author: 35 | # Jia Zhang 36 | # 37 | 38 | PRI_KEY_SECRET="H31i05" 39 | PASS_SECRET="h31i05" 40 | PRI_KEY_HANDLE=0x817FFFFF 41 | PASS_HANDLE=0x817FFFFE 42 | 43 | tmpdir=`mktemp -d /tmp/cryptfs-tpm2.XXXXXX` 44 | PRI_KEY_CONTEXT_BLOB="$tmpdir/pri_key_context_blob" 45 | PASS_PUB_BLOB="$tmpdir/passphrase_pub_blob" 46 | PASS_PRIV_BLOB="$tmpdir/passphrase_priv_blob" 47 | PASS_CONTEXT_BLOB="$tmpdir/passphrase_context_blob" 48 | PASS_NAME_BLOB="$tmpdir/passphrase_name_blob" 49 | PASS_BLOB="$tmpdir/passphrase_blob" 50 | PASS="$tmpdir/passphrase" 51 | 52 | # Assume TPM is clear 53 | function check_ownership() 54 | { 55 | tpm2_changeauth --object-context=owner 56 | [ $? != 0 ] && echo "TPM is not clear" && exit 1 57 | } 58 | 59 | # Create a primary key in owner hierarchy 60 | function create_primary_key() 61 | { 62 | # SHA256 algorithm used for computing the name of the primary key 63 | local hash_alg="sha256" 64 | # RSA algorithm associated with the primary key 65 | local key_alg="rsa" 66 | 67 | echo "Creating a primary key ..." 68 | tpm2_createprimary --hierarchy=owner --hash-algorithm=$hash_alg \ 69 | --key-algorithm=$key_alg --key-auth="$PRI_KEY_SECRET" \ 70 | --key-context="$PRI_KEY_CONTEXT_BLOB" 71 | [ $? != 0 ] && echo "Unable to create the primary key" && exit 2 72 | 73 | # Make the primary key persistent in the TPM, otherwise it will be need 74 | # to be recreated after each TPM Reset if not context saved, or reloaded 75 | # with the saved context. 76 | echo "Making the primary key persistent ..." 77 | tpm2_evictcontrol --hierarchy=owner --object-context="$PRI_KEY_CONTEXT_BLOB" \ 78 | $PRI_KEY_HANDLE 79 | [ $? != 0 ] && echo "Unable to make the primary key persistent" && exit 3 80 | 81 | rm -f "$PRI_KEY_CONTEXT_BLOB" 82 | } 83 | 84 | # Create the passphase used to decrypt LUKS master key 85 | function create_passphrase() 86 | { 87 | # SHA256 algorithm used for computing the name of the sealed passphase 88 | local hash_alg="sha256" 89 | # Keyedhash algorithm associated with the sealed passphase 90 | local key_alg="keyedhash" 91 | 92 | echo "Generating a passphrase ..." 93 | tpm2_getrandom --output "$PASS" 8 94 | [ $? != 0 ] && echo "Unable to generate the passphrase" && exit 4 95 | 96 | echo "Sealing the passphrase ..." 97 | tpm2_create --hash-algorithm=$hash_alg --parent-context="$PRI_KEY_HANDLE" \ 98 | --sealing-input="$PASS" --parent-auth="$PRI_KEY_SECRET" \ 99 | --key-auth="$PASS_SECRET" --public="$PASS_PUB_BLOB" --private="$PASS_PRIV_BLOB" \ 100 | --key-context="$PASS_CONTEXT_BLOB" 101 | [ $? != 0 ] && echo "Unable to create the sealed passphrase" && exit 5 102 | 103 | echo "Loading the passphrase ..." 104 | tpm2_load --parent-context="$PRI_KEY_HANDLE" --auth="$PRI_KEY_SECRET" \ 105 | --public="$PASS_PUB_BLOB" --public="$PASS_PRIV_BLOB" \ 106 | --key-context="$PASS_CONTEXT_BLOB" --name="$PASS_NAME_BLOB" 107 | [ $? != 0 ] && echo "Unable to load the passphrase" && exit 6 108 | 109 | rm -f "$PASS_NAME_BLOB" 110 | rm -f "$PASS_PUB_BLOB" 111 | rm -f "$PASS_PRIV_BLOB" 112 | 113 | # Make the passphrase persistent in the TPM 114 | echo "Making the passphrase persistent ..." 115 | tpm2_evictcontrol --hierarchy=owner --object-context="$PASS_CONTEXT_BLOB" \ 116 | --auth="$PASS_SECRET" $PASS_HANDLE 117 | [ $? != 0 ] && echo "Unable to make the passphrase persistent" && exit 7 118 | 119 | rm -f "$PASS_CONTEXT_BLOB" 120 | } 121 | 122 | function show_passphrase() 123 | { 124 | echo "Showing the passphrase ..." 125 | hexdump -C "$PASS" 126 | rm -f "$PASS" 127 | 128 | echo "Unsealing the passphrase ..." 129 | tpm2_unseal --object-context="$PASS_HANDLE" --auth="$PASS_SECRET" \ 130 | --output="$PASS_BLOB" 131 | [ $? != 0 ] && echo "Unable to unseal the passphrase" && exit 8 132 | } 133 | 134 | function evict_all() 135 | { 136 | echo "Evicting the passphrase ..." 137 | tpm2_evictcontrol --hierarchy=owner --object-context=$PRI_KEY_HANDLE 138 | [ $? != 0 ] && echo "Unable to evict the passphrase" && exit 9 139 | 140 | echo "Evicting the primary key ..." 141 | tpm2_evictcontrol --hierarchy=owner --object-context=$PASS_HANDLE 142 | [ $? != 0 ] && echo "Unable to evict the primary key" && exit 10 143 | } 144 | 145 | check_ownership 146 | create_primary_key 147 | create_passphrase 148 | show_passphrase 149 | evict_all 150 | 151 | echo "[*] cryptfs-tpm2 testing complete!" 152 | exit 0 153 | -------------------------------------------------------------------------------- /scripts/tpm2-lockout-status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | tpm2_getcap properties-variable | grep LOCKOUT 4 | tpm2_getcap properties-variable | grep TPM2_PT_MAX_AUTH_FAIL 5 | tpm2_getcap properties-variable | grep inLockout 6 | -------------------------------------------------------------------------------- /scripts/tpm2_clear.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | tpm2_flushcontext --transient-object 4 | tpm2_evictcontrol -C o -c 0x817FFFFF 5 | tpm2_evictcontrol -C o -c 0x817FFFFE 6 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/version.mk 2 | 3 | SUBDIRS := lib cryptfs-tpm2 tcti-probe luks-setup 4 | 5 | .DEFAULT_GOAL := all 6 | .PHONE: all clean install 7 | 8 | all clean install: 9 | @for x in $(SUBDIRS); do $(MAKE) -C $$x $@ || exit $?; done 10 | -------------------------------------------------------------------------------- /src/cryptfs-tpm2/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/env.mk 2 | include $(TOPDIR)/rules.mk 3 | 4 | BIN_NAME := cryptfs-tpm2 5 | 6 | OBJS_$(BIN_NAME) := \ 7 | main.o \ 8 | subcmd_help.o \ 9 | subcmd_evict.o \ 10 | subcmd_seal.o \ 11 | subcmd_unseal.o 12 | 13 | all: $(BIN_NAME) Makefile 14 | 15 | $(BIN_NAME): $(OBJS_$(BIN_NAME)) $(TOPDIR)/src/lib/$(LIB_NAME).so 16 | $(CCLD) $^ -o $@ $(CFLAGS) 17 | 18 | clean: 19 | @$(RM) $(OBJS_$(BIN_NAME)) $(BIN_NAME) 20 | 21 | install: all 22 | $(INSTALL) -d -m 755 $(DESTDIR)$(SBINDIR) 23 | $(INSTALL) -m 700 $(BIN_NAME) $(DESTDIR)$(SBINDIR) 24 | -------------------------------------------------------------------------------- /src/cryptfs-tpm2/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static void 38 | show_banner(void) 39 | { 40 | info_cont("\nCryptfs-TPM 2.0 tool\n"); 41 | info_cont("(C)Copyright 2024, Alibaba Cloud\n"); 42 | info_cont("(C)Copyright 2016-2023, Wind River Systems, Inc.\n"); 43 | info_cont("Version: %s+git-%s\n", VERSION, cryptfs_tpm2_git_commit); 44 | } 45 | 46 | static void 47 | show_version(void) 48 | { 49 | info_cont("%s\n", VERSION); 50 | } 51 | 52 | static void 53 | show_usage(const char *prog) 54 | { 55 | info_cont("usage: %s []\n", 56 | prog); 57 | info_cont("\noptions:\n"); 58 | info_cont(" --help, -h:\n" 59 | " Print this help information\n"); 60 | info_cont(" --version, -V:\n" 61 | " Show version number\n"); 62 | info_cont(" --verbose, -v:\n" 63 | " Show verbose messages\n"); 64 | info_cont(" --quite, -q:\n" 65 | " Don't show banner information\n"); 66 | info_cont(" --owner-auth:\n" 67 | " Specify the authorization value for owner " 68 | "hierarchy\n"); 69 | info_cont(" --lockout-auth:\n" 70 | " Specify the authorization value for lockout\n"); 71 | info_cont(" --key-secret:\n" 72 | " The authorization secret used to access " 73 | "the primary key object\n"); 74 | info_cont(" --passphrase-secret:\n" 75 | " The authorization secret used to access " 76 | "the passphrase object\n"); 77 | info_cont(" --interactive:\n" 78 | " Prompt the user to type owner authentication, " 79 | "the secret info of the primary key or passphrase.\n" 80 | " Default: FALSE\n"); 81 | info_cont("\nsubcommand:\n"); 82 | info_cont(" help:\n" 83 | " Display the help information for the " 84 | "specified command\n"); 85 | info_cont(" seal:\n" 86 | " Create the persistent primary key and seal the " 87 | "passphrase\n"); 88 | info_cont(" unseal:\n" 89 | " Unseal the passphrase\n"); 90 | info_cont(" evict:\n" 91 | " Evict the persistent primary key and passphrase\n"); 92 | info_cont("\nargs:\n"); 93 | info_cont(" Run `%s help ` for the details\n", prog); 94 | } 95 | 96 | #define EXTRA_OPT_BASE 0x8000 97 | #define EXTRA_OPT_OWNER_AUTH (EXTRA_OPT_BASE + 0) 98 | #define EXTRA_OPT_LOCKOUT_AUTH (EXTRA_OPT_BASE + 1) 99 | #define EXTRA_OPT_KEY_SECRET_AUTH (EXTRA_OPT_BASE + 2) 100 | #define EXTRA_OPT_PASSPHRASE_SECRET_AUTH (EXTRA_OPT_BASE + 3) 101 | #define EXTRA_OPT_INTERACTIVE (EXTRA_OPT_BASE + 4) 102 | 103 | static int 104 | parse_options(int argc, char *argv[]) 105 | { 106 | char opts[] = "-hVvq"; 107 | struct option long_opts[] = { 108 | { "help", no_argument, NULL, 'h' }, 109 | { "version", no_argument, NULL, 'V' }, 110 | { "verbose", no_argument, NULL, 'v' }, 111 | { "quite", no_argument, NULL, 'q' }, 112 | { "owner-auth", required_argument, NULL, 113 | EXTRA_OPT_OWNER_AUTH }, 114 | { "lockout-auth", required_argument, NULL, 115 | EXTRA_OPT_LOCKOUT_AUTH }, 116 | { "key-secret", required_argument, NULL, 117 | EXTRA_OPT_KEY_SECRET_AUTH }, 118 | { "passphrase-secret", required_argument, NULL, 119 | EXTRA_OPT_PASSPHRASE_SECRET_AUTH }, 120 | { "interactive", no_argument, NULL, 121 | EXTRA_OPT_INTERACTIVE }, 122 | { 0 }, /* NULL terminated */ 123 | }; 124 | 125 | while (1) { 126 | int opt, index; 127 | 128 | opt = getopt_long(argc, argv, opts, long_opts, NULL); 129 | if (opt == -1) 130 | break; 131 | 132 | switch (opt) { 133 | case 'h': 134 | show_usage(argv[0]); 135 | exit(EXIT_SUCCESS); 136 | case 'V': 137 | show_version(); 138 | exit(EXIT_SUCCESS); 139 | case 'v': 140 | cryptfs_tpm2_util_set_verbosity(1); 141 | break; 142 | case 'q': 143 | option_quite = 1; 144 | break; 145 | case EXTRA_OPT_OWNER_AUTH: 146 | { 147 | unsigned int size = strlen(optarg); 148 | 149 | cryptfs_tpm2_option_set_owner_auth((uint8_t *)optarg, 150 | &size); 151 | break; 152 | } 153 | case EXTRA_OPT_LOCKOUT_AUTH: 154 | { 155 | unsigned int size = strlen(optarg); 156 | 157 | cryptfs_tpm2_option_set_lockout_auth((uint8_t *)optarg, 158 | &size); 159 | break; 160 | } 161 | case EXTRA_OPT_KEY_SECRET_AUTH: 162 | { 163 | unsigned int size = strlen(optarg); 164 | 165 | cryptfs_tpm2_option_set_primary_key_secret((uint8_t *)optarg, 166 | &size); 167 | break; 168 | } 169 | case EXTRA_OPT_PASSPHRASE_SECRET_AUTH: 170 | { 171 | unsigned int size = strlen(optarg); 172 | 173 | cryptfs_tpm2_option_set_passphrase_secret((uint8_t *)optarg, 174 | &size); 175 | break; 176 | } 177 | case EXTRA_OPT_INTERACTIVE: 178 | cryptfs_tpm2_option_set_interactive(); 179 | break; 180 | case 1: 181 | index = optind; 182 | return subcommand_parse(argv[0], optarg, 183 | argc - index + 1, 184 | argv + index - 1); 185 | case '?': 186 | case ':': 187 | default: 188 | show_usage(argv[0]); 189 | return -1; 190 | } 191 | } 192 | 193 | return 0; 194 | } 195 | 196 | extern subcommand_t subcommand_help; 197 | extern subcommand_t subcommand_evict; 198 | extern subcommand_t subcommand_seal; 199 | extern subcommand_t subcommand_unseal; 200 | 201 | static void 202 | exit_notify(void) 203 | { 204 | if (cryptfs_tpm2_util_verbose()) 205 | info("cryptfs-tpm2 exiting with %d (%s)\n", errno, 206 | strerror(errno)); 207 | } 208 | 209 | int 210 | main(int argc, char *argv[], char *envp[]) 211 | { 212 | atexit(exit_notify); 213 | 214 | subcommand_add(&subcommand_help); 215 | subcommand_add(&subcommand_evict); 216 | subcommand_add(&subcommand_seal); 217 | subcommand_add(&subcommand_unseal); 218 | 219 | int rc = parse_options(argc, argv); 220 | if (rc) 221 | return rc; 222 | 223 | if (!option_quite) 224 | show_banner(); 225 | 226 | return subcommand_run_current(); 227 | } 228 | -------------------------------------------------------------------------------- /src/cryptfs-tpm2/subcmd_evict.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static bool opt_evict_key; 38 | static bool opt_evict_passphrase; 39 | 40 | static void 41 | show_usage(char *prog) 42 | { 43 | info_cont("\nUsage: %s evict \n", prog); 44 | info_cont("\nobject:\n"); 45 | info_cont(" The object to be evicted. The allowed values are:\n" 46 | " - passphrase: Passphrase used to encrypt LUKS\n" 47 | " - key: Primary key used to seal the passphrase\n" 48 | " - all: All above\n"); 49 | } 50 | 51 | static int 52 | parse_arg(int opt, char *optarg) 53 | { 54 | switch (opt) { 55 | case 1: 56 | if (!strcasecmp(optarg, "key")) 57 | opt_evict_key = 1; 58 | else if (!strcasecmp(optarg, "passphrase")) 59 | opt_evict_passphrase = 1; 60 | else if (!strcasecmp(optarg, "all")) { 61 | opt_evict_key = 1; 62 | opt_evict_passphrase = 1; 63 | } else { 64 | err("Unrecognized value\n"); 65 | return -1; 66 | } 67 | break; 68 | default: 69 | return -1; 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | static int 76 | run_evict(char *prog) 77 | { 78 | int rc = 0; 79 | 80 | if (opt_evict_passphrase) { 81 | rc = cryptfs_tpm2_evict_passphrase(); 82 | if (!rc) 83 | info("The persistent passphrase is evicted\n"); 84 | } 85 | 86 | if (opt_evict_key) { 87 | int rc1 = cryptfs_tpm2_evict_primary_key(); 88 | if (!rc1) 89 | info("The persistent primary key is evicted\n"); 90 | else 91 | rc |= rc1; 92 | } 93 | 94 | return rc; 95 | } 96 | 97 | static struct option long_opts[] = { 98 | { 0 }, /* NULL terminated */ 99 | }; 100 | 101 | subcommand_t subcommand_evict = { 102 | .name = "evict", 103 | .optstring = "-", 104 | .long_opts = long_opts, 105 | .parse_arg = parse_arg, 106 | .show_usage = show_usage, 107 | .run = run_evict, 108 | }; 109 | -------------------------------------------------------------------------------- /src/cryptfs-tpm2/subcmd_help.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static char *opt_command; 38 | 39 | static void 40 | show_usage(char *prog) 41 | { 42 | info_cont("\nUsage: %s help \n", prog); 43 | info_cont("\nsubcommand:\n"); 44 | info_cont(" The subcommand to be shown.\n"); 45 | } 46 | 47 | static int 48 | parse_arg(int opt, char *optarg) 49 | { 50 | switch (opt) { 51 | case 1: 52 | { 53 | subcommand_t *cmd; 54 | 55 | cmd = subcommand_find(optarg); 56 | if (!cmd) { 57 | err("Unrecognized subcommand argument " 58 | "\"%s\" specified\n", optarg); 59 | return -1; 60 | } 61 | opt_command = optarg; 62 | } 63 | break; 64 | default: 65 | return -1; 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | static int 72 | run_help(char *prog) 73 | { 74 | if (!opt_command) { 75 | show_usage(prog); 76 | return -1; 77 | } 78 | 79 | subcommand_find(opt_command)->show_usage(prog); 80 | 81 | return 0; 82 | } 83 | 84 | static struct option long_opts[] = { 85 | { 0 }, /* NULL terminated */ 86 | }; 87 | 88 | subcommand_t subcommand_help = { 89 | .name = "help", 90 | .optstring = "-", 91 | .long_opts = long_opts, 92 | .parse_arg = parse_arg, 93 | .show_usage = show_usage, 94 | .run = run_help, 95 | }; -------------------------------------------------------------------------------- /src/cryptfs-tpm2/subcmd_seal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static bool opt_setup_key; 38 | static bool opt_setup_passphrase; 39 | static char *opt_passphrase; 40 | static TPMI_ALG_HASH opt_pcr_bank_alg = TPM2_ALG_NULL; 41 | 42 | static void 43 | show_usage(char *prog) 44 | { 45 | info_cont("\nUsage: %s seal \n", prog); 46 | info_cont("\nobject:\n"); 47 | info_cont(" The object to be sealed. The allowed values are:\n" 48 | " - passphrase: Passphrase used to encrypt LUKS\n" 49 | " - key: Primary key used to seal the passphrase\n" 50 | " - all: All above\n"); 51 | info_cont("\nargs:\n"); 52 | info_cont(" --pcr-bank-alg, -P:\n" 53 | " (optional) Use the specified PCR bank to bind the\n" 54 | " created primary key and passphrase.\n"); 55 | info_cont(" --passphrase, -p:\n" 56 | " (optional) Explicitly set the passphrase value\n" 57 | " (32-byte at most) instead of the one generated\n" 58 | " by TPM randomly. This parameter allows to be\n" 59 | " specified as a file path.\n"); 60 | info_cont(" --no-da:\n" 61 | " (optional) The authorization failure never cause\n" 62 | " DA lockout\n"); 63 | } 64 | 65 | #define EXTRA_OPT_BASE 0x8100 66 | #define EXTRA_OPT_NO_DA (EXTRA_OPT_BASE + 0) 67 | 68 | static int 69 | parse_arg(int opt, char *optarg) 70 | { 71 | switch (opt) { 72 | case 'p': 73 | opt_passphrase = optarg; 74 | break; 75 | case 'P': 76 | if (!strcasecmp(optarg, "sha1")) 77 | opt_pcr_bank_alg = TPM2_ALG_SHA1; 78 | else if (!strcasecmp(optarg, "sha256")) 79 | opt_pcr_bank_alg = TPM2_ALG_SHA256; 80 | else if (!strcasecmp(optarg, "sha384")) 81 | opt_pcr_bank_alg = TPM2_ALG_SHA384; 82 | else if (!strcasecmp(optarg, "sha512")) 83 | opt_pcr_bank_alg = TPM2_ALG_SHA512; 84 | else if (!strcasecmp(optarg, "sm3_256")) 85 | opt_pcr_bank_alg = TPM2_ALG_SM3_256; 86 | else if (!strcasecmp(optarg, "auto")) 87 | opt_pcr_bank_alg = TPM2_ALG_AUTO; 88 | else { 89 | err("Unrecognized PCR bank algorithm\n"); 90 | return -1; 91 | } 92 | 93 | if (cryptfs_tpm2_capability_pcr_bank_supported(&opt_pcr_bank_alg) == false) { 94 | err("Unsupported PCR bank algorithm\n"); 95 | return -1; 96 | } 97 | 98 | break; 99 | case EXTRA_OPT_NO_DA: 100 | option_no_da = true; 101 | break; 102 | case 1: 103 | if (!strcasecmp(optarg, "key")) 104 | opt_setup_key = 1; 105 | else if (!strcasecmp(optarg, "passphrase")) 106 | opt_setup_passphrase = 1; 107 | else if (!strcasecmp(optarg, "all")) { 108 | opt_setup_key = 1; 109 | opt_setup_passphrase = 1; 110 | } else { 111 | err("Unrecognized value\n"); 112 | return -1; 113 | } 114 | break; 115 | default: 116 | return -1; 117 | } 118 | 119 | if (opt_passphrase && !opt_setup_passphrase) { 120 | warn("-p option is ignored if the object to be sealed is not " 121 | "passphrase\n"); 122 | opt_passphrase = NULL; 123 | } 124 | 125 | return 0; 126 | } 127 | 128 | static int 129 | run_seal(char *prog) 130 | { 131 | int rc = 0; 132 | 133 | if (opt_setup_key) { 134 | rc = cryptfs_tpm2_create_primary_key(opt_pcr_bank_alg); 135 | if (rc) 136 | return rc; 137 | } 138 | 139 | if (opt_setup_passphrase) { 140 | size_t size; 141 | 142 | if (opt_passphrase) { 143 | rc = cryptfs_tpm2_util_load_file(opt_passphrase, 144 | (uint8_t **)&opt_passphrase, 145 | (unsigned long *)&size); 146 | if (rc) 147 | size = strlen(opt_passphrase); 148 | } else 149 | size = 0; 150 | 151 | if (size > CRYPTFS_TPM2_PASSPHRASE_MAX_SIZE) { 152 | err("The passphrase explicitly specified is too long\n"); 153 | return -1; 154 | } 155 | 156 | rc = cryptfs_tpm2_create_passphrase(opt_passphrase, size, 157 | opt_pcr_bank_alg); 158 | if (rc) 159 | return rc; 160 | } 161 | 162 | return rc; 163 | } 164 | 165 | static struct option long_opts[] = { 166 | { "passphrase", required_argument, NULL, 'p' }, 167 | { "pcr-bank-alg", required_argument, NULL, 'P' }, 168 | { "no-da", no_argument, NULL, EXTRA_OPT_NO_DA }, 169 | { 0 }, /* NULL terminated */ 170 | }; 171 | 172 | subcommand_t subcommand_seal = { 173 | .name = "seal", 174 | .optstring = "-p:P:", 175 | .long_opts = long_opts, 176 | .parse_arg = parse_arg, 177 | .show_usage = show_usage, 178 | .run = run_seal, 179 | }; 180 | -------------------------------------------------------------------------------- /src/cryptfs-tpm2/subcmd_unseal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static bool opt_unseal_passphrase; 38 | static char *opt_output_file; 39 | static TPMI_ALG_HASH opt_pcr_bank_alg = TPM2_ALG_NULL; 40 | 41 | static void 42 | show_usage(char *prog) 43 | { 44 | info_cont("\nUsage: %s unseal \n", prog); 45 | info_cont("\nobject:\n"); 46 | info_cont(" The object to be unsealed. The allowed values are:\n" 47 | " - passphrase: Passphrase used to encrypt LUKS\n"); 48 | info_cont("\nargs:\n"); 49 | info_cont(" --pcr-bank-alg, -P:\n" 50 | " (optional) Use the specified PCR bank to bind the\n" 51 | " created primary key and passphrase.\n"); 52 | info_cont(" --lockoutauth, -l:\n" 53 | " (optional) Specify the authorization value for\n" 54 | " lockout.\n"); 55 | } 56 | 57 | static int 58 | parse_arg(int opt, char *optarg) 59 | { 60 | switch (opt) { 61 | case 1: 62 | if (!strcasecmp(optarg, "passphrase")) 63 | opt_unseal_passphrase = 1; 64 | else { 65 | err("Unrecognized value\n"); 66 | return -1; 67 | } 68 | break; 69 | case 'o': 70 | opt_output_file = optarg; 71 | break; 72 | case 'P': 73 | if (!strcasecmp(optarg, "sha1")) 74 | opt_pcr_bank_alg = TPM2_ALG_SHA1; 75 | else if (!strcasecmp(optarg, "sha256")) 76 | opt_pcr_bank_alg = TPM2_ALG_SHA256; 77 | else if (!strcasecmp(optarg, "sha384")) 78 | opt_pcr_bank_alg = TPM2_ALG_SHA384; 79 | else if (!strcasecmp(optarg, "sha512")) 80 | opt_pcr_bank_alg = TPM2_ALG_SHA512; 81 | else if (!strcasecmp(optarg, "sm3_256")) 82 | opt_pcr_bank_alg = TPM2_ALG_SM3_256; 83 | else if (!strcasecmp(optarg, "auto")) 84 | opt_pcr_bank_alg = TPM2_ALG_AUTO; 85 | else { 86 | err("Unrecognized PCR bank algorithm\n"); 87 | return -1; 88 | } 89 | 90 | if (cryptfs_tpm2_capability_pcr_bank_supported(&opt_pcr_bank_alg) == false) { 91 | err("Unsupported PCR bank algorithm\n"); 92 | return -1; 93 | } 94 | 95 | break; 96 | default: 97 | return -1; 98 | } 99 | 100 | return 0; 101 | } 102 | 103 | static int 104 | run_unseal(char *prog) 105 | { 106 | int rc = 0; 107 | 108 | if (opt_unseal_passphrase) { 109 | unsigned char *passphrase; 110 | size_t passphrase_size; 111 | 112 | rc = cryptfs_tpm2_unseal_passphrase(opt_pcr_bank_alg, 113 | (void **)&passphrase, 114 | &passphrase_size); 115 | if (rc) 116 | return rc; 117 | 118 | if (!opt_output_file) { 119 | info("Dumping the passphrase (%Zd-byte):\n", 120 | passphrase_size); 121 | 122 | for (size_t i = 0; i < passphrase_size; i++) 123 | info_cont("0x%02x ", passphrase[i]); 124 | info_cont("\n"); 125 | } else 126 | rc = cryptfs_tpm2_util_save_output_file(opt_output_file, 127 | passphrase, 128 | passphrase_size); 129 | } 130 | 131 | return rc; 132 | } 133 | 134 | static struct option long_opts[] = { 135 | { "output", required_argument, NULL, 'o' }, 136 | { "pcr-bank-alg", required_argument, NULL, 'P' }, 137 | { "lockoutauth", optional_argument, NULL, 'l' }, 138 | { 0 }, /* NULL terminated */ 139 | }; 140 | 141 | subcommand_t subcommand_unseal = { 142 | .name = "unseal", 143 | .optstring = "-o:P:l:", 144 | .long_opts = long_opts, 145 | .parse_arg = parse_arg, 146 | .show_usage = show_usage, 147 | .run = run_unseal, 148 | }; 149 | -------------------------------------------------------------------------------- /src/include/cryptfs_tpm2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #ifndef CRYPTFS_TPM2_H 36 | #define CRYPTFS_TPM2_H 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | #include 64 | 65 | #ifndef TSS2_LEGACY_V1 66 | #include 67 | #include 68 | #else 69 | #include 70 | #include 71 | #include 72 | #endif 73 | 74 | #define stringify(x) #x 75 | 76 | #ifndef offsetof 77 | #define offsetof(type, member) ((unsigned long)&((type *)0)->member) 78 | #endif 79 | 80 | #define container_of(ptr, type, member) ({ \ 81 | const __typeof__(((type *)0)->member) *__ptr = (ptr); \ 82 | (type *)((char *)__ptr - offsetof(type, member));}) 83 | 84 | #define align_up(x, n) (((x) + ((n) - 1)) & ~((n) - 1)) 85 | #define aligned(x, n) (!!((x) & ((n) - 1))) 86 | 87 | #define cryptfs_tpm2_assert(condition, fmt, ...) \ 88 | do { \ 89 | if (!(condition)) { \ 90 | err(fmt ": %s\n", ##__VA_ARGS__, strerror(errno)); \ 91 | exit(EXIT_FAILURE); \ 92 | } \ 93 | } while (0) 94 | 95 | /* Definitions to make it compatible with tpm2-tss 1.x */ 96 | #ifdef TSS2_LEGACY_V1 97 | #define TPM2_RC TPM_RC 98 | #define TPM2_RC_SUCCESS TPM_RC_SUCCESS 99 | #define TPM2_RC_LOCKOUT TPM_RC_LOCKOUT 100 | #define TPM2_RC_FMT1 RC_FMT1 101 | #define TPM2_RC_BAD_AUTH TPM_RC_BAD_AUTH 102 | #define TPM2_RC_AUTH_FAIL TPM_RC_AUTH_FAIL 103 | 104 | #define TPM2_ALG_RSA TPM_ALG_RSA 105 | #define TPM2_ALG_HMAC TPM_ALG_HMAC 106 | #define TPM2_ALG_AES TPM_ALG_AES 107 | #define TPM2_ALG_KEYEDHASH TPM_ALG_KEYEDHASH 108 | #define TPM2_ALG_MGF1 TPM_ALG_MGF1 109 | #define TPM2_ALG_XOR TPM_ALG_XOR 110 | #define TPM2_ALG_NULL TPM_ALG_NULL 111 | #define TPM2_ALG_SHA1 TPM_ALG_SHA1 112 | #define TPM2_ALG_SHA256 TPM_ALG_SHA256 113 | #define TPM2_ALG_SHA384 TPM_ALG_SHA384 114 | #define TPM2_ALG_SHA512 TPM_ALG_SHA512 115 | #define TPM2_ALG_SM3_256 TPM_ALG_SM3_256 116 | #define TPM2_ALG_SM4 TPM_ALG_SM4 117 | #define TPM2_ALG_RSASSA TPM_ALG_RSASSA 118 | #define TPM2_ALG_RSAES TPM_ALG_RSAES 119 | #define TPM2_ALG_RSAPSS TPM_ALG_RSAPSS 120 | #define TPM2_ALG_OAEP TPM_ALG_OAEP 121 | #define TPM2_ALG_ECDSA TPM_ALG_ECDSA 122 | #define TPM2_ALG_ECDH TPM_ALG_ECDH 123 | #define TPM2_ALG_SM2 TPM_ALG_SM2 124 | #define TPM2_ALG_ECSCHNORR TPM_ALG_ECSCHNORR 125 | #define TPM2_ALG_KDF1_SP800_56A TPM_ALG_KDF1_SP800_56A 126 | #define TPM2_ALG_KDF1_SP800_108 TPM_ALG_KDF1_SP800_108 127 | #define TPM2_ALG_ECC TPM_ALG_ECC 128 | #define TPM2_ALG_SYMCIPHER TPM_ALG_SYMCIPHER 129 | #define TPM2_ALG_CTR TPM_ALG_CTR 130 | #define TPM2_ALG_OFB TPM_ALG_OFB 131 | #define TPM2_ALG_CBC TPM_ALG_CBC 132 | #define TPM2_ALG_CFB TPM_ALG_CFB 133 | #define TPM2_ALG_ECB TPM_ALG_ECB 134 | #define TPM2_ALG_ERROR TPM_ALG_ERROR 135 | #define TPM2_ALG_ID TPM_ALG_ID 136 | 137 | #define TPM2_SHA1_DIGEST_SIZE SHA1_DIGEST_SIZE 138 | #define TPM2_SHA256_DIGEST_SIZE SHA256_DIGEST_SIZE 139 | #define TPM2_SHA384_DIGEST_SIZE SHA384_DIGEST_SIZE 140 | #define TPM2_SHA512_DIGEST_SIZE SHA512_DIGEST_SIZE 141 | #define TPM2_SM3_256_DIGEST_SIZE SM3_256_DIGEST_SIZE 142 | 143 | #define TPM2_ECC_NIST_P256 TPM_ECC_NIST_P256 144 | 145 | #define TPM2_PCR_SELECT_MAX PCR_SELECT_MAX 146 | 147 | #define TPM2_CAP_HANDLES TPM_CAP_HANDLES 148 | #define TPM2_CAP_ALGS TPM_CAP_ALGS 149 | #define TPM2_CAP_ALGS TPM_CAP_ALGS 150 | #define TPM2_CAP_PCRS TPM_CAP_PCRS 151 | #define TPM2_CAP_TPM_PROPERTIES TPM_CAP_TPM_PROPERTIES 152 | 153 | #define TPM2_PT TPM_PT 154 | #define TPM2_PT_NONE TPM_PT_NONE 155 | #define TPM2_PT_HR_PERSISTENT TPM_PT_HR_PERSISTENT 156 | #define TPM2_PT_LOCKOUT_INTERVAL TPM_PT_LOCKOUT_INTERVAL 157 | #define TPM2_PT_LOCKOUT_COUNTER TPM_PT_LOCKOUT_COUNTER 158 | #define TPM2_PT_MAX_AUTH_FAIL TPM_PT_MAX_AUTH_FAIL 159 | #define TPM2_PT_LOCKOUT_RECOVERY TPM_PT_LOCKOUT_RECOVERY 160 | #define TPM2_PT_PERMANENT TPM_PT_PERMANENT 161 | 162 | #define TPM2_SE TPM_SE 163 | #define TPM2_SE_TRIAL TPM_SE_TRIAL 164 | #define TPM2_SE_POLICY TPM_SE_POLICY 165 | 166 | #define TPM2_HT_PERSISTENT TPM_HT_PERSISTENT 167 | 168 | #define TPM2_RH_OWNER TPM_RH_OWNER 169 | #define TPM2_RH_LOCKOUT TPM_RH_LOCKOUT 170 | #define TPM2_RH_NULL TPM_RH_NULL 171 | 172 | #define TPM2_RS_PW TPM_RS_PW 173 | 174 | #define TPM2_HANDLE TPM_HANDLE 175 | 176 | #define TSS2_RC_LAYER_MASK TSS2_ERROR_LEVEL_MASK 177 | #endif 178 | 179 | /* The PCR index used to seal/unseal the passphrase */ 180 | #define CRYPTFS_TPM2_PCR_INDEX 7 181 | 182 | /* The maximum length of passphrase explicitly specified */ 183 | #define CRYPTFS_TPM2_PASSPHRASE_MAX_SIZE 64 184 | 185 | /* The maximum length of secret for hierarchy authentication */ 186 | #define CRYPTFS_TPM2_SECRET_MAX_SIZE 256 187 | 188 | /* The persiste handle value for the primary key */ 189 | #define CRYPTFS_TPM2_PRIMARY_KEY_HANDLE 0x817FFFFF 190 | 191 | /* The persiste handle value for the passphrase */ 192 | #define CRYPTFS_TPM2_PASSPHRASE_HANDLE 0x817FFFFE 193 | 194 | /* The maximum atempts of prompting to type the lockout auth */ 195 | #define CRYPTFS_TPM2_MAX_LOCKOUT_RETRY 3 196 | 197 | #define gettid() syscall(__NR_gettid) 198 | 199 | #define __pr__(level, io, fmt, ...) \ 200 | do { \ 201 | time_t __t__ = time(NULL); \ 202 | struct tm __loc__; \ 203 | localtime_r(&__t__, &__loc__); \ 204 | char __buf__[64]; \ 205 | strftime(__buf__, sizeof(__buf__), "%a %b %e %T %Z %Y", &__loc__); \ 206 | fprintf(io, "%s: [" #level "] " fmt, __buf__, ##__VA_ARGS__); \ 207 | } while (0) 208 | 209 | #define die(fmt, ...) \ 210 | do { \ 211 | __pr__(FAULT, stderr, fmt, ##__VA_ARGS__); \ 212 | exit(EXIT_FAILURE); \ 213 | } while (0) 214 | 215 | #ifdef DEBUG 216 | #define dbg(fmt, ...) \ 217 | do { \ 218 | __pr__(DEBUG, stdout, fmt, ##__VA_ARGS__); \ 219 | } while (0) 220 | 221 | #define dbg_cont(fmt, ...) \ 222 | do { \ 223 | fprintf(stdout, fmt, ##__VA_ARGS__); \ 224 | } while (0) 225 | #else 226 | #define dbg(fmt, ...) 227 | #define dbg_cont(fmt, ...) 228 | #endif 229 | 230 | #define info(fmt, ...) \ 231 | do { \ 232 | __pr__(INFO, stdout, fmt, ##__VA_ARGS__); \ 233 | } while (0) 234 | 235 | #define info_cont(fmt, ...) \ 236 | fprintf(stdout, fmt, ##__VA_ARGS__) 237 | 238 | #define warn(fmt, ...) \ 239 | do { \ 240 | __pr__(WARNING, stdout, fmt, ##__VA_ARGS__); \ 241 | } while (0) 242 | 243 | #define err(fmt, ...) \ 244 | do { \ 245 | __pr__(ERROR, stderr, fmt, ##__VA_ARGS__); \ 246 | } while (0) 247 | 248 | #define err_cont(fmt, ...) \ 249 | fprintf(stderr, fmt, ##__VA_ARGS__) 250 | 251 | extern const char *cryptfs_tpm2_git_commit; 252 | extern int option_quite; 253 | extern bool option_no_da; 254 | 255 | #define TPM2_ALG_AUTO 0x4000 256 | 257 | extern int 258 | cryptfs_tpm2_util_verbose(void); 259 | 260 | extern void 261 | cryptfs_tpm2_util_set_verbosity(int verbose); 262 | 263 | extern char ** 264 | cryptfs_tpm2_util_split_string(char *in, char *delim, unsigned int *nr); 265 | 266 | extern int 267 | cryptfs_tpm2_util_mkdir(const char *dir, mode_t mode); 268 | 269 | extern bool 270 | cryptfs_tpm2_util_file_exists(const char *file_path); 271 | 272 | extern void 273 | cryptfs_tpm2_util_hex_dump(const char *prompt, const uint8_t *data, 274 | unsigned int data_size); 275 | 276 | extern int 277 | cryptfs_tpm2_util_load_file(const char *file_path, uint8_t **out, 278 | unsigned long *out_len); 279 | 280 | extern int 281 | cryptfs_tpm2_util_save_output_file(const char *file_path, uint8_t *buf, 282 | unsigned long size); 283 | 284 | extern int 285 | cryptfs_tpm2_util_get_owner_auth(uint8_t *owner_auth, 286 | unsigned int *owner_auth_size); 287 | 288 | extern int 289 | cryptfs_tpm2_util_get_primary_key_secret(uint8_t *secret, 290 | unsigned int *secret_size); 291 | 292 | extern int 293 | cryptfs_tpm2_util_get_passphrase_secret(uint8_t *secret, 294 | unsigned int *secret_size); 295 | 296 | extern TSS2_TCTI_CONTEXT * 297 | cryptfs_tpm2_tcti_init_context(void); 298 | 299 | extern void 300 | cryptfs_tpm2_tcti_teardown_context(TSS2_TCTI_CONTEXT *ctx); 301 | 302 | extern int 303 | cryptfs_tpm2_option_set_owner_auth(uint8_t *buf, unsigned int *buf_size); 304 | 305 | extern int 306 | cryptfs_tpm2_option_get_owner_auth(uint8_t *buf, unsigned int *buf_size); 307 | 308 | extern int 309 | cryptfs_tpm2_option_set_lockout_auth(uint8_t *buf, unsigned int *buf_size); 310 | 311 | extern int 312 | cryptfs_tpm2_option_get_lockout_auth(uint8_t *buf, unsigned int *buf_size); 313 | 314 | extern int 315 | cryptfs_tpm2_option_set_primary_key_secret(uint8_t *buf, 316 | unsigned int *buf_size); 317 | 318 | extern int 319 | cryptfs_tpm2_option_get_primary_key_secret(uint8_t *buf, 320 | unsigned int *buf_size); 321 | 322 | extern int 323 | cryptfs_tpm2_option_set_passphrase_secret(uint8_t *buf, 324 | unsigned int *buf_size); 325 | 326 | extern int 327 | cryptfs_tpm2_option_get_passphrase_secret(uint8_t *buf, 328 | unsigned int *buf_size); 329 | 330 | extern void 331 | cryptfs_tpm2_option_set_interactive(void); 332 | 333 | extern int 334 | cryptfs_tpm2_option_get_interactive(bool *required); 335 | 336 | extern int 337 | cryptefs_tpm2_get_random(uint8_t *random, size_t *req_size); 338 | 339 | extern int 340 | cryptfs_tpm2_create_primary_key(TPMI_ALG_HASH pcr_bank_alg); 341 | 342 | extern int 343 | cryptfs_tpm2_create_passphrase(char *passphrase, size_t passphrase_size, 344 | TPMI_ALG_HASH pcr_bank_alg); 345 | 346 | extern int 347 | cryptfs_tpm2_unseal_passphrase(TPMI_ALG_HASH pcr_bank_alg, void **passphrase, 348 | size_t *passphrase_size); 349 | 350 | extern int 351 | cryptfs_tpm2_evict_primary_key(void); 352 | 353 | extern int 354 | cryptfs_tpm2_evict_passphrase(void); 355 | 356 | extern int 357 | cryptfs_tpm2_persist_primary_key(TPMI_DH_OBJECT handle); 358 | 359 | extern int 360 | cryptfs_tpm2_persist_passphrase(TPMI_DH_OBJECT handle); 361 | 362 | extern bool 363 | cryptfs_tpm2_capability_digest_supported(TPMI_ALG_HASH *hash_alg); 364 | 365 | bool 366 | cryptfs_tpm2_capability_pcr_bank_supported(TPMI_ALG_HASH *hash_alg); 367 | 368 | int 369 | cryptfs_tpm2_capability_in_lockout(bool *in_lockout); 370 | 371 | int 372 | cryptfs_tpm2_capability_lockout_auth_required(bool *required); 373 | 374 | int 375 | cryptfs_tpm2_capability_owner_auth_required(bool *required); 376 | 377 | extern int 378 | cryptfs_tpm2_capability_da_disabled(bool *disabled); 379 | 380 | extern int 381 | cryptfs_tpm2_capability_lockout_enforced(bool *enforced); 382 | 383 | extern int 384 | cryptfs_tpm2_capability_get_lockout_counter(UINT32 *counter); 385 | 386 | extern int 387 | cryptfs_tpm2_capability_get_max_tries(UINT32 *max_tries); 388 | 389 | extern int 390 | cryptfs_tpm2_capability_get_lockout_recovery(UINT32 *recovery); 391 | 392 | int 393 | cryptfs_tpm2_read_pcr(TPMI_ALG_HASH bank_alg, unsigned int index, 394 | BYTE *out); 395 | 396 | #endif /* CRYPTFS_TPM2_H */ 397 | -------------------------------------------------------------------------------- /src/include/subcommand.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #ifndef SUBCOMMAND_H 36 | #define SUBCOMMAND_H 37 | 38 | #include 39 | 40 | typedef struct { 41 | const char *name; 42 | const char *optstring; 43 | const struct option *long_opts; 44 | int (*parse_arg)(int opt, char *optarg); 45 | void (*show_usage)(char *prog); 46 | int (*run)(char *prog); 47 | } subcommand_t; 48 | 49 | extern int 50 | subcommand_add(subcommand_t *subcmd); 51 | 52 | extern subcommand_t * 53 | subcommand_find(char *subcmd); 54 | 55 | extern int 56 | subcommand_parse(char *prog, char *subcmd, int argc, char *argv[]); 57 | 58 | extern int 59 | subcommand_run_current(void); 60 | 61 | #endif /* SUBCOMMAND_H */ -------------------------------------------------------------------------------- /src/lib/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/env.mk 2 | include $(TOPDIR)/rules.mk 3 | 4 | LIB_NAME := libcryptfs-tpm2 5 | 6 | LIB_TARGETS := $(LIB_NAME).so $(LIB_NAME).a 7 | 8 | OBJS_$(LIB_NAME) = \ 9 | init.o \ 10 | tss2.o \ 11 | option.o \ 12 | subcommand.o \ 13 | util.o \ 14 | tcti.o \ 15 | build_info.o \ 16 | secret_area.o \ 17 | secret.o \ 18 | session.o \ 19 | evict.o \ 20 | random.o \ 21 | create.o \ 22 | unseal.o \ 23 | policy.o \ 24 | pcr.o \ 25 | hash.o \ 26 | capability.o \ 27 | da.o 28 | 29 | CFLAGS += -fpic 30 | 31 | all: $(LIB_TARGETS) Makefile 32 | 33 | clean: 34 | @$(RM) $(LIB_TARGETS) $(OBJS_$(LIB_NAME)) \ 35 | $(addsuffix .*, $(LIB_TARGETS)) \ 36 | build_info.c secret.c \ 37 | *.secret 38 | 39 | install: all 40 | $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR) 41 | $(INSTALL) -m 755 $(LIB_NAME).a $(DESTDIR)$(LIBDIR) 42 | $(INSTALL) -m 755 $(LIB_NAME).so $(DESTDIR)$(LIBDIR)/$(LIB_NAME).so.$(VERSION) 43 | $(foreach x, $(LIB_NAME), ln -sfn $(x).so.$(VERSION) $(DESTDIR)$(LIBDIR)/$(patsubst %,%.so.$(MAJOR_VERSION),$(x)); \ 44 | ln -sfn $(x).so.$(VERSION) $(DESTDIR)$(LIBDIR)/$(patsubst %,%.so,$(x));) 45 | 46 | $(LIB_NAME).so: $(OBJS_$(LIB_NAME)) 47 | $(CCLD) $^ -o $@ $(CFLAGS) -shared -Wl,-soname,$(patsubst %,%.$(MAJOR_VERSION),$@) 48 | 49 | $(LIB_NAME).a: $(filter-out init.o,$(OBJS_$(LIB_NAME))) 50 | $(AR) rcs $@ $^ 51 | 52 | define encrypt_secret 53 | $(TOPDIR)/scripts/encrypt_secret.py -i "$(1)" > "$(2)" || exit 1 54 | endef 55 | 56 | build_info.c: build_info.c.in 57 | sed -e "s~@@CRYPTFS_TPM2_GIT_COMMIT@@~$(shell if [ -e $(TOPDIR)/.git ]; then git log -1 --pretty=format:%H | tr -d '\n'; elif [ -f $(TOPDIR)/commit ]; then cat $(TOPDIR)/commit | tr -d '\n'; else echo -n ???????; fi)~" \ 58 | < $< > $@ 59 | 60 | secret_area.S: primary_key.secret passphrase.secret 61 | 62 | primary_key.secret: $(TOPDIR)/scripts/encrypt_secret.py 63 | $(call encrypt_secret,$(primary_key_secret),$@) 64 | 65 | passphrase.secret: $(TOPDIR)/scripts/encrypt_secret.py 66 | $(call encrypt_secret,$(passphrase_secret),$@) 67 | 68 | secret.c: secret.c.in 69 | sed -e "s/@@CRYPTFS_TPM2_SECRET_XOR_BYTE_CODE@@/$(secret_xor_byte_code)/" \ 70 | < $< > $@ 71 | -------------------------------------------------------------------------------- /src/lib/build_info.c.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | const char *cryptfs_tpm2_git_commit = "@@CRYPTFS_TPM2_GIT_COMMIT@@"; 38 | -------------------------------------------------------------------------------- /src/lib/capability.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | #define prop_str(val) (val) ? "set" : "clear" 40 | 41 | typedef struct { 42 | TPMI_ALG_HASH alg; 43 | unsigned int weight; 44 | } digest_alg_weight_t; 45 | 46 | int 47 | capability_read_public(TPMI_DH_OBJECT handle, TPM2B_PUBLIC *public_out) 48 | { 49 | TPMI_YES_NO more_data; 50 | TPMS_CAPABILITY_DATA capability_data; 51 | 52 | UINT32 rc = Tss2_Sys_GetCapability(cryptfs_tpm2_sys_context, NULL, 53 | TPM2_CAP_HANDLES, TPM2_HT_PERSISTENT, 54 | TPM2_HR_PERSISTENT, &more_data, 55 | &capability_data, NULL); 56 | if (rc != TPM2_RC_SUCCESS) { 57 | err("Unable to get the TPM persistent handles (%#x)", rc); 58 | return -1; 59 | }; 60 | 61 | dbg("%d persistent objects detected:\n", capability_data.data.handles.count); 62 | for (UINT32 i = 0; i < capability_data.data.handles.count; ++i) { 63 | TPMI_DH_OBJECT h = capability_data.data.handles.handle[i]; 64 | 65 | dbg_cont(" [%02d] %#8.8x\n", i, h); 66 | 67 | if (h != handle) 68 | continue; 69 | 70 | /* Actually TPM2_ReadPublic doesn't require any authorization */ 71 | struct session_complex s; 72 | password_session_create(&s, NULL, 0); 73 | 74 | #ifndef TSS2_LEGACY_V1 75 | TPM2B_NAME name = { sizeof(TPM2B_NAME)-2, }; 76 | TPM2B_NAME qualified_name = { sizeof(TPM2B_NAME)-2, }; 77 | #else 78 | TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } }; 79 | TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } }; 80 | #endif 81 | rc = Tss2_Sys_ReadPublic(cryptfs_tpm2_sys_context, handle, 82 | NULL, public_out, &name, 83 | &qualified_name, &s.sessionsDataOut); 84 | if (rc != TPM2_RC_SUCCESS) { 85 | err("Unable to read the public area for the " 86 | "persistent handle %#8.8x (%#x)", handle, rc); 87 | return -1; 88 | } 89 | 90 | return 0; 91 | } 92 | 93 | return -1; 94 | } 95 | 96 | static unsigned int 97 | weight_digest_algorithm(TPMI_ALG_HASH hash_alg) 98 | { 99 | digest_alg_weight_t alg_list[] = { 100 | { 101 | TPM2_ALG_SHA1, 102 | TPM2_SHA1_DIGEST_SIZE 103 | }, 104 | { 105 | TPM2_ALG_SHA256, 106 | TPM2_SHA256_DIGEST_SIZE 107 | }, 108 | { 109 | TPM2_ALG_SHA384, 110 | TPM2_SHA384_DIGEST_SIZE 111 | }, 112 | { 113 | TPM2_ALG_SHA512, 114 | TPM2_SHA512_DIGEST_SIZE 115 | }, 116 | { 117 | TPM2_ALG_SM3_256, 118 | TPM2_SM3_256_DIGEST_SIZE + 5 119 | }, 120 | { 121 | TPM2_ALG_NULL, 122 | 0 123 | } 124 | }; 125 | 126 | for (unsigned int i = 0; alg_list[i].alg != TPM2_ALG_NULL; ++i) { 127 | if (hash_alg == alg_list[i].alg) 128 | return alg_list[i].weight; 129 | } 130 | 131 | return 0; 132 | } 133 | 134 | static unsigned int 135 | digest_algorithm_base_weight(TPMI_ALG_HASH hash_alg) 136 | { 137 | switch (hash_alg) { 138 | case TPM2_ALG_SHA1: 139 | return 1; 140 | case TPM2_ALG_SHA256: 141 | return 2; 142 | case TPM2_ALG_SM3_256: 143 | return 3; 144 | case TPM2_ALG_SHA384: 145 | return 7; 146 | case TPM2_ALG_SHA512: 147 | return 9; 148 | case TPM2_ALG_NULL: 149 | default: 150 | break; 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | static const char * 157 | show_algorithm_name(TPM2_ALG_ID alg) 158 | { 159 | switch (alg) { 160 | case TPM2_ALG_RSA: 161 | return "RSA"; 162 | case TPM2_ALG_SHA1: 163 | return "SHA-1"; 164 | case TPM2_ALG_HMAC: 165 | return "HMAC"; 166 | case TPM2_ALG_AES: 167 | return "AES"; 168 | case TPM2_ALG_MGF1: 169 | return "MGF1"; 170 | case TPM2_ALG_KEYEDHASH: 171 | return "KEYEDHASH"; 172 | case TPM2_ALG_XOR: 173 | return "XOR"; 174 | case TPM2_ALG_SHA256: 175 | return "SHA-256"; 176 | case TPM2_ALG_SHA384: 177 | return "SHA-384"; 178 | case TPM2_ALG_SHA512: 179 | return "SHA-512"; 180 | case TPM2_ALG_NULL: 181 | return "NULL"; 182 | case TPM2_ALG_SM3_256: 183 | return "SM3-256"; 184 | case TPM2_ALG_SM4: 185 | return "SM4"; 186 | case TPM2_ALG_RSASSA: 187 | return "RSASSA PKCS#1 v1.5"; 188 | case TPM2_ALG_RSAES: 189 | return "RSAES PKCS#1 v1.5"; 190 | case TPM2_ALG_RSAPSS: 191 | return "RSAES PSS"; 192 | case TPM2_ALG_OAEP: 193 | return "RSAES OAEP"; 194 | case TPM2_ALG_ECDSA: 195 | return "ECDSA"; 196 | case TPM2_ALG_ECDH: 197 | return "ECC CDH"; 198 | case TPM2_ALG_SM2: 199 | return "SM2"; 200 | case TPM2_ALG_ECSCHNORR: 201 | return "ECS"; 202 | case TPM2_ALG_KDF1_SP800_56A: 203 | return "KDF1 (NIST SP800-56A)"; 204 | case TPM2_ALG_KDF1_SP800_108: 205 | return "KDF1 (NIST SP800-108)"; 206 | case TPM2_ALG_ECC: 207 | return "ECC"; 208 | case TPM2_ALG_SYMCIPHER: 209 | return "Symmetric block cipher"; 210 | case TPM2_ALG_CTR: 211 | return "Symmetric block cipher (Counter mode)"; 212 | case TPM2_ALG_OFB: 213 | return "Symmetric block cipher (Output Feedback mode)"; 214 | case TPM2_ALG_CBC: 215 | return "Symmetric block cipher (Cipher Block Chaining mode)"; 216 | case TPM2_ALG_CFB: 217 | return "Symmetric block cipher (Cipher Feedback mode)"; 218 | case TPM2_ALG_ECB: 219 | return "Symmetric block cipher (Electronic Codebook mode)"; 220 | case TPM2_ALG_ERROR: 221 | return NULL; 222 | case 0x00c1 ... 0x00c6: 223 | return "Reserved (for TPM 1.2 tags conflict)"; 224 | case 0x8000 ... 0xffff: 225 | return "Reserved (for other structure tags)"; 226 | } 227 | 228 | return NULL; 229 | } 230 | 231 | static bool 232 | is_null_hash(BYTE *hash, unsigned int hash_size) 233 | { 234 | for (unsigned int i = 0; i < hash_size; ++i) { 235 | if (hash[i]) 236 | return false; 237 | } 238 | 239 | return true; 240 | } 241 | 242 | bool 243 | cryptfs_tpm2_capability_digest_algorithm_supported(TPMI_ALG_HASH *hash_alg) 244 | { 245 | TPMI_YES_NO more_data; 246 | TPMS_CAPABILITY_DATA capability_data; 247 | UINT32 rc; 248 | 249 | rc = Tss2_Sys_GetCapability(cryptfs_tpm2_sys_context, NULL, 250 | TPM2_CAP_ALGS, TPM2_PT_NONE, 1, &more_data, 251 | &capability_data, NULL); 252 | if (rc != TPM2_RC_SUCCESS) { 253 | err("Unable to get the TPM supported algorithms (%#x)", rc); 254 | return false; 255 | }; 256 | 257 | TPML_ALG_PROPERTY *algs = &capability_data.data.algorithms; 258 | unsigned int i; 259 | 260 | #ifdef DEBUG 261 | dbg("%d algorithms detected: ", algs->count); 262 | 263 | for (i = 0; i < algs->count; ++i) 264 | dbg_cont("%s ", 265 | show_algorithm_name(algs->algProperties[i].alg)); 266 | 267 | dbg_cont("\n"); 268 | #endif 269 | 270 | TPMI_ALG_HASH preferred_alg = TPM2_ALG_NULL; 271 | unsigned int weight = 0; 272 | 273 | for (i = 0; i < algs->count; ++i) { 274 | TPMS_ALG_PROPERTY alg_property = algs->algProperties[i]; 275 | unsigned alg_weight; 276 | #ifndef TSS2_LEGACY_V1 277 | if (!(alg_property.algProperties & TPMA_ALGORITHM_HASH )) 278 | 279 | #else 280 | if (alg_property.algProperties.hash != 1) 281 | #endif 282 | continue; 283 | 284 | if (*hash_alg == alg_property.alg) 285 | return true; 286 | 287 | alg_weight = weight_digest_algorithm(alg_property.alg); 288 | if (alg_weight > weight) { 289 | weight = alg_weight; 290 | preferred_alg = alg_property.alg; 291 | } 292 | } 293 | 294 | if (*hash_alg != TPM2_ALG_AUTO) 295 | return false; 296 | 297 | if (preferred_alg == TPM2_ALG_NULL) 298 | return false; 299 | 300 | *hash_alg = preferred_alg; 301 | 302 | return true; 303 | } 304 | 305 | bool 306 | cryptfs_tpm2_capability_pcr_bank_supported(TPMI_ALG_HASH *hash_alg) 307 | { 308 | TPMI_YES_NO more_data; 309 | TPMS_CAPABILITY_DATA capability_data; 310 | UINT32 rc; 311 | 312 | rc = Tss2_Sys_GetCapability(cryptfs_tpm2_sys_context, NULL, 313 | TPM2_CAP_PCRS, TPM2_PT_NONE, 1, &more_data, 314 | &capability_data, NULL); 315 | if (rc != TPM2_RC_SUCCESS) { 316 | err("Unable to get the TPM PCR banks (%#x)", rc); 317 | return false; 318 | } 319 | 320 | unsigned int i; 321 | TPML_PCR_SELECTION *banks = &capability_data.data.assignedPCR; 322 | 323 | #ifdef DEBUG 324 | dbg("%d PCR banks detected: ", banks->count); 325 | 326 | for (i = 0; i < banks->count; ++i) 327 | dbg_cont("%s ", 328 | show_algorithm_name(banks->pcrSelections[i].hash)); 329 | 330 | dbg_cont("\n"); 331 | #endif 332 | 333 | TPMI_ALG_HASH preferred_alg = TPM2_ALG_NULL; 334 | unsigned int weight = 0; 335 | 336 | for (i = 0; i < banks->count; ++i) { 337 | TPMI_ALG_HASH bank_alg; 338 | 339 | bank_alg = banks->pcrSelections[i].hash; 340 | if (*hash_alg == bank_alg) 341 | return true; 342 | 343 | if (*hash_alg != TPM2_ALG_AUTO) 344 | continue; 345 | 346 | unsigned int alg_weight; 347 | 348 | alg_weight = weight_digest_algorithm(bank_alg); 349 | 350 | UINT16 alg_size; 351 | 352 | util_digest_size(bank_alg, &alg_size); 353 | 354 | BYTE pcr_value[alg_size]; 355 | 356 | rc = cryptfs_tpm2_read_pcr(bank_alg, 357 | CRYPTFS_TPM2_PCR_INDEX, 358 | pcr_value); 359 | if (rc != TPM2_RC_SUCCESS) 360 | continue; 361 | 362 | if (is_null_hash(pcr_value, alg_size)) { 363 | warn("%s PCR bank is unused\n", 364 | show_algorithm_name(bank_alg)); 365 | 366 | alg_weight = digest_algorithm_base_weight(bank_alg); 367 | } 368 | 369 | if (alg_weight > weight) { 370 | weight = alg_weight; 371 | preferred_alg = bank_alg; 372 | } 373 | } 374 | 375 | if (*hash_alg != TPM2_ALG_AUTO) 376 | return false; 377 | 378 | if (preferred_alg == TPM2_ALG_NULL) 379 | return false; 380 | 381 | *hash_alg = preferred_alg; 382 | 383 | info("%s PCR bank voted\n", show_algorithm_name(preferred_alg)); 384 | 385 | return true; 386 | } 387 | 388 | static UINT32 389 | get_permanent_property(TPM2_PT property, UINT32 *value) 390 | { 391 | TPMI_YES_NO more_data; 392 | TPMS_CAPABILITY_DATA capability_data; 393 | UINT32 rc; 394 | 395 | rc = Tss2_Sys_GetCapability(cryptfs_tpm2_sys_context, NULL, 396 | TPM2_CAP_TPM_PROPERTIES, property, 397 | 1, &more_data, 398 | &capability_data, NULL); 399 | if (rc != TPM2_RC_SUCCESS) { 400 | err("Unable to get the TPM properties (%#x)", rc); 401 | return rc; 402 | } 403 | 404 | TPML_TAGGED_TPM_PROPERTY *properties; 405 | 406 | properties = &capability_data.data.tpmProperties; 407 | 408 | if (properties->count != 1) 409 | die("Invalid number of TPM permanent properties (%d)\n", 410 | properties->count); 411 | 412 | TPMS_TAGGED_PROPERTY *tagged_property = properties->tpmProperty; 413 | 414 | if (tagged_property->property != property) 415 | die("Invalid tagged property (0x%x)\n", 416 | tagged_property->property); 417 | 418 | *value = tagged_property->value; 419 | 420 | return TPM2_RC_SUCCESS; 421 | } 422 | 423 | int 424 | cryptfs_tpm2_capability_in_lockout(bool *in_lockout) 425 | { 426 | if (!in_lockout) 427 | return EXIT_FAILURE; 428 | 429 | TPMA_PERMANENT attrs; 430 | UINT32 rc; 431 | 432 | rc = get_permanent_property(TPM2_PT_PERMANENT, (UINT32 *)&attrs); 433 | if (rc == TPM2_RC_SUCCESS) { 434 | #ifndef TSS2_LEGACY_V1 435 | 436 | *in_lockout = !!(attrs & TPMA_PERMANENT_INLOCKOUT); 437 | #else 438 | *in_lockout = !!attrs.inLockout; 439 | #endif 440 | return EXIT_SUCCESS; 441 | } 442 | 443 | return EXIT_FAILURE; 444 | } 445 | 446 | int 447 | cryptfs_tpm2_capability_lockout_auth_required(bool *required) 448 | { 449 | if (!required) 450 | return EXIT_FAILURE; 451 | 452 | TPMA_PERMANENT attrs; 453 | UINT32 rc; 454 | 455 | rc = get_permanent_property(TPM2_PT_PERMANENT, (UINT32 *)&attrs); 456 | if (rc == TPM2_RC_SUCCESS) { 457 | #ifndef TSS2_LEGACY_V1 458 | 459 | *required = !!(attrs & TPMA_PERMANENT_LOCKOUTAUTHSET); 460 | #else 461 | *required = !!attrs.lockoutAuthSet; 462 | #endif 463 | return EXIT_SUCCESS; 464 | } 465 | 466 | return EXIT_FAILURE; 467 | } 468 | 469 | int 470 | cryptfs_tpm2_capability_owner_auth_required(bool *required) 471 | { 472 | if (!required) 473 | return EXIT_FAILURE; 474 | 475 | TPMA_PERMANENT attrs; 476 | UINT32 rc; 477 | 478 | rc = get_permanent_property(TPM2_PT_PERMANENT, (UINT32 *)&attrs); 479 | if (rc == TPM2_RC_SUCCESS) { 480 | #ifndef TSS2_LEGACY_V1 481 | 482 | *required = !!(attrs & TPMA_PERMANENT_OWNERAUTHSET); 483 | #else 484 | *required = !!attrs.ownerAuthSet; 485 | #endif 486 | return EXIT_SUCCESS; 487 | } 488 | 489 | return EXIT_FAILURE; 490 | } 491 | 492 | int 493 | cryptfs_tpm2_capability_da_disabled(bool *disabled) 494 | { 495 | if (!disabled) 496 | return EXIT_FAILURE; 497 | 498 | UINT32 recovery_time; 499 | UINT32 rc; 500 | 501 | rc = get_permanent_property(TPM2_PT_LOCKOUT_INTERVAL, 502 | &recovery_time); 503 | if (rc == TPM2_RC_SUCCESS) { 504 | bool enforced; 505 | 506 | rc = cryptfs_tpm2_capability_lockout_enforced(&enforced); 507 | if (rc == EXIT_FAILURE) 508 | return EXIT_FAILURE; 509 | 510 | *disabled = !recovery_time && enforced == false; 511 | return EXIT_SUCCESS; 512 | } 513 | 514 | return EXIT_FAILURE; 515 | } 516 | 517 | int 518 | cryptfs_tpm2_capability_lockout_enforced(bool *enforced) 519 | { 520 | if (!enforced) 521 | return EXIT_FAILURE; 522 | 523 | UINT32 max_tries; 524 | int rc; 525 | 526 | rc = cryptfs_tpm2_capability_get_max_tries(&max_tries); 527 | if (rc == EXIT_FAILURE) 528 | return EXIT_FAILURE; 529 | 530 | *enforced = !max_tries; 531 | 532 | return EXIT_SUCCESS; 533 | } 534 | 535 | int 536 | cryptfs_tpm2_capability_get_lockout_counter(UINT32 *counter) 537 | { 538 | if (!counter) 539 | return EXIT_FAILURE; 540 | 541 | UINT32 rc; 542 | 543 | rc = get_permanent_property(TPM2_PT_LOCKOUT_COUNTER, 544 | counter); 545 | if (rc == TPM2_RC_SUCCESS) 546 | return EXIT_SUCCESS; 547 | 548 | return EXIT_FAILURE; 549 | } 550 | 551 | int 552 | cryptfs_tpm2_capability_get_max_tries(UINT32 *max_tries) 553 | { 554 | if (!max_tries) 555 | return EXIT_FAILURE; 556 | 557 | UINT32 rc; 558 | 559 | rc = get_permanent_property(TPM2_PT_MAX_AUTH_FAIL, 560 | max_tries); 561 | if (rc == TPM2_RC_SUCCESS) 562 | return EXIT_SUCCESS; 563 | 564 | return EXIT_FAILURE; 565 | } 566 | 567 | int 568 | cryptfs_tpm2_capability_get_lockout_recovery(UINT32 *recovery) 569 | { 570 | if (!recovery) 571 | return EXIT_FAILURE; 572 | 573 | UINT32 rc; 574 | 575 | rc = get_permanent_property(TPM2_PT_LOCKOUT_RECOVERY, 576 | recovery); 577 | if (rc == TPM2_RC_SUCCESS) 578 | return EXIT_SUCCESS; 579 | 580 | return EXIT_FAILURE; 581 | } 582 | -------------------------------------------------------------------------------- /src/lib/da.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | static int 40 | clear_lockout(const char *lockout_auth) 41 | { 42 | unsigned int lockout_auth_size; 43 | 44 | if (!lockout_auth) 45 | lockout_auth_size = 0; 46 | else 47 | lockout_auth_size = strlen(lockout_auth); 48 | 49 | struct session_complex s; 50 | 51 | password_session_create(&s, (char *)lockout_auth, lockout_auth_size); 52 | 53 | UINT32 rc; 54 | 55 | rc = Tss2_Sys_DictionaryAttackLockReset(cryptfs_tpm2_sys_context, 56 | TPM2_RH_LOCKOUT, 57 | &s.sessionsData, 58 | &s.sessionsDataOut); 59 | if (rc != TPM2_RC_SUCCESS) { 60 | if (rc == TPM2_RC_LOCKOUT) { 61 | /* 62 | * XXX: recover this sort of lockout via lockoutAuth 63 | * policy. 64 | */ 65 | UINT32 recovery; 66 | int ret; 67 | 68 | ret = cryptfs_tpm2_capability_get_lockout_recovery(&recovery); 69 | if (ret == EXIT_SUCCESS) 70 | err("TPM lockout will be recovered within %d " 71 | "seconds\n", recovery); 72 | } 73 | 74 | err("Unable to reset DA lockout (err: 0x%x)\n", rc); 75 | return EXIT_FAILURE; 76 | } 77 | 78 | info("Reset DA lockout\n"); 79 | 80 | return EXIT_SUCCESS; 81 | } 82 | 83 | int 84 | da_reset(void) 85 | { 86 | UINT32 counter; 87 | int rc; 88 | 89 | rc = cryptfs_tpm2_capability_get_lockout_counter(&counter); 90 | if (rc == EXIT_FAILURE) 91 | return EXIT_FAILURE; 92 | 93 | UINT32 max_tries; 94 | 95 | rc = cryptfs_tpm2_capability_get_max_tries(&max_tries); 96 | if (rc == EXIT_FAILURE) 97 | return EXIT_FAILURE; 98 | 99 | dbg("counter (%d) VS max-tries (%d)\n", counter, max_tries); 100 | 101 | if (counter != max_tries) { 102 | info("Lockout already recovered\n"); 103 | return EXIT_SUCCESS; 104 | } 105 | 106 | bool disabled; 107 | 108 | rc = cryptfs_tpm2_capability_da_disabled(&disabled); 109 | if (rc == EXIT_FAILURE) 110 | return EXIT_FAILURE; 111 | 112 | if (disabled == true) { 113 | info("DA protection is disabled\n"); 114 | return EXIT_SUCCESS; 115 | } 116 | 117 | bool enforced; 118 | 119 | rc = cryptfs_tpm2_capability_lockout_enforced(&enforced); 120 | if (rc == EXIT_FAILURE) 121 | return EXIT_FAILURE; 122 | 123 | /* 124 | * XXX: attempt to fix the DA policy with lockoutAuth. 125 | */ 126 | if (enforced == true) { 127 | err("Unable to reset DA because lockout is enforced\n"); 128 | return EXIT_FAILURE; 129 | } 130 | 131 | bool required; 132 | 133 | rc = cryptfs_tpm2_capability_lockout_auth_required(&required); 134 | if (rc == EXIT_FAILURE) 135 | return EXIT_FAILURE; 136 | 137 | uint8_t lockout_auth[sizeof(TPMU_HA)]; 138 | unsigned int lockout_auth_size = sizeof(lockout_auth); 139 | 140 | rc = cryptfs_tpm2_option_get_lockout_auth(lockout_auth, 141 | &lockout_auth_size); 142 | if (rc == EXIT_FAILURE) 143 | return EXIT_FAILURE; 144 | 145 | if (required == false) { 146 | if (lockout_auth_size) 147 | warn("Ignore --lockout-auth due to lockout " 148 | "authentication not required\n"); 149 | 150 | return clear_lockout(NULL); 151 | } 152 | 153 | if (lockout_auth_size) { 154 | rc = clear_lockout((const char *)lockout_auth); 155 | if (rc == EXIT_SUCCESS) { 156 | info("Automatically reset DA lockout\n"); 157 | return rc; 158 | } 159 | 160 | err("Wrong lockout authentication specified by " 161 | "--lockout-auth\n"); 162 | } 163 | 164 | info("TPM is in lockout state. Need to type lockout authentication " 165 | "to reset DA lockout\n"); 166 | 167 | if (cryptfs_tpm2_option_get_interactive(&required)) 168 | return EXIT_FAILURE; 169 | 170 | rc = EXIT_FAILURE; 171 | 172 | if (required == false) 173 | goto out; 174 | 175 | int retry = 0; 176 | 177 | while (retry++ < CRYPTFS_TPM2_MAX_LOCKOUT_RETRY) { 178 | if (get_input("Lockout Authentication: ", lockout_auth, 179 | &lockout_auth_size) == EXIT_FAILURE) 180 | break; 181 | 182 | rc = clear_lockout((const char *)lockout_auth); 183 | if (rc == EXIT_SUCCESS) 184 | break; 185 | 186 | err("Wrong lockout authentication specified\n"); 187 | } 188 | 189 | out: 190 | if (rc == EXIT_SUCCESS) 191 | info("Automatically reset DA lockout\n"); 192 | else 193 | warn("Please specify correct --lockout-auth to reset DA " 194 | "lockout\n"); 195 | 196 | return rc; 197 | } 198 | 199 | int 200 | da_check_and_reset(void) 201 | { 202 | bool in_lockout; 203 | int rc; 204 | 205 | rc = cryptfs_tpm2_capability_in_lockout(&in_lockout); 206 | if (rc == EXIT_SUCCESS && in_lockout == true) 207 | rc = da_reset(); 208 | 209 | return rc; 210 | } 211 | -------------------------------------------------------------------------------- /src/lib/evict.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | static int 40 | evictcontrol(TPMI_DH_OBJECT obj_handle, TPMI_DH_PERSISTENT persist_handle) 41 | { 42 | uint8_t owner_auth[sizeof(TPMU_HA)]; 43 | unsigned int owner_auth_size = sizeof(owner_auth); 44 | 45 | if (cryptfs_tpm2_option_get_owner_auth(owner_auth, &owner_auth_size)) 46 | return EXIT_FAILURE; 47 | 48 | struct session_complex s; 49 | UINT32 rc; 50 | 51 | re_auth_owner: 52 | password_session_create(&s, (char *)owner_auth, owner_auth_size); 53 | redo: 54 | rc = Tss2_Sys_EvictControl(cryptfs_tpm2_sys_context, TPM2_RH_OWNER, 55 | obj_handle, &s.sessionsData, persist_handle, 56 | &s.sessionsDataOut); 57 | if (rc != TPM2_RC_SUCCESS) { 58 | if (rc == TPM2_RC_LOCKOUT) { 59 | if (da_reset() == EXIT_SUCCESS) 60 | goto redo; 61 | } else if (tpm2_rc_is_format_one(rc) && 62 | (tpm2_rc_get_code_7bit(rc) | TPM2_RC_FMT1) == 63 | TPM2_RC_BAD_AUTH) { 64 | owner_auth_size = sizeof(owner_auth); 65 | 66 | if (cryptfs_tpm2_util_get_owner_auth(owner_auth, 67 | &owner_auth_size) == 68 | EXIT_SUCCESS) 69 | goto re_auth_owner; 70 | } 71 | 72 | err("Unable to evictcontrol the object (%#x)\n", rc); 73 | return -1; 74 | } 75 | 76 | return 0; 77 | } 78 | 79 | int 80 | cryptfs_tpm2_evict_primary_key(void) 81 | { 82 | return evictcontrol((TPMI_DH_OBJECT)CRYPTFS_TPM2_PRIMARY_KEY_HANDLE, 83 | (TPMI_DH_PERSISTENT)CRYPTFS_TPM2_PRIMARY_KEY_HANDLE); 84 | } 85 | 86 | int 87 | cryptfs_tpm2_evict_passphrase(void) 88 | { 89 | return evictcontrol((TPMI_DH_OBJECT)CRYPTFS_TPM2_PASSPHRASE_HANDLE, 90 | (TPMI_DH_PERSISTENT)CRYPTFS_TPM2_PASSPHRASE_HANDLE); 91 | } 92 | 93 | int 94 | cryptfs_tpm2_persist_primary_key(TPMI_DH_OBJECT handle) 95 | { 96 | return evictcontrol(handle, 97 | (TPMI_DH_PERSISTENT)CRYPTFS_TPM2_PRIMARY_KEY_HANDLE); 98 | } 99 | 100 | int 101 | cryptfs_tpm2_persist_passphrase(TPMI_DH_OBJECT handle) 102 | { 103 | return evictcontrol(handle, 104 | (TPMI_DH_PERSISTENT)CRYPTFS_TPM2_PASSPHRASE_HANDLE); 105 | } 106 | -------------------------------------------------------------------------------- /src/lib/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | static int 40 | tpm_hash(TPMI_ALG_HASH hash_alg, BYTE *data, UINT16 data_len, 41 | BYTE *hash, UINT16 hash_size) 42 | { 43 | TPM2B_MAX_BUFFER data_buf; 44 | 45 | #ifndef TSS2_LEGACY_V1 46 | if (data_len > sizeof(data_buf.buffer)) { 47 | #else 48 | if (data_len > sizeof(data_buf.t.buffer)) { 49 | #endif 50 | err("The data to be hashed is too large\n"); 51 | return -1; 52 | } 53 | 54 | #ifndef TSS2_LEGACY_V1 55 | data_buf.size = data_len; 56 | memcpy(data_buf.buffer, data, data_len); 57 | TPM2B_DIGEST digest = { hash_size, }; 58 | #else 59 | data_buf.t.size = data_len; 60 | memcpy(data_buf.t.buffer, data, data_len); 61 | TPM2B_DIGEST digest = { { hash_size, } }; 62 | #endif 63 | 64 | UINT32 rc = Tss2_Sys_Hash(cryptfs_tpm2_sys_context, NULL, &data_buf, 65 | hash_alg, TPM2_RH_NULL, &digest, NULL, 66 | NULL); 67 | if (rc != TPM2_RC_SUCCESS) { 68 | err("Unable to calculate the digest (%#x)\n", rc); 69 | return -1; 70 | } 71 | 72 | #ifndef TSS2_LEGACY_V1 73 | memcpy(hash, digest.buffer, hash_size); 74 | #else 75 | memcpy(hash, digest.t.buffer, hash_size); 76 | #endif 77 | return 0; 78 | } 79 | 80 | int 81 | sha1_digest(BYTE *data, UINT16 data_len, BYTE *hash) 82 | { 83 | return tpm_hash(TPM2_ALG_SHA1, data, data_len, hash, TPM2_SHA1_DIGEST_SIZE); 84 | } 85 | 86 | int 87 | hash_digest(TPMI_ALG_HASH hash_alg, BYTE *data, UINT16 data_len, BYTE *hash) 88 | { 89 | UINT16 hash_size; 90 | 91 | if (util_digest_size(hash_alg, &hash_size)) 92 | return -1; 93 | 94 | return tpm_hash(hash_alg, data, data_len, hash, hash_size); 95 | } 96 | -------------------------------------------------------------------------------- /src/lib/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | void __attribute__ ((constructor)) 40 | libcryptfs_tpm2_init(void) 41 | { 42 | tss2_init_sys_context(); 43 | 44 | dbg("libcryptfs-tpm2 initialized\n"); 45 | } 46 | 47 | void __attribute__((destructor)) 48 | libcryptfs_tpm2_fini(void) 49 | { 50 | tss2_teardown_sys_context(); 51 | 52 | dbg("libcryptfs-tpm2 exited\n"); 53 | } 54 | -------------------------------------------------------------------------------- /src/lib/internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #ifndef __INTERNAL_H__ 36 | #define __INTERNAL_H__ 37 | 38 | #include 39 | #ifndef TSS2_LEGACY_V1 40 | #include 41 | #endif 42 | #include "tpm2_rc.h" 43 | 44 | #ifndef TSS2_LEGACY_V1 45 | #define TPM2B_SIZE(type) (sizeof (type) - 2) 46 | #define TPM2B_NAMED_INIT(type, field) \ 47 | { \ 48 | .size = TPM2B_SIZE (type), \ 49 | .field = { 0 } \ 50 | } 51 | #define TPM2B_DIGEST_INIT TPM2B_NAMED_INIT (TPM2B_DIGEST, buffer) 52 | #define TPM2B_NAME_INIT TPM2B_NAMED_INIT (TPM2B_NAME, name) 53 | #define TPM2B_PRIVATE_INIT TPM2B_NAMED_INIT (TPM2B_PRIVATE, buffer) 54 | 55 | #define TPM2B_MAX_BUFFER_INIT { .size = TPM2_MAX_DIGEST_BUFFER } 56 | #define TPM2B_IV_INIT { .size = TPM2_MAX_SYM_BLOCK_SIZE } 57 | 58 | #define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->t.field))) 59 | #define TPM2B_TYPE_INIT(type, field) { .size = BUFFER_SIZE(type, field), } 60 | 61 | struct session_complex { 62 | TPMI_SH_AUTH_SESSION session_handle; 63 | TSS2L_SYS_AUTH_COMMAND sessionsData; 64 | TSS2L_SYS_AUTH_RESPONSE sessionsDataOut; 65 | }; 66 | #else 67 | 68 | struct session_complex { 69 | TPMI_SH_AUTH_SESSION session_handle; 70 | 71 | TPMS_AUTH_COMMAND sessionData; 72 | TPMS_AUTH_COMMAND *sessionDataArray[1]; 73 | TSS2_SYS_CMD_AUTHS sessionsData; 74 | 75 | TPMS_AUTH_RESPONSE sessionDataOut; 76 | TPMS_AUTH_RESPONSE *sessionDataOutArray[1]; 77 | TSS2_SYS_RSP_AUTHS sessionsDataOut; 78 | }; 79 | #endif 80 | extern TSS2_SYS_CONTEXT *cryptfs_tpm2_sys_context; 81 | 82 | TSS2_RC 83 | tss2_init_sys_context(void); 84 | 85 | void 86 | tss2_teardown_sys_context(void); 87 | 88 | int 89 | util_digest_size(TPMI_ALG_HASH hash_alg, UINT16 *alg_size); 90 | 91 | void 92 | password_session_create(struct session_complex *s, char *auth_password, 93 | unsigned int auth_password_size); 94 | 95 | int 96 | policy_session_create(struct session_complex *s, TPM2_SE type, 97 | TPMI_ALG_HASH hash_alg); 98 | 99 | void 100 | policy_session_destroy(struct session_complex *s); 101 | 102 | void 103 | policy_auth_set(TPMS_AUTH_COMMAND *session, TPMI_SH_AUTH_SESSION handle, 104 | char *auth_password, unsigned int auth_password_size); 105 | 106 | int 107 | pcr_policy_extend(TPMI_DH_OBJECT session_handle, TPML_PCR_SELECTION *pcrs, 108 | TPMI_ALG_HASH policy_digest_alg); 109 | 110 | int 111 | password_policy_extend(TPMI_DH_OBJECT session_handle); 112 | 113 | int 114 | capability_read_public(TPMI_DH_OBJECT handle, TPM2B_PUBLIC *public_out); 115 | 116 | int 117 | sha1_digest(BYTE *data, UINT16 data_len, BYTE *hash); 118 | 119 | int 120 | hash_digest(TPMI_ALG_HASH hash_alg, BYTE *data, UINT16 data_len, BYTE *hash); 121 | 122 | const char * 123 | get_primary_key_secret(char *out, unsigned int *out_size); 124 | 125 | const char * 126 | get_passphrase_secret(char *out, unsigned int *out_size); 127 | 128 | int 129 | get_input(const char *prompt, uint8_t *buf, unsigned int *buf_len); 130 | 131 | int 132 | da_check_and_reset(void); 133 | 134 | int 135 | da_reset(void); 136 | 137 | #endif /* __INTERNAL_H__ */ 138 | -------------------------------------------------------------------------------- /src/lib/option.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | int option_quite; 38 | char *option_lockout_auth; 39 | bool option_no_da = false; 40 | 41 | static uint8_t owner_auth[sizeof(TPMU_HA)]; 42 | static unsigned int owner_auth_size; 43 | static uint8_t lockout_auth[sizeof(TPMU_HA)]; 44 | static unsigned int lockout_auth_size; 45 | static uint8_t primary_key_secret[sizeof(TPMU_HA)]; 46 | static unsigned int primary_key_secret_size; 47 | static uint8_t passphrase_secret[sizeof(TPMU_HA)]; 48 | static unsigned int passphrase_secret_size; 49 | static bool interactive = false; 50 | 51 | #define option_set_value(name, buf, buf_size, obj, obj_size) \ 52 | do { \ 53 | if (!buf || !buf_size || !*buf_size) \ 54 | return EXIT_FAILURE; \ 55 | \ 56 | obj_size = sizeof(owner_auth); \ 57 | \ 58 | if (obj_size > *buf_size) \ 59 | obj_size = *buf_size; \ 60 | else { \ 61 | warn("The authorization value for " name " is " \ 62 | "no more than %d characters\n", obj_size); \ 63 | \ 64 | *buf_size = obj_size; \ 65 | } \ 66 | \ 67 | memcpy(obj, buf, obj_size); \ 68 | \ 69 | return EXIT_SUCCESS; \ 70 | } while (0) 71 | 72 | #define option_get_value(name, buf, buf_size, obj, obj_size) \ 73 | do { \ 74 | if (!buf_size) \ 75 | return EXIT_FAILURE; \ 76 | \ 77 | unsigned int __size; \ 78 | \ 79 | if (obj_size > *buf_size) { \ 80 | __size = *buf_size; \ 81 | if (!*buf_size) \ 82 | *buf_size = obj_size; \ 83 | } else { \ 84 | __size = obj_size; \ 85 | *buf_size = __size; \ 86 | } \ 87 | \ 88 | memcpy(buf, obj, __size); \ 89 | \ 90 | return EXIT_SUCCESS; \ 91 | } while (0) 92 | 93 | int 94 | cryptfs_tpm2_option_set_owner_auth(uint8_t *buf, unsigned int *buf_size) 95 | { 96 | option_set_value("owner hierarchy", buf, buf_size, owner_auth, 97 | owner_auth_size); 98 | } 99 | 100 | int 101 | cryptfs_tpm2_option_get_owner_auth(uint8_t *buf, unsigned int *buf_size) 102 | { 103 | option_get_value("owner hierarchy", buf, buf_size, owner_auth, 104 | owner_auth_size); 105 | } 106 | 107 | int 108 | cryptfs_tpm2_option_set_lockout_auth(uint8_t *buf, unsigned int *buf_size) 109 | { 110 | option_set_value("DA lockout", buf, buf_size, lockout_auth, 111 | lockout_auth_size); 112 | } 113 | 114 | int 115 | cryptfs_tpm2_option_get_lockout_auth(uint8_t *buf, unsigned int *buf_size) 116 | { 117 | option_get_value("DA lockout", buf, buf_size, lockout_auth, 118 | lockout_auth_size); 119 | } 120 | 121 | int 122 | cryptfs_tpm2_option_set_primary_key_secret(uint8_t *buf, 123 | unsigned int *buf_size) 124 | { 125 | option_set_value("primary key", buf, buf_size, primary_key_secret, 126 | primary_key_secret_size); 127 | } 128 | 129 | int 130 | cryptfs_tpm2_option_get_primary_key_secret(uint8_t *buf, 131 | unsigned int *buf_size) 132 | { 133 | option_get_value("primary key", buf, buf_size, primary_key_secret, 134 | primary_key_secret_size); 135 | } 136 | 137 | int 138 | cryptfs_tpm2_option_set_passphrase_secret(uint8_t *buf, 139 | unsigned int *buf_size) 140 | { 141 | option_set_value("passphrase", buf, buf_size, passphrase_secret, 142 | passphrase_secret_size); 143 | } 144 | 145 | int 146 | cryptfs_tpm2_option_get_passphrase_secret(uint8_t *buf, 147 | unsigned int *buf_size) 148 | { 149 | option_get_value("passphrase", buf, buf_size, passphrase_secret, 150 | passphrase_secret_size); 151 | } 152 | 153 | void 154 | cryptfs_tpm2_option_set_interactive(void) 155 | { 156 | interactive = true; 157 | } 158 | 159 | int 160 | cryptfs_tpm2_option_get_interactive(bool *required) 161 | { 162 | if (!required) 163 | return EXIT_FAILURE; 164 | 165 | *required = interactive; 166 | 167 | return EXIT_SUCCESS; 168 | } 169 | -------------------------------------------------------------------------------- /src/lib/pcr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | int 40 | cryptfs_tpm2_read_pcr(TPMI_ALG_HASH bank_alg, unsigned int index, 41 | BYTE *out) 42 | { 43 | TPML_PCR_SELECTION pcrs; 44 | 45 | pcrs.count = 1; 46 | pcrs.pcrSelections->hash = bank_alg; 47 | pcrs.pcrSelections->sizeofSelect = 3; 48 | memset(pcrs.pcrSelections->pcrSelect, 0, TPM2_PCR_SELECT_MAX); 49 | pcrs.pcrSelections->pcrSelect[index / 8] |= (1 << (index % 8)); 50 | 51 | /* Obviously I'm lazy of using malloc() here */ 52 | TPML_DIGEST pcr_digest; 53 | 54 | TPML_PCR_SELECTION pcrs_out; 55 | UINT32 pcr_update_counter; 56 | UINT32 rc; 57 | 58 | rc = Tss2_Sys_PCR_Read(cryptfs_tpm2_sys_context, NULL, &pcrs, 59 | &pcr_update_counter, &pcrs_out, &pcr_digest, 60 | NULL); 61 | if (rc != TPM2_RC_SUCCESS) { 62 | err("Unable to read the PCR (%#x)\n", rc); 63 | return -1; 64 | } 65 | 66 | if (pcrs_out.count != 1) 67 | return -1; 68 | 69 | if (pcrs_out.pcrSelections->hash != bank_alg) 70 | return -1; 71 | 72 | if (pcrs_out.pcrSelections->sizeofSelect < align_up(index, 8) / 8) 73 | return -1; 74 | 75 | if (!(pcrs_out.pcrSelections->pcrSelect[index / 8] & (1 << (index % 8)))) 76 | return -1; 77 | 78 | if (pcr_digest.count != 1) 79 | return -1; 80 | 81 | UINT16 alg_size; 82 | 83 | util_digest_size(bank_alg, &alg_size); 84 | 85 | #ifndef TSS2_LEGACY_V1 86 | if (pcr_digest.digests->size != alg_size) 87 | return -1; 88 | 89 | memcpy(out, pcr_digest.digests->buffer, alg_size); 90 | #else 91 | if (pcr_digest.digests->t.size != alg_size) 92 | return -1; 93 | 94 | memcpy(out, pcr_digest.digests->t.buffer, alg_size); 95 | #endif 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /src/lib/policy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | static int 40 | extend_pcr_policy_digest(TPMI_DH_OBJECT session_handle, 41 | TPML_PCR_SELECTION *pcrs, 42 | TPMI_ALG_HASH policy_digest_alg) 43 | { 44 | UINT16 alg_size; 45 | 46 | if (util_digest_size(policy_digest_alg, &alg_size)) 47 | return -1; 48 | 49 | unsigned int nr_pcr = 0; 50 | 51 | /* Calculate the total number of requested PCRs */ 52 | for (UINT32 c = 0; c < pcrs->count; ++c) { 53 | TPMS_PCR_SELECTION *pcr_sel = pcrs->pcrSelections + c; 54 | 55 | for (UINT8 s = 0; s < pcr_sel->sizeofSelect; ++s) { 56 | BYTE *sel = pcr_sel->pcrSelect + s; 57 | 58 | if (!*sel) 59 | continue; 60 | 61 | for (unsigned int i = 0; i < sizeof(BYTE) * 8; ++i) { 62 | if (*sel & (1 << i)) 63 | ++nr_pcr; 64 | } 65 | } 66 | } 67 | 68 | if (!nr_pcr) { 69 | err("No PCR policy applied"); 70 | return -1; 71 | } 72 | 73 | /* Obviously I'm lazy of using malloc() here */ 74 | TPML_DIGEST pcr_digests[(nr_pcr + 7) / 8]; 75 | TPML_PCR_SELECTION pcrs_out; 76 | UINT32 pcr_update_counter; 77 | 78 | pcr_digests->count = nr_pcr; 79 | 80 | UINT32 rc = Tss2_Sys_PCR_Read(cryptfs_tpm2_sys_context, NULL, pcrs, 81 | &pcr_update_counter, &pcrs_out, 82 | pcr_digests, NULL); 83 | if (rc != TPM2_RC_SUCCESS) { 84 | err("Unable to read the PCRs (%#x)\n", rc); 85 | return -1; 86 | } 87 | 88 | unsigned nr_pcr_real = 0; 89 | #ifndef TSS2_LEGACY_V1 90 | TPM2B_DIGEST digest_tpm = { alg_size, }; 91 | #else 92 | TPM2B_DIGEST digest_tpm = { { alg_size, } }; 93 | #endif 94 | for (UINT32 c = 0; c < pcrs_out.count; ++c) { 95 | TPMS_PCR_SELECTION *pcr_sel = pcrs->pcrSelections + c; 96 | TPMS_PCR_SELECTION *pcr_sel_real = pcrs_out.pcrSelections + c; 97 | 98 | for (UINT8 s = 0; s < pcr_sel_real->sizeofSelect; ++s) { 99 | BYTE *sel = pcr_sel->pcrSelect + s; 100 | BYTE *sel_real = pcr_sel_real->pcrSelect + s; 101 | 102 | if (!*sel) 103 | continue; 104 | 105 | for (unsigned int i = 0; i < sizeof(BYTE) * 8; ++i) { 106 | if (!(*sel & (1 << i))) 107 | continue; 108 | 109 | /* Check whether the input pcrs contain unsupported PCRs */ 110 | if (!(*sel_real & (1 << i))) { 111 | err("PCR %x is not supported\n", 112 | s * 8 + i); 113 | return -1; 114 | } 115 | 116 | if (nr_pcr_real) { 117 | BYTE data[sizeof(TPMU_HA) * 2]; 118 | 119 | #ifndef TSS2_LEGACY_V1 120 | memcpy(data, digest_tpm.buffer, 121 | alg_size); 122 | memcpy(data + alg_size, 123 | pcr_digests->digests[nr_pcr_real].buffer, 124 | alg_size); 125 | if (hash_digest(policy_digest_alg, 126 | data, alg_size * 2, 127 | digest_tpm.buffer)) 128 | #else 129 | memcpy(data, digest_tpm.t.buffer, 130 | alg_size); 131 | memcpy(data + alg_size, 132 | pcr_digests->digests[nr_pcr_real].t.buffer, 133 | alg_size); 134 | if (hash_digest(policy_digest_alg, 135 | data, alg_size * 2, 136 | digest_tpm.t.buffer)) 137 | #endif 138 | return -1; 139 | } else { 140 | #ifndef TSS2_LEGACY_V1 141 | if (hash_digest(policy_digest_alg, 142 | pcr_digests->digests[nr_pcr_real].buffer, 143 | pcr_digests->digests[nr_pcr_real].size, 144 | digest_tpm.buffer)) 145 | #else 146 | if (hash_digest(policy_digest_alg, 147 | pcr_digests->digests[nr_pcr_real].t.buffer, 148 | pcr_digests->digests[nr_pcr_real].t.size, 149 | digest_tpm.t.buffer)) 150 | #endif 151 | return -1; 152 | } 153 | 154 | ++nr_pcr_real; 155 | } 156 | } 157 | } 158 | 159 | if (nr_pcr_real != nr_pcr) { 160 | err("The supported PCRs (%d) are less than the " 161 | "specified (%d)\n", nr_pcr_real, nr_pcr); 162 | return -1; 163 | } 164 | 165 | rc = Tss2_Sys_PolicyPCR(cryptfs_tpm2_sys_context, session_handle, 166 | NULL, &digest_tpm, &pcrs_out, NULL); 167 | if (rc != TPM2_RC_SUCCESS) { 168 | err("Unable to set the policy for PCRs (%#x)\n", rc); 169 | return -1; 170 | } 171 | 172 | return 0; 173 | } 174 | 175 | int 176 | pcr_policy_extend(TPMI_DH_OBJECT session_handle, TPML_PCR_SELECTION *pcrs, 177 | TPMI_ALG_HASH policy_digest_alg) 178 | { 179 | return extend_pcr_policy_digest(session_handle, pcrs, 180 | policy_digest_alg); 181 | } 182 | 183 | int 184 | password_policy_extend(TPMI_DH_OBJECT session_handle) 185 | { 186 | UINT32 rc = Tss2_Sys_PolicyPassword(cryptfs_tpm2_sys_context, 187 | session_handle, NULL, NULL); 188 | if (rc != TPM2_RC_SUCCESS) { 189 | err("Unable to set the policy for password (%#x)\n", rc); 190 | return -1; 191 | } 192 | 193 | return 0; 194 | } 195 | -------------------------------------------------------------------------------- /src/lib/random.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | int 40 | cryptefs_tpm2_get_random(uint8_t *random, size_t *req_size) 41 | { 42 | #ifndef TSS2_LEGACY_V1 43 | TPM2B_DIGEST random_bytes = { sizeof(TPM2B_DIGEST) - 2, }; 44 | #else 45 | TPM2B_DIGEST random_bytes = { { sizeof(TPM2B_DIGEST) - 2, } }; 46 | #endif 47 | TPM2_RC rc; 48 | 49 | rc = Tss2_Sys_GetRandom(cryptfs_tpm2_sys_context, NULL, *req_size, 50 | &random_bytes, NULL); 51 | if (rc != TSS2_RC_SUCCESS) { 52 | err("Unable to get the random number (%#x)\n", rc); 53 | return -1; 54 | } 55 | 56 | #ifndef TSS2_LEGACY_V1 57 | if (random_bytes.size < *req_size) { 58 | *req_size = random_bytes.size; 59 | warn("Random number truncated to %d-byte\n", 60 | random_bytes.size); 61 | } 62 | 63 | cryptfs_tpm2_util_hex_dump("RNG random", random_bytes.buffer, 64 | random_bytes.size); 65 | 66 | memcpy(random, random_bytes.buffer, *req_size); 67 | #else 68 | if (random_bytes.t.size < *req_size) { 69 | *req_size = random_bytes.t.size; 70 | warn("Random number truncated to %d-byte\n", 71 | random_bytes.t.size); 72 | } 73 | 74 | cryptfs_tpm2_util_hex_dump("RNG random", random_bytes.t.buffer, 75 | random_bytes.t.size); 76 | 77 | memcpy(random, random_bytes.t.buffer, *req_size); 78 | #endif 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /src/lib/secret.c.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | /* 38 | * Note: this value must be same with scripts/ecrypt_secret.py 39 | */ 40 | #define XOR_CODE @@CRYPTFS_TPM2_SECRET_XOR_BYTE_CODE@@ 41 | 42 | extern const uint8_t secret_area[]; 43 | extern const unsigned int secret_area_size[]; 44 | 45 | static void 46 | decrypt_secret(char *out, const uint8_t *in, unsigned int in_size) 47 | { 48 | uint8_t xor = XOR_CODE; 49 | 50 | for (unsigned int i = 0; i < in_size; ++i) { 51 | out[i] = in[i] ^ xor; 52 | xor = in[i]; 53 | } 54 | } 55 | 56 | void 57 | get_primary_key_secret(char *out, unsigned int *out_size) 58 | { 59 | if (!out || !out_size) 60 | return; 61 | 62 | unsigned int secret_size = *out_size; 63 | 64 | if (cryptfs_tpm2_option_get_primary_key_secret((uint8_t *)out, 65 | &secret_size) == 66 | EXIT_SUCCESS && secret_size) { 67 | #ifdef DEBUG 68 | cryptfs_tpm2_util_hex_dump("primary key secret", 69 | (uint8_t *)out, secret_size); 70 | #endif 71 | *out_size = secret_size; 72 | 73 | return; 74 | } 75 | 76 | if (secret_area_size[0] < *out_size) 77 | *out_size = secret_area_size[0]; 78 | 79 | const uint8_t *in = secret_area; 80 | 81 | #ifdef DEBUG 82 | cryptfs_tpm2_util_hex_dump("encrypted primary key secret", 83 | in, *out_size); 84 | #endif 85 | 86 | decrypt_secret(out, in, *out_size); 87 | 88 | #ifdef DEBUG 89 | cryptfs_tpm2_util_hex_dump("decrypted primary key secret", 90 | (uint8_t *)out, *out_size); 91 | #endif 92 | } 93 | 94 | void 95 | get_passphrase_secret(char *out, unsigned int *out_size) 96 | { 97 | if (!out || !out_size) 98 | return; 99 | 100 | unsigned int secret_size = *out_size; 101 | 102 | if (cryptfs_tpm2_option_get_passphrase_secret((uint8_t *)out, 103 | &secret_size) == 104 | EXIT_SUCCESS && secret_size) { 105 | #ifdef DEBUG 106 | cryptfs_tpm2_util_hex_dump("passphrase secret", 107 | (uint8_t *)out, secret_size); 108 | #endif 109 | *out_size = secret_size; 110 | 111 | return; 112 | } 113 | 114 | if (secret_area_size[1] < *out_size) 115 | *out_size = secret_area_size[1]; 116 | 117 | const uint8_t *in = secret_area + secret_area_size[0]; 118 | 119 | #ifdef DEBUG 120 | cryptfs_tpm2_util_hex_dump("encrypted passphrase secret", 121 | in, *out_size); 122 | #endif 123 | 124 | decrypt_secret(out, in, *out_size); 125 | 126 | #ifdef DEBUG 127 | cryptfs_tpm2_util_hex_dump("decrypted passphrase secret", 128 | (uint8_t *)out, *out_size); 129 | #endif 130 | } 131 | -------------------------------------------------------------------------------- /src/lib/secret_area.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | .data 36 | 37 | .globl secret_area 38 | secret_area: 39 | __primary_key_secret_start: 40 | .incbin "primary_key.secret" 41 | __primary_key_secret_end: 42 | 43 | __passphrase_secret_start: 44 | .incbin "passphrase.secret" 45 | __passphrase_secret_end: 46 | 47 | .globl secret_area_size 48 | secret_area_size: 49 | .int __primary_key_secret_end - __primary_key_secret_start 50 | .int __passphrase_secret_end - __passphrase_secret_start 51 | -------------------------------------------------------------------------------- /src/lib/session.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | static void 40 | complete_session_complex(struct session_complex *s) 41 | { 42 | #ifndef TSS2_LEGACY_V1 43 | s->sessionsData.count = 1; 44 | s->sessionsDataOut.count = 1; 45 | #else 46 | s->sessionDataArray[0] = &s->sessionData; 47 | s->sessionsData.cmdAuthsCount = 1; 48 | s->sessionsData.cmdAuths = s->sessionDataArray; 49 | 50 | s->sessionDataOutArray[0] = &s->sessionDataOut; 51 | s->sessionsDataOut.rspAuthsCount = 1; 52 | s->sessionsDataOut.rspAuths = s->sessionDataOutArray; 53 | #endif 54 | } 55 | 56 | static void 57 | set_session_auth(TPMS_AUTH_COMMAND *session, TPMI_SH_AUTH_SESSION handle, 58 | void *auth_password, size_t auth_password_size) 59 | { 60 | #ifndef TSS2_LEGACY_V1 61 | session->sessionHandle = handle; 62 | session->nonce.size = 0; 63 | *((UINT8 *)((void *)&session->sessionAttributes)) = 0; 64 | session->sessionAttributes |= TPMA_SESSION_CONTINUESESSION; 65 | 66 | if (auth_password && auth_password_size) { 67 | session->hmac.size = auth_password_size; 68 | memcpy(session->hmac.buffer, auth_password, 69 | session->hmac.size); 70 | } else 71 | session->hmac.size = 0; 72 | #else 73 | session->sessionHandle = handle; 74 | session->nonce.t.size = 0; 75 | *((UINT8 *)((void *)&session->sessionAttributes)) = 0; 76 | session->sessionAttributes.continueSession = 1; 77 | 78 | if (auth_password && auth_password_size) { 79 | session->hmac.t.size = auth_password_size; 80 | memcpy(session->hmac.t.buffer, auth_password, 81 | session->hmac.t.size); 82 | } else 83 | session->hmac.t.size = 0; 84 | #endif 85 | } 86 | 87 | static void 88 | set_password_auth(TPMS_AUTH_COMMAND *session, char *auth_password, 89 | unsigned int auth_password_size) 90 | { 91 | set_session_auth(session, TPM2_RS_PW, auth_password, 92 | auth_password && auth_password_size ? 93 | auth_password_size : 0); 94 | } 95 | 96 | /* TODO: move this call to policy_session_create() */ 97 | void 98 | policy_auth_set(TPMS_AUTH_COMMAND *session, TPMI_SH_AUTH_SESSION handle, 99 | char *auth_password, unsigned int auth_password_size) 100 | { 101 | set_session_auth(session, handle, auth_password, 102 | auth_password && auth_password_size ? 103 | auth_password_size : 0); 104 | } 105 | 106 | /* 107 | * Create an unsalted and unbound policy session for generating 108 | * the policy digest calculated by TPM. 109 | */ 110 | int 111 | policy_session_create(struct session_complex *s, TPM2_SE type, 112 | TPMI_ALG_HASH hash_alg) 113 | { 114 | UINT16 hash_alg_size; 115 | 116 | if (util_digest_size(hash_alg, &hash_alg_size)) 117 | return -1; 118 | 119 | if (type != TPM2_SE_POLICY && type != TPM2_SE_TRIAL) { 120 | err("Invalid policy session type %#x specified\n", type); 121 | return -1; 122 | } 123 | 124 | TPM2B_ENCRYPTED_SECRET salt; 125 | #ifndef TSS2_LEGACY_V1 126 | salt.size = 0; 127 | #else 128 | salt.t.size = 0; 129 | #endif 130 | 131 | /* No symmetric algorithm */ 132 | TPMT_SYM_DEF symmetric; 133 | symmetric.algorithm = TPM2_ALG_NULL; 134 | 135 | TPM2B_NONCE nonce_caller; 136 | #ifndef TSS2_LEGACY_V1 137 | nonce_caller.size = hash_alg_size; 138 | memset(nonce_caller.buffer, 0, nonce_caller.size); 139 | #else 140 | nonce_caller.t.size = hash_alg_size; 141 | memset(nonce_caller.t.buffer, 0, nonce_caller.t.size); 142 | #endif 143 | TPM2B_NONCE nonce_tpm; 144 | #ifndef TSS2_LEGACY_V1 145 | nonce_tpm.size = nonce_caller.size; 146 | #else 147 | nonce_tpm.t.size = nonce_caller.t.size; 148 | #endif 149 | UINT32 rc = Tss2_Sys_StartAuthSession(cryptfs_tpm2_sys_context, 150 | TPM2_RH_NULL, TPM2_RH_NULL, NULL, 151 | &nonce_caller, &salt, 152 | type, &symmetric, 153 | hash_alg, &s->session_handle, 154 | &nonce_tpm, NULL); 155 | if (rc != TPM2_RC_SUCCESS) { 156 | err("Unable to create a %spolicy session " 157 | "(%#x)\n", type == TPM2_SE_TRIAL ? "trial " : "", 158 | rc); 159 | return -1; 160 | } 161 | 162 | complete_session_complex(s); 163 | 164 | dbg("The %spolicy session handle %#8.8x created\n", 165 | type == TPM2_SE_TRIAL ? "trial " : "", 166 | s->session_handle); 167 | 168 | return 0; 169 | } 170 | 171 | void 172 | policy_session_destroy(struct session_complex *s) 173 | { 174 | if (s->session_handle == TPM2_RS_PW) 175 | return; 176 | 177 | UINT32 rc = Tss2_Sys_FlushContext(cryptfs_tpm2_sys_context, 178 | s->session_handle); 179 | if (rc == TPM2_RC_SUCCESS) 180 | dbg("The policy session %#8.8x destroyed\n", s->session_handle); 181 | else 182 | err("Unable to destroy the policy session handle " 183 | "(%#x)\n", rc); 184 | } 185 | 186 | void 187 | password_session_create(struct session_complex *s, char *auth_password, 188 | unsigned int auth_password_size) 189 | { 190 | #ifndef TSS2_LEGACY_V1 191 | set_password_auth(&s->sessionsData.auths[0], auth_password, auth_password_size); 192 | #else 193 | set_password_auth(&s->sessionData, auth_password, auth_password_size); 194 | #endif 195 | s->session_handle = TPM2_RS_PW; 196 | 197 | complete_session_complex(s); 198 | } 199 | -------------------------------------------------------------------------------- /src/lib/subcommand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #define MAX_SUBCOMMANDS 16 38 | 39 | static subcommand_t *curr_subcommand; 40 | static unsigned int nr_subcommand; 41 | static subcommand_t *subcommands[MAX_SUBCOMMANDS]; 42 | static char *prog_name; 43 | 44 | int 45 | subcommand_add(subcommand_t *subcmd) 46 | { 47 | if (!subcmd->name || !subcmd->optstring || !subcmd->long_opts 48 | || !subcmd->parse_arg) 49 | return -1; 50 | 51 | if (nr_subcommand >= MAX_SUBCOMMANDS) 52 | return -1; 53 | 54 | subcommands[nr_subcommand++] = subcmd; 55 | 56 | return 0; 57 | } 58 | 59 | subcommand_t * 60 | subcommand_find(char *subcmd) 61 | { 62 | unsigned int i; 63 | 64 | for (i = 0; i < nr_subcommand; ++i) { 65 | if (!strcmp(subcmd, subcommands[i]->name)) 66 | break; 67 | } 68 | if (i == nr_subcommand) 69 | return NULL; 70 | 71 | return subcommands[i]; 72 | } 73 | 74 | int 75 | subcommand_parse(char *prog, char *subcmd, int argc, char *argv[]) 76 | { 77 | subcommand_t *cmd; 78 | 79 | dbg("Input subcommand: %s\n", subcmd); 80 | 81 | cmd = subcommand_find(subcmd); 82 | if (!cmd) { 83 | err("Unrecognized subcommand: %s\n", subcmd); 84 | return -1; 85 | } 86 | 87 | optind = 1; 88 | opterr = 0; 89 | 90 | while (1) { 91 | int opt; 92 | 93 | opt = getopt_long(argc, argv, cmd->optstring, 94 | cmd->long_opts, NULL); 95 | if (opt == -1) 96 | break; 97 | 98 | dbg("opt 0x%x, optind %d, argc %d, argv[i] %s, optarg %s\n", 99 | opt, optind, argc, argv[optind - 1], optarg); 100 | 101 | switch (opt) { 102 | default: 103 | if (cmd->parse_arg(opt, optarg)) 104 | return -1; 105 | break; 106 | case '?': 107 | case ':': 108 | cmd->show_usage(prog); 109 | return -1; 110 | } 111 | } 112 | 113 | curr_subcommand = cmd; 114 | prog_name = prog; 115 | 116 | return 0; 117 | } 118 | 119 | int 120 | subcommand_run_current(void) 121 | { 122 | if (!curr_subcommand) 123 | return -1; 124 | 125 | return curr_subcommand->run(prog_name); 126 | } 127 | -------------------------------------------------------------------------------- /src/lib/tcti.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static void *tcti_handle; 38 | 39 | TSS2_TCTI_CONTEXT * 40 | init_tcti_tabrmd(void) 41 | { 42 | TSS2_TCTI_CONTEXT *ctx; 43 | size_t size; 44 | TSS2_RC rc; 45 | #ifndef TSS2_LEGACY_V1 46 | TSS2_RC (*init)(TSS2_TCTI_CONTEXT *, size_t *, const char *); 47 | 48 | tcti_handle = dlopen("libtss2-tcti-tabrmd.so.0", RTLD_LAZY); 49 | #else 50 | TSS2_RC (*init)(TSS2_TCTI_CONTEXT *, size_t *); 51 | 52 | tcti_handle = dlopen("libtcti-tabrmd.so.0", RTLD_LAZY); 53 | #endif 54 | 55 | if (!tcti_handle) { 56 | err("Unable to find out the tabrmd tcti library\n"); 57 | return NULL; 58 | } 59 | 60 | #ifndef TSS2_LEGACY_V1 61 | init = dlsym(tcti_handle, "Tss2_Tcti_Tabrmd_Init"); 62 | #else 63 | init = dlsym(tcti_handle, "tss2_tcti_tabrmd_init"); 64 | #endif 65 | if (!init) { 66 | dlclose(tcti_handle); 67 | return NULL; 68 | } 69 | 70 | #ifndef TSS2_LEGACY_V1 71 | rc = init(NULL, &size, NULL); 72 | #else 73 | rc = init(NULL, &size); 74 | #endif 75 | if (rc != TSS2_RC_SUCCESS) { 76 | dlclose(tcti_handle); 77 | err("Unable to get the size of tabrmd tcti context\n"); 78 | return NULL; 79 | } 80 | 81 | ctx = (TSS2_TCTI_CONTEXT *)malloc(size); 82 | if (ctx) { 83 | memset(ctx, 0, size); 84 | 85 | #ifndef TSS2_LEGACY_V1 86 | rc = init(ctx, &size, NULL); 87 | #else 88 | rc = init(ctx, &size); 89 | #endif 90 | if (rc != TSS2_RC_SUCCESS) { 91 | err("Unable to initialize tabrmd tcti context\n"); 92 | free(ctx); 93 | ctx = NULL; 94 | dlclose(tcti_handle); 95 | } 96 | } 97 | 98 | return ctx; 99 | } 100 | 101 | TSS2_TCTI_CONTEXT * 102 | init_tcti_device(void) 103 | { 104 | #ifndef TSS2_LEGACY_V1 105 | const char *cfgs[] = { "/dev/tpmrm0", "/dev/tpm0" }; 106 | #else 107 | TCTI_DEVICE_CONF cfgs[] = { 108 | { 109 | .device_path = "/dev/tpm0", 110 | .logCallback = NULL, 111 | .logData = NULL, 112 | } 113 | }; 114 | #endif 115 | size_t size; 116 | TSS2_TCTI_CONTEXT *ctx; 117 | TSS2_RC rc; 118 | 119 | #ifndef TSS2_LEGACY_V1 120 | rc = Tss2_Tcti_Device_Init(NULL, &size, NULL); 121 | #else 122 | rc = InitDeviceTcti(NULL, &size, NULL); 123 | #endif 124 | if (rc != TSS2_RC_SUCCESS) { 125 | err("Unable to get the size of device tcti context\n"); 126 | return NULL; 127 | } 128 | 129 | ctx = (TSS2_TCTI_CONTEXT *)malloc(size); 130 | if (!ctx) 131 | return ctx; 132 | 133 | memset(ctx, 0, size); 134 | 135 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 136 | 137 | for (unsigned int i = 0; i < ARRAY_SIZE(cfgs); ++i) { 138 | #ifndef TSS2_LEGACY_V1 139 | rc = Tss2_Tcti_Device_Init(ctx, &size, cfgs[i]); 140 | #else 141 | rc = InitDeviceTcti(ctx, &size, &cfgs[i]); 142 | #endif 143 | if (rc == TSS2_RC_SUCCESS) 144 | break; 145 | } 146 | 147 | #undef ARRAY_SIZE 148 | 149 | if (rc != TSS2_RC_SUCCESS) { 150 | err("Unable to initialize device tcti context\n"); 151 | free(ctx); 152 | ctx = NULL; 153 | } 154 | 155 | return ctx; 156 | } 157 | 158 | TSS2_TCTI_CONTEXT * 159 | init_tcti_socket(void) 160 | { 161 | #ifndef TSS2_LEGACY_V1 162 | const char *cfg = "host=127.0.0.1,port=2321"; 163 | #else 164 | TCTI_SOCKET_CONF cfg = { 165 | .hostname = DEFAULT_HOSTNAME, 166 | .port = 2321, 167 | .logCallback = NULL, 168 | .logBufferCallback = NULL, 169 | .logData = NULL, 170 | }; 171 | #endif 172 | size_t size; 173 | TSS2_TCTI_CONTEXT *ctx; 174 | TSS2_RC rc; 175 | 176 | #ifndef TSS2_LEGACY_V1 177 | rc = Tss2_Tcti_Mssim_Init(NULL, &size, cfg); 178 | #else 179 | rc = InitSocketTcti(NULL, &size, &cfg, 0); 180 | #endif 181 | if (rc != TSS2_RC_SUCCESS) { 182 | err("Unable to get the size of socket tcti context\n"); 183 | return NULL; 184 | } 185 | 186 | ctx = (TSS2_TCTI_CONTEXT *)malloc(size); 187 | if (ctx) { 188 | memset(ctx, 0, size); 189 | 190 | #ifndef TSS2_LEGACY_V1 191 | rc = Tss2_Tcti_Mssim_Init(ctx, &size, cfg); 192 | #else 193 | rc = InitSocketTcti(ctx, &size, &cfg, 0); 194 | #endif 195 | if (rc != TSS2_RC_SUCCESS) { 196 | err("Unable to initialize socket tcti context\n"); 197 | free(ctx); 198 | ctx = NULL; 199 | } 200 | } 201 | 202 | return ctx; 203 | } 204 | 205 | TSS2_TCTI_CONTEXT * 206 | cryptfs_tpm2_tcti_init_context(void) 207 | { 208 | char *tcti_str; 209 | 210 | tcti_str = getenv("TSS2_TCTI"); 211 | if (!tcti_str) { 212 | #ifndef TSS2_LEGACY_V1 213 | tcti_str = "device"; 214 | #else 215 | tcti_str = "tabrmd"; 216 | #endif 217 | 218 | info("Use %s as the default tcti interface\n", tcti_str); 219 | } 220 | 221 | if (!strcmp(tcti_str, "tabrmd")) 222 | return init_tcti_tabrmd(); 223 | else if (!strcmp(tcti_str, "device")) 224 | return init_tcti_device(); 225 | else if (!strcmp(tcti_str, "socket")) 226 | return init_tcti_socket(); 227 | else 228 | err("Invalid tcti interface specified (%s)\n", tcti_str); 229 | 230 | return NULL; 231 | } 232 | 233 | void 234 | cryptfs_tpm2_tcti_teardown_context(TSS2_TCTI_CONTEXT *ctx) 235 | { 236 | #ifndef TSS2_LEGACY_V1 237 | Tss2_Tcti_Finalize(ctx); 238 | #else 239 | tss2_tcti_finalize(ctx); 240 | #endif 241 | free(ctx); 242 | 243 | if (tcti_handle) 244 | dlclose(tcti_handle); 245 | } 246 | -------------------------------------------------------------------------------- /src/lib/tpm2_rc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #ifndef __TPM2_RC_H__ 36 | #define __TPM2_RC_H__ 37 | 38 | #include 39 | 40 | /* To understand the TPM2_RC you need to read a 2 different parts of the 41 | * spec: 42 | * Section 39.4 of TPM 2.0 Part 1: Architecture 43 | * Section 6.6 of TPM 2.0 Part 2: Structures 44 | * 45 | * The notion of RC levels only exists for the TSS. See the TSS system API 46 | * specification section 6.1.2 for details. 47 | */ 48 | 49 | /* Macros to determine whether or not a specific bit in position 'pos' from 50 | * variable 'var' is set. 51 | */ 52 | #define IS_BIT_SET(var, pos) ((1 << (pos)) & (var)) 53 | #define IS_BIT_CLEAR(var, pos) !IS_BIT_SET(var, pos) 54 | 55 | /* useful masks not defined in the spec */ 56 | /* bits [06:00] */ 57 | #define TPM2_RC_7BIT_ERROR_MASK 0x7f 58 | /* bits [05:00] */ 59 | #define TPM2_RC_6BIT_ERROR_MASK 0x3f 60 | /* bits [11:08] */ 61 | #define TPM2_RC_PARAMETER_MASK 0xf00 62 | /* bits [10:08] */ 63 | #define TPM2_RC_HANDLE_MASK 0x700 64 | #define TPM2_RC_SESSION_MASK 0x700 65 | 66 | /* "Format Zero" response codes have bit 7 clear. 67 | * Format zero RCs could be in a number of formats: 68 | * - A TPM 1.2 RC 69 | * - A vendor defined error code 70 | * - A 6 bit warning code 71 | * - A 6 bit error code 72 | */ 73 | static inline bool 74 | tpm2_rc_is_format_zero (TPM2_RC response_code) 75 | { 76 | if (IS_BIT_CLEAR (response_code, 7)) 77 | return true; 78 | else 79 | return false; 80 | } 81 | /* "Format One" response codes have bit 7 set. 82 | * These RCs have two components: 83 | * - A 5 bit error code in bits [05:00] 84 | * - A 4 bit parameter identifier in [11:08] or a 3 bit handle / session 85 | * identifier in bits [10:08] 86 | */ 87 | static inline int 88 | tpm2_rc_is_format_one (TPM2_RC response_code) 89 | { 90 | if (IS_BIT_SET (response_code, 7)) 91 | return true; 92 | else 93 | return false; 94 | } 95 | /* Determine whether or not a response code (TPM2_RC) is in the 1.2 format or 96 | * the 2.0 format. 97 | */ 98 | static inline bool 99 | tpm2_rc_is_tpm2 (TPM2_RC response_code) 100 | { 101 | /* if bit 7 & 8 are both 0, TPM2_RC is 1.2 format */ 102 | if (IS_BIT_CLEAR (response_code, 7) && IS_BIT_CLEAR (response_code, 8)) 103 | return false; 104 | else 105 | return true; 106 | } 107 | static inline bool 108 | tpm2_rc_is_tpm12 (TPM2_RC response_code) 109 | { 110 | if (!tpm2_rc_is_tpm2 (response_code)) 111 | return true; 112 | else 113 | return false; 114 | } 115 | /* Determine whether or not a response code (TPM2_RC) is a vendor defined code. 116 | * Vendor defined TPM2 response codes have bit 8 and 10 set, and bit 7 clear. 117 | */ 118 | static inline bool 119 | tpm2_rc_is_vendor_defined (TPM2_RC response_code) 120 | { 121 | if (IS_BIT_CLEAR (response_code, 7) && 122 | IS_BIT_SET (response_code, 8) && 123 | IS_BIT_SET (response_code, 10)) 124 | { 125 | return true; 126 | } else { 127 | return false; 128 | } 129 | } 130 | /* Determine whether or not bits [06:00] contain a warning code. 131 | * Warning codes have bit 8 and 11 set, and bits 7 and 10 clear. 132 | */ 133 | static inline bool 134 | tpm2_rc_is_warning_code (TPM2_RC response_code) 135 | { 136 | if (IS_BIT_CLEAR (response_code, 7) && 137 | IS_BIT_SET (response_code, 8) && 138 | IS_BIT_CLEAR (response_code, 10) && 139 | IS_BIT_SET (response_code, 11)) 140 | { 141 | return true; 142 | } else { 143 | return false; 144 | } 145 | } 146 | /* Determine whether or not bits [06:00] contain an error code. 147 | * Error codes have bit 8 set, and bits 7, 10 and 11 clear. 148 | */ 149 | static inline bool 150 | tpm2_rc_is_error_code (TPM2_RC response_code) 151 | { 152 | if (IS_BIT_CLEAR (response_code, 7) && 153 | IS_BIT_SET (response_code, 8) && 154 | IS_BIT_CLEAR (response_code, 10) && 155 | IS_BIT_CLEAR (response_code, 11)) 156 | { 157 | return 1; 158 | } else { 159 | return 0; 160 | } 161 | } 162 | /* Determine whether or not bits [05:00] contain and error code with a 163 | * parameter number in bits [11:08]. 164 | * Bit 6 and 7 are set. 165 | */ 166 | static inline bool 167 | tpm2_rc_is_error_code_with_parameter (TPM2_RC response_code) 168 | { 169 | if (IS_BIT_SET (response_code, 6) && IS_BIT_SET (response_code, 7)) 170 | return true; 171 | else 172 | return false; 173 | } 174 | /* Determine whether or not bits [05:00] contain an error code with a 175 | * handle number in bits [10:08] 176 | * Bit 7 set, bits 6 and 11 clear. 177 | */ 178 | static inline bool 179 | tpm2_rc_is_error_code_with_handle (TPM2_RC response_code) 180 | { 181 | if (IS_BIT_CLEAR (response_code, 6) && 182 | IS_BIT_SET (response_code, 7) && 183 | IS_BIT_CLEAR (response_code, 11)) 184 | { 185 | return true; 186 | } else { 187 | return false; 188 | } 189 | } 190 | /* Determine whether or not bits [05:00] contain an error code with a 191 | * session number in bits [10:08] 192 | * Bit 6 clear, bits 7 and 11 set. 193 | */ 194 | static inline bool 195 | tpm2_rc_is_error_code_with_session (TPM2_RC response_code) 196 | { 197 | if (IS_BIT_CLEAR (response_code, 6) && 198 | IS_BIT_SET (response_code, 7) && 199 | IS_BIT_SET (response_code, 11)) 200 | { 201 | return true; 202 | } else { 203 | return false; 204 | } 205 | } 206 | /* Isolate bits [06:00] of the TPM2_RC. 207 | * The 7bit warning or error code is only valid if the RC is a "format zero" 208 | * RC. 209 | */ 210 | static inline UINT32 211 | tpm2_rc_get_code_7bit (TPM2_RC response_code) 212 | { 213 | return TPM2_RC_7BIT_ERROR_MASK & response_code; 214 | } 215 | /* Isolate bits [05:00] of the TPM2_RC. 216 | * The 6bit error code is only valid if the RC is a "format one" RC. 217 | */ 218 | static inline UINT32 219 | tpm2_rc_get_code_6bit (TPM2_RC response_code) 220 | { 221 | return TPM2_RC_6BIT_ERROR_MASK & response_code; 222 | } 223 | /* Isolate bits [11:08] of the TPM2_RC. 224 | * The 4 it parameter code is only valid if the RC is a "format one" RC 225 | * with bit 6 set. Test for this with the 226 | * tpm2_rc_is_error_code_with_parameters function. 227 | */ 228 | static inline UINT32 229 | tpm2_rc_get_parameter_number (TPM2_RC response_code) 230 | { 231 | return TPM2_RC_PARAMETER_MASK & response_code; 232 | } 233 | /* Isolate bits [10:08] of the TPM2_RC. 234 | * The 3 bit handle / session code is only valid if the RC is a "format one" 235 | * RC with bits 6 clear. 236 | */ 237 | static inline UINT32 238 | tpm2_rc_get_handle_number (TPM2_RC response_code) 239 | { 240 | return TPM2_RC_HANDLE_MASK & response_code; 241 | } 242 | static inline UINT32 243 | tpm2_rc_get_session_number (TPM2_RC response_code) 244 | { 245 | return TPM2_RC_SESSION_MASK & response_code; 246 | } 247 | /* Isolate the error level component of the TPM2_RC in bits [23:16] */ 248 | static inline UINT32 249 | tpm2_rc_get_layer (TPM2_RC response_code) 250 | { 251 | return TSS2_RC_LAYER_MASK & response_code; 252 | } 253 | /* This function returns true if the error code indicates that it came from a 254 | * TSS component. False otherwise (which indicates it came from the TPM). 255 | */ 256 | static inline bool 257 | tpm2_rc_is_from_tss (TPM2_RC response_code) 258 | { 259 | if (tpm2_rc_get_layer (response_code)) 260 | return true; 261 | else 262 | return false; 263 | } 264 | /* Isolate the error code from a TSS layer. It's not entirely clear to me 265 | * from the spec what the right mask is here. Bits [23:16] are for the layer 266 | * indicator but it says nothing else about which bits mean what. It makes 267 | * sense to assume that the lower 2 bytes hold the error code but the top 268 | * byte (AFAIK) is unaccounted for. 269 | * So I'm masking [31:24] as well as the ayer indicator. 270 | */ 271 | static inline UINT32 272 | tpm2_rc_get_tss_err_code (TPM2_RC response_code) 273 | { 274 | return 0X0000ffff & response_code; 275 | } 276 | 277 | #endif /* __TPM2_RC_H__ */ 278 | -------------------------------------------------------------------------------- /src/lib/tss2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | #define TSSWG_INTEROP 1 40 | #define TSS_SAPI_FIRST_FAMILY 2 41 | #define TSS_SAPI_FIRST_LEVEL 1 42 | #define TSS_SAPI_FIRST_VERSION 108 43 | 44 | TSS2_SYS_CONTEXT *cryptfs_tpm2_sys_context; 45 | 46 | static TSS2_TCTI_CONTEXT *tcti_context; 47 | 48 | TSS2_RC 49 | tss2_init_sys_context(void) 50 | { 51 | TSS2_ABI_VERSION tss2_abi_version = { 52 | TSSWG_INTEROP, 53 | TSS_SAPI_FIRST_FAMILY, 54 | TSS_SAPI_FIRST_LEVEL, 55 | TSS_SAPI_FIRST_VERSION 56 | }; 57 | TSS2_SYS_CONTEXT *sys_context; 58 | UINT32 size; 59 | TSS2_RC rc; 60 | 61 | tcti_context = cryptfs_tpm2_tcti_init_context(); 62 | if (!tcti_context) 63 | return TSS2_TCTI_RC_BAD_CONTEXT; 64 | 65 | /* Get the size needed for system context structure */ 66 | size = Tss2_Sys_GetContextSize(0); 67 | 68 | /* Allocate the space for the system context structure */ 69 | sys_context = malloc(size); 70 | if (!sys_context) { 71 | err("Unable to allocate system context\n"); 72 | cryptfs_tpm2_tcti_teardown_context(tcti_context); 73 | return TSS2_TCTI_RC_BAD_CONTEXT; 74 | } 75 | 76 | rc = Tss2_Sys_Initialize(sys_context, size, tcti_context, 77 | &tss2_abi_version); 78 | if (rc != TSS2_RC_SUCCESS) { 79 | err("Unable to initialize system context\n"); 80 | free(sys_context); 81 | cryptfs_tpm2_tcti_teardown_context(tcti_context); 82 | return rc; 83 | } 84 | 85 | cryptfs_tpm2_sys_context = sys_context; 86 | 87 | return TSS2_RC_SUCCESS; 88 | } 89 | 90 | void 91 | tss2_teardown_sys_context(void) 92 | { 93 | Tss2_Sys_Finalize(cryptfs_tpm2_sys_context); 94 | free(cryptfs_tpm2_sys_context); 95 | cryptfs_tpm2_sys_context = NULL; 96 | 97 | cryptfs_tpm2_tcti_teardown_context(tcti_context); 98 | tcti_context = NULL; 99 | } 100 | -------------------------------------------------------------------------------- /src/lib/unseal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #include "internal.h" 38 | 39 | int 40 | cryptfs_tpm2_unseal_passphrase(TPMI_ALG_HASH pcr_bank_alg, void **passphrase, 41 | size_t *passphrase_size) 42 | { 43 | struct session_complex s; 44 | char secret[256]; 45 | unsigned int secret_size; 46 | 47 | secret_size = sizeof(secret); 48 | get_passphrase_secret(secret, &secret_size); 49 | 50 | redo: 51 | if (pcr_bank_alg != TPM2_ALG_NULL) { 52 | TPMI_ALG_HASH policy_digest_alg = pcr_bank_alg; 53 | 54 | if (policy_session_create(&s, TPM2_SE_POLICY, policy_digest_alg)) 55 | return -1; 56 | 57 | TPML_PCR_SELECTION pcrs; 58 | unsigned int pcr_index = CRYPTFS_TPM2_PCR_INDEX; 59 | 60 | pcrs.count = 1; 61 | pcrs.pcrSelections->hash = pcr_bank_alg; 62 | pcrs.pcrSelections->sizeofSelect = 3; 63 | memset(pcrs.pcrSelections->pcrSelect, 0, TPM2_PCR_SELECT_MAX); 64 | pcrs.pcrSelections->pcrSelect[pcr_index / 8] |= 65 | (1 << (pcr_index % 8)); 66 | 67 | if (pcr_policy_extend(s.session_handle, &pcrs, 68 | policy_digest_alg)) { 69 | policy_session_destroy(&s); 70 | return -1; 71 | } 72 | 73 | if (password_policy_extend(s.session_handle)) { 74 | policy_session_destroy(&s); 75 | return -1; 76 | } 77 | 78 | /* TODO: move this call to policy_session_create() */ 79 | #ifndef TSS2_LEGACY_V1 80 | policy_auth_set(&s.sessionsData.auths[0], s.session_handle, 81 | (char *)secret, secret_size); 82 | #else 83 | policy_auth_set(&s.sessionData, s.session_handle, 84 | (char *)secret, secret_size); 85 | #endif 86 | } else 87 | password_session_create(&s, (char *)secret, secret_size); 88 | 89 | #ifndef TSS2_LEGACY_V1 90 | TPM2B_SENSITIVE_DATA out_data = { sizeof(TPM2B_SENSITIVE_DATA)-2, }; 91 | #else 92 | TPM2B_SENSITIVE_DATA out_data = { { sizeof(TPM2B_SENSITIVE_DATA)-2, } }; 93 | #endif 94 | UINT32 rc; 95 | 96 | rc = Tss2_Sys_Unseal(cryptfs_tpm2_sys_context, 97 | CRYPTFS_TPM2_PASSPHRASE_HANDLE, 98 | &s.sessionsData, &out_data, 99 | &s.sessionsDataOut); 100 | policy_session_destroy(&s); 101 | if (rc != TPM2_RC_SUCCESS) { 102 | if (rc == TPM2_RC_LOCKOUT) { 103 | if (da_reset() == EXIT_SUCCESS) 104 | goto redo; 105 | } else if (tpm2_rc_is_format_one(rc) && 106 | (((tpm2_rc_get_code_7bit(rc) | TPM2_RC_FMT1) == 107 | TPM2_RC_BAD_AUTH) || 108 | ((tpm2_rc_get_code_7bit(rc) | TPM2_RC_FMT1) == 109 | TPM2_RC_AUTH_FAIL))) { 110 | err("Wrong passphrase secret specified\n"); 111 | 112 | secret_size = sizeof(secret); 113 | 114 | if (cryptfs_tpm2_util_get_passphrase_secret((uint8_t *)secret, 115 | &secret_size) == 116 | EXIT_SUCCESS) 117 | goto redo; 118 | } 119 | 120 | err("Unable to unseal the passphrase object (%#x)\n", rc); 121 | return -1; 122 | } 123 | 124 | #ifndef TSS2_LEGACY_V1 125 | info("Succeed to unseal the passphrase (%d-byte)\n", out_data.size); 126 | 127 | *passphrase = malloc(out_data.size); 128 | if (!*passphrase) 129 | return -1; 130 | 131 | memcpy(*passphrase, out_data.buffer, out_data.size); 132 | *passphrase_size = out_data.size; 133 | #else 134 | info("Succeed to unseal the passphrase (%d-byte)\n", out_data.t.size); 135 | 136 | *passphrase = malloc(out_data.t.size); 137 | if (!*passphrase) 138 | return -1; 139 | 140 | memcpy(*passphrase, out_data.t.buffer, out_data.t.size); 141 | *passphrase_size = out_data.t.size; 142 | #endif 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /src/lib/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #ifndef O_LARGEFILE 38 | #define O_LARGEFILE 0 39 | #endif 40 | 41 | static int show_verbose; 42 | 43 | int 44 | util_digest_size(TPMI_ALG_HASH hash_alg, UINT16 *alg_size) 45 | { 46 | switch (hash_alg) { 47 | case TPM2_ALG_SHA1: 48 | *alg_size = TPM2_SHA1_DIGEST_SIZE; 49 | break; 50 | case TPM2_ALG_SHA256: 51 | *alg_size = TPM2_SHA256_DIGEST_SIZE; 52 | break; 53 | case TPM2_ALG_SHA384: 54 | *alg_size = TPM2_SHA384_DIGEST_SIZE; 55 | break; 56 | case TPM2_ALG_SHA512: 57 | *alg_size = TPM2_SHA512_DIGEST_SIZE; 58 | break; 59 | case TPM2_ALG_SM3_256: 60 | *alg_size = TPM2_SM3_256_DIGEST_SIZE; 61 | break; 62 | default: 63 | err("Unsupported hash algorithm %#x\n", hash_alg); 64 | return -1; 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | int 71 | cryptfs_tpm2_util_verbose(void) 72 | { 73 | return show_verbose; 74 | } 75 | 76 | void 77 | cryptfs_tpm2_util_set_verbosity(int verbose) 78 | { 79 | show_verbose = verbose; 80 | } 81 | 82 | char ** 83 | cryptfs_tpm2_util_split_string(char *in, char *delim, unsigned int *nr) 84 | { 85 | char **out = NULL; 86 | unsigned int delim_sz = strlen(delim); 87 | 88 | *nr = 0; 89 | while (*in) { 90 | char *p = strstr(in, delim); 91 | int len; 92 | 93 | if (p) 94 | len = p - in; 95 | else 96 | len = strlen(in); 97 | 98 | char *str = strndup(in, len + 1); 99 | if (!str) { 100 | free(out); 101 | return NULL; 102 | } 103 | 104 | out = realloc(out, sizeof(char *) * (*nr + 1)); 105 | if (!out) { 106 | free(str); 107 | return NULL; 108 | } 109 | 110 | str[len] = 0; 111 | out[(*nr)++] = str; 112 | 113 | in += len; 114 | if (p) 115 | in += delim_sz; 116 | } 117 | 118 | return out; 119 | } 120 | 121 | int 122 | cryptfs_tpm2_util_mkdir(const char *dir, mode_t mode) 123 | { 124 | const char *dir_delim = dir; 125 | const char *dir_start = dir; 126 | char *dir_name; 127 | 128 | do { 129 | dir = dir_delim + strspn(dir_delim, "/"); 130 | dir_delim = dir + strcspn(dir, "/"); 131 | dir_name = strndup(dir_start, dir - dir_start); 132 | if (*dir_name) { 133 | if (mkdir(dir_name, mode) && errno != EEXIST) { 134 | err("Unable to create directory %s", dir_name); 135 | free(dir_name); 136 | return -1; 137 | } 138 | } 139 | free(dir_name); 140 | } while (dir != dir_delim); 141 | 142 | return 0; 143 | } 144 | 145 | bool 146 | cryptfs_tpm2_util_file_exists(const char *file_path) 147 | { 148 | struct stat statbuf; 149 | 150 | return !stat(file_path, &statbuf); 151 | } 152 | 153 | void 154 | cryptfs_tpm2_util_hex_dump(const char *prompt, const uint8_t *data, 155 | unsigned int data_size) 156 | { 157 | if (prompt) 158 | dbg("%s (%d-byte): ", prompt, data_size); 159 | 160 | for (uint8_t i = 0; i < data_size; ++i) 161 | dbg_cont("%02x", data[i]); 162 | 163 | dbg_cont("\n"); 164 | } 165 | 166 | int 167 | cryptfs_tpm2_util_load_file(const char *file_path, uint8_t **out, 168 | unsigned long *out_len) 169 | { 170 | FILE *fp; 171 | uint8_t *buf; 172 | unsigned int size; 173 | int ret; 174 | 175 | dbg("Opening file %s ...\n", file_path); 176 | 177 | fp = fopen(file_path, "rb"); 178 | if (!fp) { 179 | err("Failed to open file %s.\n", file_path); 180 | return -1; 181 | } 182 | 183 | if (fseek(fp, 0, SEEK_END)) { 184 | ret = -1; 185 | err("Failed to seek the end of file.\n"); 186 | goto err; 187 | } 188 | 189 | size = ftell(fp); 190 | if (!size) { 191 | ret = -1; 192 | err("Empty file.\n"); 193 | goto err; 194 | } 195 | 196 | rewind(fp); 197 | 198 | buf = (uint8_t *)malloc(size); 199 | if (!buf) { 200 | ret = -1; 201 | err("Failed to allocate memory for file.\n"); 202 | goto err; 203 | } 204 | 205 | if (fread(buf, size, 1, fp) != 1) { 206 | ret = -1; 207 | err("Failed to read file.\n"); 208 | free(buf); 209 | } else { 210 | *out = buf; 211 | *out_len = size; 212 | ret = 0; 213 | } 214 | 215 | err: 216 | fclose(fp); 217 | 218 | return ret; 219 | } 220 | 221 | int 222 | cryptfs_tpm2_util_save_output_file(const char *file_path, uint8_t *buf, 223 | unsigned long size) 224 | { 225 | FILE *fp; 226 | 227 | dbg("Saving output file %s ...\n", file_path); 228 | 229 | fp = fopen(file_path, "w"); 230 | if (!fp) { 231 | err("Failed to create output file.\n"); 232 | return -1; 233 | } 234 | 235 | if (fwrite(buf, size, 1, fp) != 1) { 236 | fclose(fp); 237 | err("Failed to write output file.\n"); 238 | return -1; 239 | } 240 | 241 | fclose(fp); 242 | 243 | return 0; 244 | } 245 | 246 | int 247 | get_input(const char *prompt, uint8_t *buf, unsigned int *buf_len) 248 | { 249 | if (prompt) { 250 | info_cont("%s", prompt); 251 | fflush(stdout); 252 | } 253 | 254 | struct termios term; 255 | int rc; 256 | 257 | rc = tcgetattr(STDIN_FILENO, &term); 258 | if (rc) 259 | return rc; 260 | 261 | term.c_lflag &= ~ECHO; 262 | tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); 263 | 264 | char input[256]; 265 | 266 | memset(input, 0, sizeof(input)); 267 | rc = scanf("%255[^\n]", input); 268 | 269 | term.c_lflag |= ECHO; 270 | tcsetattr(STDIN_FILENO, TCSANOW, &term); 271 | 272 | if (rc != 1) 273 | return EXIT_FAILURE; 274 | 275 | char cr; 276 | 277 | /* Work around the attribute warn_unused_result */ 278 | rc = scanf("%c", &cr); 279 | puts("\n"); 280 | 281 | unsigned int size = strlen(input); 282 | 283 | if (size > *buf_len) 284 | size = *buf_len; 285 | else 286 | *buf_len = size; 287 | 288 | strcpy((char *)buf, input); 289 | 290 | return EXIT_SUCCESS; 291 | } 292 | 293 | int 294 | cryptfs_tpm2_util_get_owner_auth(uint8_t *owner_auth, 295 | unsigned int *owner_auth_size) 296 | { 297 | if (!owner_auth || !owner_auth_size || !*owner_auth_size) 298 | return EXIT_FAILURE; 299 | 300 | bool required; 301 | 302 | if (cryptfs_tpm2_capability_owner_auth_required(&required) == 303 | EXIT_FAILURE) 304 | return EXIT_FAILURE; 305 | 306 | unsigned int opt_owner_auth_size = 0; 307 | 308 | if (cryptfs_tpm2_option_get_owner_auth(NULL, &opt_owner_auth_size)) 309 | return EXIT_FAILURE; 310 | 311 | if (required == true) { 312 | err("Wrong owner authentication\n"); 313 | 314 | if (cryptfs_tpm2_option_get_interactive(&required) == 315 | EXIT_FAILURE) 316 | return EXIT_FAILURE; 317 | 318 | if (required == false) 319 | return EXIT_FAILURE; 320 | 321 | if (get_input("Owner Authentication: ", owner_auth, 322 | owner_auth_size) == EXIT_FAILURE) 323 | return EXIT_FAILURE; 324 | } else if (opt_owner_auth_size) { 325 | warn("Ignore --owner-auth due to owner authentication not " 326 | "required\n"); 327 | 328 | *owner_auth_size = 0; 329 | } 330 | 331 | return EXIT_SUCCESS; 332 | } 333 | 334 | int 335 | cryptfs_tpm2_util_get_primary_key_secret(uint8_t *secret, 336 | unsigned int *secret_size) 337 | { 338 | bool required; 339 | 340 | if (cryptfs_tpm2_option_get_interactive(&required) == 341 | EXIT_FAILURE) 342 | return EXIT_FAILURE; 343 | 344 | if (required == false) 345 | return EXIT_FAILURE; 346 | 347 | if (!secret || !secret_size || !*secret_size) 348 | return EXIT_FAILURE; 349 | 350 | if (get_input("Primary Key Secret: ", secret, 351 | secret_size) == EXIT_FAILURE) 352 | return EXIT_FAILURE; 353 | 354 | return EXIT_SUCCESS; 355 | } 356 | 357 | int 358 | cryptfs_tpm2_util_get_passphrase_secret(uint8_t *secret, 359 | unsigned int *secret_size) 360 | { 361 | bool required; 362 | 363 | if (cryptfs_tpm2_option_get_interactive(&required)) 364 | return EXIT_FAILURE; 365 | 366 | if (required == false) 367 | return EXIT_FAILURE; 368 | 369 | if (!secret || !secret_size || !*secret_size) 370 | return EXIT_FAILURE; 371 | 372 | if (get_input("Passphrase Secret: ", secret, 373 | secret_size) == EXIT_FAILURE) 374 | return EXIT_FAILURE; 375 | 376 | return EXIT_SUCCESS; 377 | } 378 | -------------------------------------------------------------------------------- /src/luks-setup/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/env.mk 2 | include $(TOPDIR)/rules.mk 3 | 4 | BIN_NAME := luks-setup 5 | 6 | all: $(BIN_NAME).sh Makefile 7 | 8 | clean: 9 | 10 | install: all 11 | $(INSTALL) -d -m 755 $(DESTDIR)$(SBINDIR) 12 | $(INSTALL) -m 700 $(BIN_NAME).sh $(DESTDIR)$(SBINDIR)/$(BIN_NAME) 13 | -------------------------------------------------------------------------------- /src/tcti-probe/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/env.mk 2 | include $(TOPDIR)/rules.mk 3 | 4 | BIN_NAME := tcti-probe 5 | 6 | OBJS_$(BIN_NAME) := \ 7 | main.o \ 8 | subcmd_help.o \ 9 | subcmd_wait.o 10 | 11 | all: $(BIN_NAME) Makefile 12 | 13 | $(BIN_NAME): $(OBJS_$(BIN_NAME)) $(TOPDIR)/src/lib/$(LIB_NAME).a 14 | $(CCLD) $^ -o $@ $(CFLAGS) 15 | 16 | clean: 17 | @$(RM) $(OBJS_$(BIN_NAME)) $(BIN_NAME) 18 | 19 | install: all 20 | $(INSTALL) -d -m 755 $(DESTDIR)$(SBINDIR) 21 | $(INSTALL) -m 700 $(BIN_NAME) $(DESTDIR)$(SBINDIR) 22 | -------------------------------------------------------------------------------- /src/tcti-probe/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static int opt_quite; 38 | 39 | static void 40 | show_banner(void) 41 | { 42 | info_cont("\ntcti utility\n"); 43 | info_cont("(C)Copyright 2024, Alibaba Cloud\n"); 44 | info_cont("(C)Copyright 2017-2023, Wind River Systems, Inc.\n"); 45 | info_cont("Version: %s+git-%s\n", VERSION, cryptfs_tpm2_git_commit); 46 | } 47 | 48 | static void 49 | show_version(void) 50 | { 51 | info_cont("%s\n", VERSION); 52 | } 53 | 54 | static void 55 | show_usage(const char *prog) 56 | { 57 | info_cont("usage: %s []\n", 58 | prog); 59 | info_cont("\noptions:\n"); 60 | info_cont(" --help, -h: Print this help information\n"); 61 | info_cont(" --version, -V: Show version number\n"); 62 | info_cont(" --verbose, -v: Show verbose messages\n"); 63 | info_cont(" --quite, -q: Don't show banner information\n"); 64 | info_cont("\nsubcommand:\n"); 65 | info_cont(" help: Display the help information for the " 66 | "specified command\n"); 67 | info_cont(" wait: wait for the resource manager getting ready\n"); 68 | } 69 | 70 | static int 71 | parse_options(int argc, char *argv[]) 72 | { 73 | char opts[] = "-hVvq"; 74 | struct option long_opts[] = { 75 | { "help", no_argument, NULL, 'h' }, 76 | { "version", no_argument, NULL, 'V' }, 77 | { "verbose", no_argument, NULL, 'v' }, 78 | { "quite", no_argument, NULL, 'q' }, 79 | { 0 }, /* NULL terminated */ 80 | }; 81 | 82 | while (1) { 83 | int opt, index; 84 | 85 | opt = getopt_long(argc, argv, opts, long_opts, NULL); 86 | if (opt == -1) 87 | break; 88 | 89 | switch (opt) { 90 | case '?': 91 | err("Unrecognized option\n"); 92 | return -1; 93 | case 'h': 94 | show_usage(argv[0]); 95 | exit(EXIT_SUCCESS); 96 | case 'V': 97 | show_version(); 98 | exit(EXIT_SUCCESS); 99 | case 'v': 100 | cryptfs_tpm2_util_set_verbosity(1); 101 | break; 102 | case 'q': 103 | opt_quite = 1; 104 | break; 105 | case 1: 106 | index = optind; 107 | optind = 1; 108 | if (subcommand_parse(argv[0], optarg, argc - index + 1, 109 | argv + index - 1)) 110 | exit(EXIT_FAILURE); 111 | return 0; 112 | default: 113 | show_usage(argv[0]); 114 | return -1; 115 | } 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | extern subcommand_t subcommand_help; 122 | extern subcommand_t subcommand_wait; 123 | 124 | static void 125 | exit_notify(void) 126 | { 127 | if (cryptfs_tpm2_util_verbose()) 128 | info("tcti-probe exiting with %d (%s)\n", errno, 129 | strerror(errno)); 130 | } 131 | 132 | int 133 | main(int argc, char *argv[], char *envp[]) 134 | { 135 | atexit(exit_notify); 136 | 137 | subcommand_add(&subcommand_help); 138 | subcommand_add(&subcommand_wait); 139 | 140 | int rc = parse_options(argc, argv); 141 | if (rc) 142 | return rc; 143 | 144 | if (!opt_quite) 145 | show_banner(); 146 | 147 | return subcommand_run_current(); 148 | } 149 | -------------------------------------------------------------------------------- /src/tcti-probe/subcmd_help.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | static char *opt_command; 38 | 39 | static void 40 | show_usage(char *prog) 41 | { 42 | info_cont("\nUsage: %s help \n", prog); 43 | info_cont("\nsubcommand:\n"); 44 | info_cont(" The subcommand to be shown.\n"); 45 | } 46 | 47 | static int 48 | parse_arg(int opt, char *optarg) 49 | { 50 | switch (opt) { 51 | case 1: 52 | { 53 | subcommand_t *cmd; 54 | 55 | cmd = subcommand_find(optarg); 56 | if (!cmd) { 57 | err("Unrecognized subcommand argument " 58 | "\"%s\" specified\n", optarg); 59 | return -1; 60 | } 61 | opt_command = optarg; 62 | } 63 | break; 64 | default: 65 | return -1; 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | static int 72 | run_help(char *prog) 73 | { 74 | if (!opt_command) { 75 | show_usage(prog); 76 | return -1; 77 | } 78 | 79 | subcommand_find(opt_command)->show_usage(prog); 80 | 81 | return 0; 82 | } 83 | 84 | static struct option long_opts[] = { 85 | { 0 }, /* NULL terminated */ 86 | }; 87 | 88 | subcommand_t subcommand_help = { 89 | .name = "help", 90 | .optstring = "-", 91 | .long_opts = long_opts, 92 | .parse_arg = parse_arg, 93 | .show_usage = show_usage, 94 | .run = run_help, 95 | }; -------------------------------------------------------------------------------- /src/tcti-probe/subcmd_wait.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024, Alibaba Cloud 3 | * Copyright (c) 2016-2023, Wind River Systems, Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1) Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * 2) Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3) Neither the name of Wind River Systems nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | * POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * Author: 32 | * Jia Zhang 33 | */ 34 | 35 | #include 36 | 37 | #define DEFAULT_DELAY_MSEC 100UL 38 | #define DEFAULT_TIMEOUT_MSEC 5000UL 39 | 40 | static unsigned long opt_delay_ms = DEFAULT_DELAY_MSEC; 41 | static unsigned long opt_timeout_ms = DEFAULT_TIMEOUT_MSEC; 42 | 43 | static void 44 | show_usage(char *prog) 45 | { 46 | info_cont("\nUsage: %s wait \n", prog); 47 | info_cont("\nargs:\n"); 48 | info_cont(" --delay, -d:\n" 49 | " (optional)The delay (in millisecond) before\n" 50 | " attempting to connecting the resource manager.\n" 51 | " Default: %ld\n", DEFAULT_DELAY_MSEC); 52 | info_cont(" --timeout, -t:\n" 53 | " (optional) The timeout (in millisecond) upon\n" 54 | " awaiting the resource manager. 0 indicates infinite " 55 | "wait.\n" 56 | " Default: %ld\n", DEFAULT_TIMEOUT_MSEC); 57 | } 58 | 59 | static int 60 | parse_arg(int opt, char *optarg) 61 | { 62 | switch (opt) { 63 | case 'd': 64 | opt_delay_ms = strtoul(optarg, NULL, 0); 65 | break; 66 | case 't': 67 | opt_timeout_ms = strtoul(optarg, NULL, 0); 68 | break; 69 | default: 70 | return -1; 71 | } 72 | 73 | if (!opt_delay_ms) { 74 | err("Invalid setting of -d option\n"); 75 | return -1; 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | static void 82 | accurate_delay_begin(void) 83 | { 84 | struct sched_param param; 85 | int policy = SCHED_RR; 86 | 87 | param.sched_priority = sched_get_priority_max(policy); 88 | sched_setscheduler(0, policy, ¶m); 89 | } 90 | 91 | static void 92 | accurate_delay(unsigned long delay_ms) 93 | { 94 | struct timespec req; 95 | 96 | req.tv_sec = delay_ms / 1000; 97 | delay_ms %= 1000; 98 | req.tv_nsec = delay_ms * 1000000; 99 | 100 | while (1) { 101 | struct timespec rem; 102 | int err; 103 | 104 | err = nanosleep(&req, &rem); 105 | if (!err || errno != EINTR) 106 | break; 107 | 108 | req = rem; 109 | } 110 | } 111 | 112 | static int 113 | run_wait(char *prog) 114 | { 115 | TSS2_TCTI_CONTEXT *context = NULL; 116 | unsigned long total_delay_ms = 0; 117 | int ret = EXIT_SUCCESS; 118 | 119 | accurate_delay_begin(); 120 | 121 | while (1) { 122 | context = cryptfs_tpm2_tcti_init_context(); 123 | if (context) { 124 | info("The resource manager is getting ready\n"); 125 | break; 126 | } 127 | 128 | if (total_delay_ms + opt_delay_ms > opt_timeout_ms && 129 | opt_timeout_ms) 130 | opt_delay_ms = opt_timeout_ms - total_delay_ms; 131 | accurate_delay(opt_delay_ms); 132 | total_delay_ms += opt_delay_ms; 133 | 134 | dbg("Already waited for the resource manager %ld " 135 | "millisecond\n", total_delay_ms); 136 | 137 | if (total_delay_ms >= opt_timeout_ms && opt_timeout_ms) { 138 | err("Timeout upon awaiting the resource manager\n"); 139 | ret = EXIT_FAILURE; 140 | break; 141 | } 142 | } 143 | 144 | if (context) 145 | cryptfs_tpm2_tcti_teardown_context(context); 146 | 147 | return ret; 148 | } 149 | 150 | static struct option long_opts[] = { 151 | { "delay", required_argument, NULL, 'd' }, 152 | { "timeout", required_argument, NULL, 't' }, 153 | { 0 }, /* NULL terminated */ 154 | }; 155 | 156 | subcommand_t subcommand_wait = { 157 | .name = "wait", 158 | .optstring = "-d:t:", 159 | .long_opts = long_opts, 160 | .parse_arg = parse_arg, 161 | .show_usage = show_usage, 162 | .run = run_wait, 163 | }; 164 | -------------------------------------------------------------------------------- /version.mk: -------------------------------------------------------------------------------- 1 | MAJOR_VERSION := 0 2 | MINOR_VERSION := 7 3 | REVISION := 10 4 | VERSION := $(MAJOR_VERSION).$(MINOR_VERSION).$(REVISION) 5 | --------------------------------------------------------------------------------