// This file was extracted from the TCG Published // Trusted Platform Module Library // Part 4: Supporting Routines // Family "2.0" // Level 00 Revision 01.16 // October 30, 2014 #include "Global.h" #include "CryptoEngine.h" #include "InternalRoutines.h" #include "AlgorithmCap_fp.h" // // // 10.4.2 Functions // // 10.4.2.1 RunSelfTest() // // Local function to run self-test // static TPM_RC CryptRunSelfTests( ALGORITHM_VECTOR *toTest // IN: the vector of the algorithms to test ) { TPM_ALG_ID alg; // For each of the algorithms that are in the toTestVecor, need to run a // test for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++) { if(TEST_BIT(alg, *toTest)) { TPM_RC result = CryptTestAlgorithm(alg, toTest); if(result != TPM_RC_SUCCESS) return result; } } return TPM_RC_SUCCESS; } // // // 10.4.2.2 CryptSelfTest() // // This function is called to start/complete a full self-test. If fullTest is NO, then only the untested algorithms // will be run. If fullTest is YES, then g_untestedDecryptionAlgorithms is reinitialized and then all tests are // run. This implementation of the reference design does not support processing outside the framework of a // TPM command. As a consequence, this command does not complete until all tests are done. Since this // can take a long time, the TPM will check after each test to see if the command is canceled. If so, then the // TPM will returned TPM_RC_CANCELLED. To continue with the self-tests, call TPM2_SelfTest(fullTest == // No) and the TPM will complete the testing. // // Error Returns Meaning // // TPM_RC_CANCELED if the command is canceled // LIB_EXPORT TPM_RC CryptSelfTest( TPMI_YES_NO fullTest // IN: if full test is required ) { if(g_forceFailureMode) FAIL(FATAL_ERROR_FORCED); // If the caller requested a full test, then reset the to test vector so that // all the tests will be run if(fullTest == YES) { MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest), sizeof(g_toTest)); } return CryptRunSelfTests(&g_toTest); } // // // 10.4.2.3 CryptIncrementalSelfTest() // // This function is used to perform an incremental self-test. This implementation will perform the toTest // values before returning. That is, it assumes that the TPM cannot perform background tasks between // commands. // This command may be canceled. If it is, then there is no return result. However, this command can be run // again and the incremental progress will not be lost. // // Error Returns Meaning // // TPM_RC_CANCELED processing of this command was canceled // TPM_RC_TESTING if toTest list is not empty // TPM_RC_VALUE an algorithm in the toTest list is not implemented // TPM_RC CryptIncrementalSelfTest( TPML_ALG *toTest, // IN: list of algorithms to be tested TPML_ALG *toDoList // OUT: list of algorithms needing test ) { ALGORITHM_VECTOR toTestVector = {0}; TPM_ALG_ID alg; UINT32 i; pAssert(toTest != NULL && toDoList != NULL); if(toTest->count > 0) { // Transcribe the toTest list into the toTestVector for(i = 0; i < toTest->count; i++) { TPM_ALG_ID alg = toTest->algorithms[i]; // make sure that the algorithm value is not out of range if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms)) return TPM_RC_VALUE; SET_BIT(alg, toTestVector); } // Run the test if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED) return TPM_RC_CANCELED; } // Fill in the toDoList with the algorithms that are still untested toDoList->count = 0; for(alg = TPM_ALG_FIRST; toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST; alg++) { if(TEST_BIT(alg, g_toTest)) toDoList->algorithms[toDoList->count++] = alg; } return TPM_RC_SUCCESS; // } // // // 10.4.2.4 CryptInitializeToTest() // // This function will initialize the data structures for testing all the algorithms. This should not be called // unless CryptAlgsSetImplemented() has been called // void CryptInitializeToTest( void ) { MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest), sizeof(g_toTest)); // Setting the algorithm to null causes the test function to just clear // out any algorithms for which there is no test. CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest); return; } // // // 10.4.2.5 CryptTestAlgorithm() // // Only point of contact with the actual self tests. If a self-test fails, there is no return and the TPM goes into // failure mode. The call to TestAlgorithm() uses an algorithms selector and a bit vector. When the test is // run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest is NULL, then only the bit in // g_toTest is CLEAR. There is a special case for the call to TestAlgorithm(). When alg is // TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for which it has no test. This allows the // knowledge about which algorithms have test to be accessed through the interface that provides the test. // // Error Returns Meaning // // TPM_RC_SUCCESS test complete // TPM_RC_CANCELED test was canceled // LIB_EXPORT TPM_RC CryptTestAlgorithm( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ) { TPM_RC result = TPM_RC_SUCCESS; #ifdef SELF_TEST // This is the function prototype for TestAlgorithms(). It is here and not // in a _fp.h file to avoid a compiler error when SELF_TEST is not defined and // AlgorithmTexts.c is not part of the build. TPM_RC TestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest); result = TestAlgorithm(alg, toTest); #else // If this is an attempt to determine the algorithms for which there is a // self test, pretend that all of them do. We do that by not clearing any // of the algorithm bits. When/if this function is called to run tests, it // will over report. This can be changed so that any call to check on which // algorithms have tests, 'toTest' can be cleared. if(alg != TPM_ALG_ERROR) { CLEAR_BIT(alg, g_toTest); if(toTest != NULL) CLEAR_BIT(alg, *toTest); } #endif return result; }