Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | } |