Home | History | Annotate | Download | only in tpm2
      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