Skip to content

Commit

Permalink
tpm: Add full HMAC and encrypt/decrypt session handling code
Browse files Browse the repository at this point in the history
Add true session based HMAC authentication plus parameter decryption
and response encryption using AES. The basic design is to segregate
all the nasty crypto, hash and hmac code into tpm2-sessions.c and
export a usable API.  The API first of all starts off by gaining a
session with

tpm2_start_auth_session()

Which initiates a session with the TPM and allocates an opaque
tpm2_auth structure to handle the session parameters.  Then the use is
simply:

* tpm_buf_append_name() in place of the tpm_buf_append_u32 for the
  handles

* tpm_buf_append_hmac_session() where tpm2_append_auth() would go

* tpm_buf_fill_hmac_session() called after the entire command buffer
  is finished but before tpm_transmit_cmd() is called which computes
  the correct HMAC and places it in the command at the correct
  location.

Finally, after tpm_transmit_cmd() is called,
tpm_buf_check_hmac_response() is called to check that the returned
HMAC matched and collect the new state for the next use of the
session, if any.

The features of the session is controlled by the session attributes
set in tpm_buf_append_hmac_session().  If TPM2_SA_CONTINUE_SESSION is
not specified, the session will be flushed and the tpm2_auth structure
freed in tpm_buf_check_hmac_response(); otherwise the session may be
used again.  Parameter encryption is specified by or'ing the flag
TPM2_SA_DECRYPT and response encryption by or'ing the flag
TPM2_SA_ENCRYPT.  the various encryptions will be taken care of by
tpm_buf_fill_hmac_session() and tpm_buf_check_hmac_response()
respectively.

To get all of this to work securely, the Kernel needs a primary key to
encrypt the session salt to, so an EC key from the NULL seed is
derived and its context saved in the tpm_chip structure.  The context
is loaded on demand into an available volatile handle when
tpm_start_auth_session() is called, but is flushed before that
function exits to conserve handles.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> # crypto API parts
  • Loading branch information
James Bottomley authored and intel-lab-lkp committed Apr 3, 2023
1 parent 196dd6e commit 2fbef78
Show file tree
Hide file tree
Showing 8 changed files with 1,356 additions and 0 deletions.
13 changes: 13 additions & 0 deletions drivers/char/tpm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ menuconfig TCG_TPM

if TCG_TPM

config TPM_BUS_SECURITY
bool "Use secure transactions on the TPM bus"
default y
select CRYPTO_ECDH
select CRYPTO_LIB_AESCFB
select CRYPTO_LIB_SHA256
help
Setting this causes us to deploy a tamper resistent scheme
for communicating with the TPM to prevent or detect bus
snooping and iterposer attacks like TPM Genie. Saying Y here
adds some encryption overhead to all kernel to TPM
transactions.

config HW_RANDOM_TPM
bool "TPM HW Random Number Generator support"
depends on TCG_TPM && HW_RANDOM && !(TCG_TPM=y && HW_RANDOM=m)
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tpm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ tpm-y += eventlog/tpm1.o
tpm-y += eventlog/tpm2.o
tpm-y += tpm-buf.o

tpm-$(CONFIG_TPM_BUS_SECURITY) += tpm2-sessions.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o
tpm-$(CONFIG_EFI) += eventlog/efi.o
tpm-$(CONFIG_OF) += eventlog/of.o
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tpm/tpm-buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
head->tag = cpu_to_be16(tag);
head->length = cpu_to_be32(sizeof(*head));
head->ordinal = cpu_to_be32(ordinal);
buf->handles = 0;
}
EXPORT_SYMBOL_GPL(tpm_buf_reset);

Expand Down
3 changes: 3 additions & 0 deletions drivers/char/tpm/tpm-chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ static void tpm_dev_release(struct device *dev)
kfree(chip->work_space.context_buf);
kfree(chip->work_space.session_buf);
kfree(chip->allocated_banks);
#ifdef CONFIG_TPM_BUS_SECURITY
kfree(chip->auth);
#endif
kfree(chip);
}

Expand Down
10 changes: 10 additions & 0 deletions drivers/char/tpm/tpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,14 @@ void tpm_bios_log_setup(struct tpm_chip *chip);
void tpm_bios_log_teardown(struct tpm_chip *chip);
int tpm_dev_common_init(void);
void tpm_dev_common_exit(void);

#ifdef CONFIG_TPM_BUS_SECURITY
int tpm2_sessions_init(struct tpm_chip *chip);
#else
static inline int tpm2_sessions_init(struct tpm_chip *chip)
{
return 0;
}
#endif

#endif
5 changes: 5 additions & 0 deletions drivers/char/tpm/tpm2-cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,11 @@ int tpm2_auto_startup(struct tpm_chip *chip)
rc = 0;
}

if (rc)
goto out;

rc = tpm2_sessions_init(chip);

out:
/*
* Infineon TPM in field upgrade mode will return no data for the number
Expand Down

0 comments on commit 2fbef78

Please sign in to comment.