From d4b9d10ce9663e947442b163f99e15a9e7ec1a86 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 10 Nov 2017 23:02:28 -0500 Subject: [PATCH] tpm2: Handle failures better The current TpmFail() implementation invokes longjmp() at the end and crashes with a segmentation fault if setjmp() wasn't called before. To avoid this we implement TpmSetFailureMode() that logs the failure and sets the TPM into failure mode. Since NVRAM may set failure mode before the CryptInit() is called, we need to make sure we don't reset the failure mode variable in case CryptInit() succeeds. In this case we now call the FAIL_NOCMD() macro. Signed-off-by: Stefan Berger --- src/tpm2/GpMacros.h | 4 ++- src/tpm2/NVReserved.c | 2 +- src/tpm2/StartupCommands.c | 2 +- src/tpm2/TpmFail.c | 51 +++++++++++++++++++++++++++++++++++--- src/tpm2/TpmFail_fp.h | 8 ++++++ 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/tpm2/GpMacros.h b/src/tpm2/GpMacros.h index ad24014..f8cff51 100644 --- a/src/tpm2/GpMacros.h +++ b/src/tpm2/GpMacros.h @@ -85,14 +85,16 @@ #endif // SELF_TEST /* 5.11.3 For Failures */ #if defined _POSIX_ -# define FUNCTION_NAME 0 +# define FUNCTION_NAME __func__ #else # define FUNCTION_NAME __FUNCTION__ #endif #ifdef NO_FAIL_TRACE # define FAIL(errorCode) (TpmFail(errorCode)) +# define FAIL_NOCMD(errorCode) (TpmSetFailureMode(errorCode) #else # define FAIL(errorCode) (TpmFail(FUNCTION_NAME, __LINE__, errorCode)) +# define FAIL_NOCMD(errorCode) (TpmSetFailureMode(FUNCTION_NAME, __LINE__, errorCode)) #endif /* If implementation is using longjmp, then the call to TpmFail() does not return and the compiler will complain about unreachable code that comes after. To allow for not having longjmp, TpmFail() diff --git a/src/tpm2/NVReserved.c b/src/tpm2/NVReserved.c index 39df843..f782196 100644 --- a/src/tpm2/NVReserved.c +++ b/src/tpm2/NVReserved.c @@ -123,7 +123,7 @@ NvPowerOn( if(g_powerWasLost) { if((nvError = _plat__NVEnable(0)) < 0) - FAIL(FATAL_ERROR_NV_UNRECOVERABLE); + FAIL_NOCMD(FATAL_ERROR_NV_UNRECOVERABLE); NvInitStatic(); } return nvError == 0; diff --git a/src/tpm2/StartupCommands.c b/src/tpm2/StartupCommands.c index abd68af..d8cb44d 100644 --- a/src/tpm2/StartupCommands.c +++ b/src/tpm2/StartupCommands.c @@ -94,7 +94,7 @@ _TPM_Init( // Initialize the NvEnvironment. g_nvOk = NvPowerOn(); // Initialize cryptographic functions - g_inFailureMode = (CryptInit() == FALSE); + g_inFailureMode |= (CryptInit() == FALSE); // stefanb if(!g_inFailureMode) { // Load the persistent data diff --git a/src/tpm2/TpmFail.c b/src/tpm2/TpmFail.c index 16ebcd4..d687f6e 100644 --- a/src/tpm2/TpmFail.c +++ b/src/tpm2/TpmFail.c @@ -191,13 +191,13 @@ TpmFail( ) { #if 0 +#ifndef NO_FAIL_TRACE UINT32 *failFuncp; -#endif // Save the values that indicate where the error occurred. // On a 64-bit machine, this may truncate the address of the string // of the function name where the error occurred. -#ifndef NO_FAIL_TRACE - s_failFunction = *(UINT32 *)&function; + failFuncp = (UINT32 *)&function; + s_failFunction = *failFuncp; s_failLine = line; #else s_failFunction = (UINT32)0; @@ -214,11 +214,56 @@ TpmFail( # endif // Clear this flag g_forceFailureMode = FALSE; +#endif + +#else + + TpmSetFailureMode( +#ifndef NO_FAIL_TRACE + function, line, +#endif + code); + #endif // Jump to the failure mode code. // Note: only get here if asserts are off or if we are testing failure mode _plat__Fail(); } + +void +TpmSetFailureMode( +#ifndef NO_FAIL_TRACE + const char *function, + int line, +#endif + int code + ) +{ + // Save the values that indicate where the error occurred. + // On a 64-bit machine, this may truncate the address of the string + // of the function name where the error occurred. +#ifndef NO_FAIL_TRACE + s_failFunction = *(UINT32 *)function; + s_failLine = line; +#else + s_failFunction = (UINT32)0; + s_failLine = 0; +#endif + s_failCode = code; + + TPMLIB_LogTPM2Error("Entering failure mode; code: %d" +#ifndef NO_FAIL_TRACE + ", location: %s line %d" +#endif + "\n", s_failCode +#ifndef NO_FAIL_TRACE + , function, s_failLine +#endif + ); + + // We are in failure mode + g_inFailureMode = TRUE; +} /* 9.17.5 TpmFailureMode */ /* This function is called by the interface code when the platform is in failure mode. */ void diff --git a/src/tpm2/TpmFail_fp.h b/src/tpm2/TpmFail_fp.h index 2f509bf..928c8d1 100644 --- a/src/tpm2/TpmFail_fp.h +++ b/src/tpm2/TpmFail_fp.h @@ -77,6 +77,14 @@ TpmFail( int code ); void +TpmSetFailureMode( +#ifndef NO_FAIL_TRACE + const char *function, + int line, +#endif + int code + ); +void TpmFailureMode( unsigned int inRequestSize, // IN: command buffer size unsigned char *inRequest, // IN: command buffer -- 2.39.5