Files
tpm2-linux/README.md
T

136 lines
6.7 KiB
Markdown

# TPM 2.0 Password Management Scripts
Two pairs of scripts for storing and retrieving a password using the TPM 2.0 on Ubuntu 24.04.
## Requirements
- Ubuntu 24.04
- `tpm2-tools` package (`apt install tpm2-tools`)
- Access to `/dev/tpmrm0`, either as root or as a member of the `tss` group
## Which pair to use
- `tpm-nv-store-password.sh` / `tpm-nv-read-password.sh` : stores the password as plaintext inside the TPM's own NV (non-volatile) memory. Confidentiality comes only from the TPM enforcing access to the index; the data itself is not encrypted.
- `tpm-seal-password.sh` / `tpm-unseal-password.sh` : seals the password as an encrypted TPM object and binds its release to a PCR policy, so it can only be unsealed when the current boot measurements match those recorded at seal time.
## tpm-nv-store-password.sh
Stores a password directly in a TPM NV index.
### Usage
```
tpm-nv-store-password.sh [-H handle] [-f]
```
- `-H handle` : NV index to store the password at. Default: `0x1500016`.
- `-f` : Undefine any existing NV index at the target handle before storing the new password.
### Behavior
1. Checks that `tpm2-tools` is installed.
2. Checks whether an NV index already exists at the target handle. If one exists and `-f` was not given, the script exits with an error.
3. Prompts for the password twice (input is not echoed) and verifies both entries match.
4. Defines an NV index sized to the exact byte length of the password, under the TPM owner hierarchy.
5. Writes the password into that index.
### Exit status
Non-zero if `tpm2-tools` is missing, if an NV index already exists at the handle without `-f`, or if the two password entries do not match.
## tpm-nv-read-password.sh
Retrieves a password previously stored with `tpm-nv-store-password.sh`.
### Usage
```
tpm-nv-read-password.sh [-H handle]
```
- `-H handle` : NV index the password was stored at. Default: `0x1500016`.
### Behavior
1. Checks that `tpm2-tools` is installed.
2. Checks that an NV index exists at the given handle.
3. Reads the full contents of the index and prints the password to stdout.
### Exit status
Non-zero if `tpm2-tools` is missing or if no NV index exists at the given handle.
## tpm-seal-password.sh
Seals a password into the TPM as an encrypted object and persists it at a TPM handle. The sealed object's authorization policy requires the current PCR values to match those read at seal time.
### Usage
```
tpm-seal-password.sh [-H handle] [-l pcr-list] [-f]
```
- `-H handle` : Persistent TPM handle to store the sealed password at. Default: `0x81010001`.
- `-l pcr-list` : PCR bank and indices to bind release to, in `tpm2_createpolicy --policy-pcr -l` format. Default: `sha256:7` (Secure Boot state).
- `-f` : Evict any existing object already stored at the target handle before sealing the new password.
### Behavior
1. Checks that `tpm2-tools` is installed.
2. Checks whether an object already exists at the target handle. If one exists and `-f` was not given, the script exits with an error.
3. Prompts for the password twice (input is not echoed) and verifies both entries match.
4. Creates a primary key under the TPM owner hierarchy.
5. Reads the current values of the given PCRs and builds a policy digest requiring those exact values.
6. Seals the password as a TPM sealed data object under that primary key, with the PCR policy digest as its authorization policy.
7. Loads the sealed object into the TPM and persists it at the target handle via `tpm2_evictcontrol`.
8. Removes all temporary key material created during the process.
### Exit status
Non-zero if `tpm2-tools` is missing, if a sealed object already exists at the handle without `-f`, or if the two password entries do not match.
## tpm-unseal-password.sh
Retrieves a password previously sealed with `tpm-seal-password.sh`.
### Usage
```
tpm-unseal-password.sh [-H handle] [-l pcr-list]
```
- `-H handle` : Persistent TPM handle the password was sealed at. Default: `0x81010001`.
- `-l pcr-list` : PCR bank and indices the password was bound to at seal time. Default: `sha256:7`.
### Behavior
1. Checks that `tpm2-tools` is installed.
2. Checks that a sealed object exists at the given handle.
3. Unseals the object using a PCR policy session built from the current PCR values, and prints the password to stdout. The TPM refuses the operation if the current PCR values do not match those recorded at seal time.
### Exit status
Non-zero if `tpm2-tools` is missing, if no sealed object exists at the given handle, or if the current PCR values do not satisfy the policy recorded at seal time.
## Security properties
### NV storage pair
The password is stored as plaintext inside the TPM's non-volatile memory. Confidentiality relies entirely on the TPM enforcing the NV index's access attributes (`ownerread`/`ownerwrite` under the owner hierarchy) for every read and write command. Anyone with access to the TPM device (`/dev/tpmrm0`) and the owner hierarchy authorization (empty by default, since none is set) can run `tpm-nv-read-password.sh` and retrieve the password, regardless of what booted the machine.
### Sealing pair
The password is encrypted under the primary key before being written to the TPM, and stays encrypted even while persisted inside the TPM's own non-volatile memory. Release additionally requires a policy session proving the current PCR values match those recorded at seal time, so unsealing fails if the machine was booted through a different firmware, bootloader, or Secure Boot configuration than the one in effect when the password was sealed.
This policy binding does not protect the password from a process running with sufficient privilege on a machine that has already booted through the expected boot chain, since at that point the PCR values satisfy the policy and `tpm2_unseal` succeeds for any caller with TPM device access. It also does not protect against bus-sniffing attacks on TPM implementations where the TPM chip is discrete (a separate chip on the LPC/SPI bus) and commands are not sent through an encrypted TPM session, since neither script establishes one.
Any firmware, bootloader, or Secure Boot configuration change that alters the measured value of the bound PCRs invalidates the existing seal. The password must be resealed against the new PCR values (rerun `tpm-seal-password.sh -f`) before it can be unsealed again.
## Handles
`tpm-nv-store-password.sh`/`tpm-nv-read-password.sh` default to NV index `0x1500016`, in the NV index handle range (`0x01000000`-`0x01FFFFFF`).
`tpm-seal-password.sh`/`tpm-unseal-password.sh` default to persistent handle `0x81010001`, in the TPM's owner-hierarchy persistent handle range (`0x81000000`-`0x81FFFFFF`).
Use `-H` with the same value on both scripts of a pair if a different handle is required, or to manage multiple stored passwords at distinct handles.