/src/tpm2/CryptSelfTest.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
25 | 0 | TPM_ALG_ID alg; |
26 | | // For each of the algorithms that are in the toTestVecor, need to run a |
27 | | // test |
28 | 0 | for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++) |
29 | 0 | { |
30 | 0 | if(TEST_BIT(alg, *toTest)) |
31 | 0 | { |
32 | 0 | TPM_RC result = CryptTestAlgorithm(alg, toTest); |
33 | 0 | if(result != TPM_RC_SUCCESS) |
34 | 0 | return result; |
35 | 0 | } |
36 | 0 | } |
37 | 0 | return TPM_RC_SUCCESS; |
38 | 0 | } |
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 | 0 | { |
61 | 0 | if(g_forceFailureMode) |
62 | 0 | 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 | 0 | if(fullTest == YES) |
66 | 0 | { |
67 | 0 | MemoryCopy(g_toTest, |
68 | 0 | g_implementedAlgorithms, |
69 | 0 | sizeof(g_toTest), sizeof(g_toTest)); |
70 | 0 | } |
71 | 0 | return CryptRunSelfTests(&g_toTest); |
72 | 0 | } |
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 | 0 | { |
95 | 0 | ALGORITHM_VECTOR toTestVector = {0}; |
96 | 0 | TPM_ALG_ID alg; |
97 | 0 | UINT32 i; |
98 | 0 | pAssert(toTest != NULL && toDoList != NULL); |
99 | 0 | if(toTest->count > 0) |
100 | 0 | { |
101 | | // Transcribe the toTest list into the toTestVector |
102 | 0 | for(i = 0; i < toTest->count; i++) |
103 | 0 | { |
104 | 0 | TPM_ALG_ID alg = toTest->algorithms[i]; |
105 | | // make sure that the algorithm value is not out of range |
106 | 0 | if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms)) |
107 | 0 | return TPM_RC_VALUE; |
108 | 0 | SET_BIT(alg, toTestVector); |
109 | 0 | } |
110 | | // Run the test |
111 | 0 | if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED) |
112 | 0 | return TPM_RC_CANCELED; |
113 | 0 | } |
114 | | // Fill in the toDoList with the algorithms that are still untested |
115 | 0 | toDoList->count = 0; |
116 | 0 | for(alg = TPM_ALG_FIRST; |
117 | 0 | toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST; |
118 | 0 | alg++) |
119 | 0 | { |
120 | 0 | if(TEST_BIT(alg, g_toTest)) |
121 | 0 | toDoList->algorithms[toDoList->count++] = alg; |
122 | 0 | } |
123 | 0 | return TPM_RC_SUCCESS; |
124 | | // |
125 | 0 | } |
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 | 253 | { |
138 | 253 | MemoryCopy(g_toTest, |
139 | 253 | g_implementedAlgorithms, |
140 | 253 | sizeof(g_toTest), |
141 | 253 | 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 | 253 | CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest); |
145 | 253 | return; |
146 | 253 | } |
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 | 330 | { |
170 | 330 | 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 | 330 | if(alg != TPM_ALG_ERROR) |
184 | 77 | { |
185 | 77 | CLEAR_BIT(alg, g_toTest); |
186 | 77 | if(toTest != NULL) |
187 | 0 | CLEAR_BIT(alg, *toTest); |
188 | 77 | } |
189 | 330 | #endif |
190 | 330 | return result; |
191 | 330 | } |