1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 4: Supporting Routines 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #include "Global.h" 9 #include "CryptoEngine.h" 10 #include "InternalRoutines.h" 11 #include "AlgorithmCap_fp.h" 12 // 13 // 14 // 10.4.2 Functions 15 // 16 // 10.4.2.1 RunSelfTest() 17 // 18 // Local function to run self-test 19 // 20 static TPM_RC 21 CryptRunSelfTests( 22 ALGORITHM_VECTOR *toTest // IN: the vector of the algorithms to test 23 ) 24 { 25 TPM_ALG_ID alg; 26 // For each of the algorithms that are in the toTestVecor, need to run a 27 // test 28 for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++) 29 { 30 if(TEST_BIT(alg, *toTest)) 31 { 32 TPM_RC result = CryptTestAlgorithm(alg, toTest); 33 if(result != TPM_RC_SUCCESS) 34 return result; 35 } 36 } 37 return TPM_RC_SUCCESS; 38 } 39 // 40 // 41 // 10.4.2.2 CryptSelfTest() 42 // 43 // This function is called to start/complete a full self-test. If fullTest is NO, then only the untested algorithms 44 // will be run. If fullTest is YES, then g_untestedDecryptionAlgorithms is reinitialized and then all tests are 45 // run. This implementation of the reference design does not support processing outside the framework of a 46 // TPM command. As a consequence, this command does not complete until all tests are done. Since this 47 // can take a long time, the TPM will check after each test to see if the command is canceled. If so, then the 48 // TPM will returned TPM_RC_CANCELLED. To continue with the self-tests, call TPM2_SelfTest(fullTest == 49 // No) and the TPM will complete the testing. 50 // 51 // Error Returns Meaning 52 // 53 // TPM_RC_CANCELED if the command is canceled 54 // 55 LIB_EXPORT 56 TPM_RC 57 CryptSelfTest( 58 TPMI_YES_NO fullTest // IN: if full test is required 59 ) 60 { 61 if(g_forceFailureMode) 62 FAIL(FATAL_ERROR_FORCED); 63 // If the caller requested a full test, then reset the to test vector so that 64 // all the tests will be run 65 if(fullTest == YES) 66 { 67 MemoryCopy(g_toTest, 68 g_implementedAlgorithms, 69 sizeof(g_toTest), sizeof(g_toTest)); 70 } 71 return CryptRunSelfTests(&g_toTest); 72 } 73 // 74 // 75 // 10.4.2.3 CryptIncrementalSelfTest() 76 // 77 // This function is used to perform an incremental self-test. This implementation will perform the toTest 78 // values before returning. That is, it assumes that the TPM cannot perform background tasks between 79 // commands. 80 // This command may be canceled. If it is, then there is no return result. However, this command can be run 81 // again and the incremental progress will not be lost. 82 // 83 // Error Returns Meaning 84 // 85 // TPM_RC_CANCELED processing of this command was canceled 86 // TPM_RC_TESTING if toTest list is not empty 87 // TPM_RC_VALUE an algorithm in the toTest list is not implemented 88 // 89 TPM_RC 90 CryptIncrementalSelfTest( 91 TPML_ALG *toTest, // IN: list of algorithms to be tested 92 TPML_ALG *toDoList // OUT: list of algorithms needing test 93 ) 94 { 95 ALGORITHM_VECTOR toTestVector = {0}; 96 TPM_ALG_ID alg; 97 UINT32 i; 98 pAssert(toTest != NULL && toDoList != NULL); 99 if(toTest->count > 0) 100 { 101 // Transcribe the toTest list into the toTestVector 102 for(i = 0; i < toTest->count; i++) 103 { 104 TPM_ALG_ID alg = toTest->algorithms[i]; 105 // make sure that the algorithm value is not out of range 106 if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms)) 107 return TPM_RC_VALUE; 108 SET_BIT(alg, toTestVector); 109 } 110 // Run the test 111 if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED) 112 return TPM_RC_CANCELED; 113 } 114 // Fill in the toDoList with the algorithms that are still untested 115 toDoList->count = 0; 116 for(alg = TPM_ALG_FIRST; 117 toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST; 118 alg++) 119 { 120 if(TEST_BIT(alg, g_toTest)) 121 toDoList->algorithms[toDoList->count++] = alg; 122 } 123 return TPM_RC_SUCCESS; 124 // 125 } 126 // 127 // 128 // 10.4.2.4 CryptInitializeToTest() 129 // 130 // This function will initialize the data structures for testing all the algorithms. This should not be called 131 // unless CryptAlgsSetImplemented() has been called 132 // 133 void 134 CryptInitializeToTest( 135 void 136 ) 137 { 138 MemoryCopy(g_toTest, 139 g_implementedAlgorithms, 140 sizeof(g_toTest), 141 sizeof(g_toTest)); 142 // Setting the algorithm to null causes the test function to just clear 143 // out any algorithms for which there is no test. 144 CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest); 145 return; 146 } 147 // 148 // 149 // 10.4.2.5 CryptTestAlgorithm() 150 // 151 // Only point of contact with the actual self tests. If a self-test fails, there is no return and the TPM goes into 152 // failure mode. The call to TestAlgorithm() uses an algorithms selector and a bit vector. When the test is 153 // run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest is NULL, then only the bit in 154 // g_toTest is CLEAR. There is a special case for the call to TestAlgorithm(). When alg is 155 // TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for which it has no test. This allows the 156 // knowledge about which algorithms have test to be accessed through the interface that provides the test. 157 // 158 // Error Returns Meaning 159 // 160 // TPM_RC_SUCCESS test complete 161 // TPM_RC_CANCELED test was canceled 162 // 163 LIB_EXPORT 164 TPM_RC 165 CryptTestAlgorithm( 166 TPM_ALG_ID alg, 167 ALGORITHM_VECTOR *toTest 168 ) 169 { 170 TPM_RC result = TPM_RC_SUCCESS; 171 #ifdef SELF_TEST 172 // This is the function prototype for TestAlgorithms(). It is here and not 173 // in a _fp.h file to avoid a compiler error when SELF_TEST is not defined and 174 // AlgorithmTexts.c is not part of the build. 175 TPM_RC TestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest); 176 result = TestAlgorithm(alg, toTest); 177 #else 178 // If this is an attempt to determine the algorithms for which there is a 179 // self test, pretend that all of them do. We do that by not clearing any 180 // of the algorithm bits. When/if this function is called to run tests, it 181 // will over report. This can be changed so that any call to check on which 182 // algorithms have tests, 'toTest' can be cleared. 183 if(alg != TPM_ALG_ERROR) 184 { 185 CLEAR_BIT(alg, g_toTest); 186 if(toTest != NULL) 187 CLEAR_BIT(alg, *toTest); 188 } 189 #endif 190 return result; 191 } 192