191 lines
6.8 KiB
C
191 lines
6.8 KiB
C
// 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;
|
|
}
|