Coverage Report

Created: 2025-07-18 06:04

/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
}