From a3a1cd052297156035211e209d4788b6febf262e Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 26 Feb 2021 09:24:22 -0500 Subject: [PATCH] tpm2: Fix public key context save due to ANY_OBJECT_Marshal usage This patch fixes a VM suspend/resume issue when externally loaded public keys are involved. This patch addresses the bug reported in issue #195 where the saving of an externally loaded public key's context doesn't work due to the usage of ANY_CONTEXT_SAVE for saving key contexts. This patch fixes the issue by creating local versions of TPM_SENSITIVE_Marshal/_Unmarshal that deals with the case where sensitiveType is not a type of private key but a public key instead that basically doesn't have much information in TPM_SENSITIVE but is all zeros instead. Signed-off-by: Stefan Berger --- src/tpm2/NVMarshal.c | 65 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c index 74ea17f4..e764f649 100644 --- a/src/tpm2/NVMarshal.c +++ b/src/tpm2/NVMarshal.c @@ -2248,6 +2248,67 @@ skip_future_versions: return rc; } +/* Local version of TPMT_SENSITIVE_Marshal handling public keys that don't have much in TPM_SENSITIVE */ +static UINT16 +NV_TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size) +{ + UINT16 written = 0; + + written += TPM_ALG_ID_Marshal(&source->sensitiveType, buffer, size); + written += TPM2B_AUTH_Marshal(&source->authValue, buffer, size); + written += TPM2B_DIGEST_Marshal(&source->seedValue, buffer, size); + + switch (source->sensitiveType) { + case TPM_ALG_RSA: + case TPM_ALG_ECC: + case TPM_ALG_KEYEDHASH: + case TPM_ALG_SYMCIPHER: + written += TPMU_SENSITIVE_COMPOSITE_Marshal(&source->sensitive, buffer, size, source->sensitiveType); + break; + default: + /* we wrote these but they must have been 0 in this case */ + pAssert(source->authValue.t.size == 0); + pAssert(source->seedValue.t.size == 0); + pAssert(source->sensitiveType == TPM_ALG_ERROR) + /* public keys */ + } + return written; +} + +/* local version of TPM_SENSITIVE_Unmarshal handling public keys that don't have much in TPMT_SENSITVE */ +static TPM_RC +NV_TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size) +{ + TPM_RC rc = TPM_RC_SUCCESS; + + if (rc == TPM_RC_SUCCESS) { + /* TPMI_ALG_PUBLIC_Unmarshal would test the sensitiveType; we don't want this */ + rc = TPM_ALG_ID_Unmarshal(&target->sensitiveType, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_AUTH_Unmarshal(&target->authValue, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + rc = TPM2B_DIGEST_Unmarshal(&target->seedValue, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { + switch (target->sensitiveType) { + case TPM_ALG_RSA: + case TPM_ALG_ECC: + case TPM_ALG_KEYEDHASH: + case TPM_ALG_SYMCIPHER: + rc = TPMU_SENSITIVE_COMPOSITE_Unmarshal(&target->sensitive, buffer, size, target->sensitiveType); + break; + default: + pAssert(target->authValue.t.size == 0); + pAssert(target->seedValue.t.size == 0); + pAssert(target->sensitiveType == TPM_ALG_ERROR) + /* nothing do to do */ + } + } + return rc; +} + #define OBJECT_MAGIC 0x75be73af #define OBJECT_VERSION 2 @@ -2265,7 +2326,7 @@ OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size) * attributes are written in ANY_OBJECT_Marshal */ written += TPMT_PUBLIC_Marshal(&data->publicArea, buffer, size); - written += TPMT_SENSITIVE_Marshal(&data->sensitive, buffer, size); + written += NV_TPMT_SENSITIVE_Marshal(&data->sensitive, buffer, size); #if ALG_RSA has_block = TRUE; @@ -2312,7 +2373,7 @@ OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size) rc = TPMT_PUBLIC_Unmarshal(&data->publicArea, buffer, size, TRUE); } if (rc == TPM_RC_SUCCESS) { - rc = TPMT_SENSITIVE_Unmarshal(&data->sensitive, buffer, size); + rc = NV_TPMT_SENSITIVE_Unmarshal(&data->sensitive, buffer, size); } #if ALG_RSA