diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/tpm2-util.c | 104 | ||||
-rw-r--r-- | src/shared/tpm2-util.h | 1 |
2 files changed, 91 insertions, 14 deletions
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 44fe899acd..3dfc5d8b7d 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -36,6 +36,7 @@ TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR policySes TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) = NULL; TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) = NULL; TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType) = NULL; +TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask); TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) = NULL; TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData) = NULL; @@ -66,6 +67,7 @@ int dlopen_tpm2(void) { DLSYM_ARG(Esys_PolicyPCR), DLSYM_ARG(Esys_StartAuthSession), DLSYM_ARG(Esys_Startup), + DLSYM_ARG(Esys_TRSess_SetAttributes), DLSYM_ARG(Esys_TR_SetAuth), DLSYM_ARG(Esys_Unseal)); if (r < 0) @@ -595,8 +597,71 @@ static int tpm2_get_best_pcr_bank( return 0; } +static int tpm2_make_encryption_session( + ESYS_CONTEXT *c, + ESYS_TR tpmKey, + ESYS_TR *ret_session) { + + static const TPMT_SYM_DEF symmetric = { + .algorithm = TPM2_ALG_AES, + .keyBits = { + .aes = 128, + }, + .mode = { + .aes = TPM2_ALG_CFB, + }, + }; + const TPMA_SESSION sessionAttributes = TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT | + TPMA_SESSION_CONTINUESESSION; + ESYS_TR session = ESYS_TR_NONE; + TSS2_RC rc; + + assert(c); + + log_debug("Starting HMAC encryption session."); + + /* Start a salted, unbound HMAC session with a well-known key (e.g. primary key) as tpmKey, which + * means that the random salt will be encrypted with the well-known key. That way, only the TPM can + * recover the salt, which is then used for key derivation. */ + rc = sym_Esys_StartAuthSession( + c, + tpmKey, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + NULL, + TPM2_SE_HMAC, + &symmetric, + TPM2_ALG_SHA256, + &session); + if (rc != TSS2_RC_SUCCESS) + return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), + "Failed to open session in TPM: %s", sym_Tss2_RC_Decode(rc)); + + /* Enable parameter encryption/decryption with AES in CFB mode. Together with HMAC digests (which are + * always used for sessions), this provides confidentiality, integrity and replay protection for + * operations that use this session. */ + rc = sym_Esys_TRSess_SetAttributes(c, session, sessionAttributes, 0xff); + if (rc != TSS2_RC_SUCCESS) + return log_error_errno( + SYNTHETIC_ERRNO(ENOTRECOVERABLE), + "Failed to configure TPM session: %s", + sym_Tss2_RC_Decode(rc)); + + if (ret_session) { + *ret_session = session; + session = ESYS_TR_NONE; + } + + session = flush_context_verbose(c, session); + return 0; +} + static int tpm2_make_pcr_session( ESYS_CONTEXT *c, + ESYS_TR tpmKey, + ESYS_TR parent_session, uint32_t pcr_mask, uint16_t pcr_bank, /* If UINT16_MAX, pick best bank automatically, otherwise specify bank explicitly. */ bool use_pin, @@ -645,9 +710,9 @@ static int tpm2_make_pcr_session( rc = sym_Esys_StartAuthSession( c, + tpmKey, ESYS_TR_NONE, - ESYS_TR_NONE, - ESYS_TR_NONE, + parent_session, ESYS_TR_NONE, ESYS_TR_NONE, NULL, @@ -771,7 +836,7 @@ int tpm2_seal( _cleanup_(erase_and_freep) void *secret = NULL; _cleanup_free_ void *blob = NULL, *hash = NULL; TPM2B_SENSITIVE_CREATE hmac_sensitive; - ESYS_TR primary = ESYS_TR_NONE; + ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE; TPMI_ALG_PUBLIC primary_alg; TPM2B_PUBLIC hmac_template; TPMI_ALG_HASH pcr_bank; @@ -816,8 +881,12 @@ int tpm2_seal( if (r < 0) return r; - r = tpm2_make_pcr_session(c.esys_context, pcr_mask, UINT16_MAX, !!pin, NULL, &policy_digest, - &pcr_bank); + r = tpm2_make_encryption_session(c.esys_context, primary, &session); + if (r < 0) + goto finish; + + r = tpm2_make_pcr_session(c.esys_context, primary, session, pcr_mask, UINT16_MAX, !!pin, NULL, + &policy_digest, &pcr_bank); if (r < 0) goto finish; @@ -869,7 +938,7 @@ int tpm2_seal( rc = sym_Esys_Create( c.esys_context, primary, - ESYS_TR_PASSWORD, + session, /* use HMAC session to enable parameter encryption */ ESYS_TR_NONE, ESYS_TR_NONE, &hmac_sensitive, @@ -951,6 +1020,7 @@ int tpm2_seal( finish: explicit_bzero_safe(&hmac_sensitive, sizeof(hmac_sensitive)); primary = flush_context_verbose(c.esys_context, primary); + session = flush_context_verbose(c.esys_context, session); return r; } @@ -968,7 +1038,8 @@ int tpm2_unseal( size_t *ret_secret_size) { _cleanup_(tpm2_context_destroy) struct tpm2_context c = {}; - ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE, hmac_key = ESYS_TR_NONE; + ESYS_TR primary = ESYS_TR_NONE, session = ESYS_TR_NONE, hmac_session = ESYS_TR_NONE, + hmac_key = ESYS_TR_NONE; _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL; _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL; _cleanup_(erase_and_freep) char *secret = NULL; @@ -1019,7 +1090,16 @@ int tpm2_unseal( if (r < 0) return r; - r = tpm2_make_pcr_session(c.esys_context, pcr_mask, pcr_bank, !!pin, &session, &policy_digest, NULL); + r = tpm2_make_primary(c.esys_context, &primary, primary_alg, NULL); + if (r < 0) + return r; + + r = tpm2_make_encryption_session(c.esys_context, primary, &hmac_session); + if (r < 0) + goto finish; + + r = tpm2_make_pcr_session(c.esys_context, primary, hmac_session, pcr_mask, pcr_bank, !!pin, &session, + &policy_digest, NULL); if (r < 0) goto finish; @@ -1030,16 +1110,12 @@ int tpm2_unseal( return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Current policy digest does not match stored policy digest, cancelling TPM2 authentication attempt."); - r = tpm2_make_primary(c.esys_context, &primary, primary_alg, NULL); - if (r < 0) - return r; - log_debug("Loading HMAC key into TPM."); rc = sym_Esys_Load( c.esys_context, primary, - ESYS_TR_PASSWORD, + hmac_session, /* use HMAC session to enable parameter encryption */ ESYS_TR_NONE, ESYS_TR_NONE, &private, @@ -1084,7 +1160,7 @@ int tpm2_unseal( c.esys_context, hmac_key, session, - ESYS_TR_NONE, + hmac_session, /* use HMAC session to enable parameter encryption */ ESYS_TR_NONE, &unsealed); if (rc != TSS2_RC_SUCCESS) { diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 5a9bcf8c24..f9dedd670b 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -31,6 +31,7 @@ extern TSS2_RC (*sym_Esys_PolicyGetDigest)(ESYS_CONTEXT *esysContext, ESYS_TR po extern TSS2_RC (*sym_Esys_PolicyPCR)(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs); extern TSS2_RC (*sym_Esys_StartAuthSession)(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle); extern TSS2_RC (*sym_Esys_Startup)(ESYS_CONTEXT *esysContext, TPM2_SU startupType); +extern TSS2_RC (*sym_Esys_TRSess_SetAttributes)(ESYS_CONTEXT *esysContext, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask); extern TSS2_RC (*sym_Esys_TR_SetAuth)(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue); extern TSS2_RC (*sym_Esys_Unseal)(ESYS_CONTEXT *esysContext, ESYS_TR itemHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_SENSITIVE_DATA **outData); |