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     <memory.h>
      9 #include     <stdio.h>
     10 #include     <string.h>
     11 
     12 #include     "PlatformData.h"
     13 #include     "TpmError.h"
     14 #include     "assert.h"
     15 
     16 #ifndef EMBEDDED_MODE
     17 #define FILE_BACKED_NV
     18 #endif
     19 
     20 #if defined FILE_BACKED_NV
     21 static   FILE*                  s_NVFile;
     22 #endif
     23 static   unsigned char          s_NV[NV_MEMORY_SIZE];
     24 static   BOOL                   s_NvIsAvailable;
     25 static   BOOL                   s_NV_unrecoverable;
     26 static   BOOL                   s_NV_recoverable;
     27 //
     28 //
     29 //          Functions
     30 //
     31 //          _plat__NvErrors()
     32 //
     33 //     This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the
     34 //     NV loading process
     35 //
     36 LIB_EXPORT void
     37 _plat__NvErrors(
     38      BOOL                 recoverable,
     39      BOOL                 unrecoverable
     40      )
     41 {
     42      s_NV_unrecoverable = unrecoverable;
     43      s_NV_recoverable = recoverable;
     44 }
     45 //
     46 //
     47 //          _plat__NVEnable()
     48 //
     49 //     Enable NV memory.
     50 //     This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the
     51 //     integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV
     52 //     state would be read in, decrypted and integrity checked.
     53 //     The recovery from an integrity failure depends on where the error occurred. It it was in the state that is
     54 //     discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go
     55 //     into failure mode.
     56 //
     57 //     Return Value                      Meaning
     58 //
     59 //     0                                 if success
     60 //     >0                                if receive recoverable error
     61 //     <0                                if unrecoverable error
     62 //
     63 LIB_EXPORT int
     64 _plat__NVEnable(
     65      void                *platParameter       // IN: platform specific parameter
     66      )
     67 {
     68      // Start assuming everything is OK
     69    s_NV_unrecoverable = FALSE;
     70    s_NV_recoverable = FALSE;
     71 #ifdef FILE_BACKED_NV
     72    if(s_NVFile != NULL) return 0;
     73    // Try to open an exist NVChip file for read/write
     74    s_NVFile = fopen("NVChip", "r+b");
     75    if(NULL != s_NVFile)
     76    {
     77        // See if the NVChip file is empty
     78        fseek(s_NVFile, 0, SEEK_END);
     79        if(0 == ftell(s_NVFile))
     80            s_NVFile = NULL;
     81    }
     82    if(s_NVFile == NULL)
     83    {
     84        // Initialize all the byte in the new file to 0
     85        memset(s_NV, 0, NV_MEMORY_SIZE);
     86           // If NVChip file does not exist, try to create it for read/write
     87           s_NVFile = fopen("NVChip", "w+b");
     88           // Start initialize at the end of new file
     89           fseek(s_NVFile, 0, SEEK_END);
     90           // Write 0s to NVChip file
     91           fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
     92    }
     93    else
     94    {
     95        // If NVChip file exist, assume the size is correct
     96        fseek(s_NVFile, 0, SEEK_END);
     97        assert(ftell(s_NVFile) == NV_MEMORY_SIZE);
     98        // read NV file data to memory
     99        fseek(s_NVFile, 0, SEEK_SET);
    100        assert(1 == fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile));
    101    }
    102 #endif
    103    // NV contents have been read and the error checks have been performed. For
    104    // simulation purposes, use the signaling interface to indicate if an error is
    105    // to be simulated and the type of the error.
    106    if(s_NV_unrecoverable)
    107        return -1;
    108    return s_NV_recoverable;
    109 }
    110 //
    111 //
    112 //         _plat__NVDisable()
    113 //
    114 //     Disable NV memory
    115 //
    116 LIB_EXPORT void
    117 _plat__NVDisable(
    118    void
    119    )
    120 {
    121 #ifdef     FILE_BACKED_NV
    122    assert(s_NVFile != NULL);
    123    // Close NV file
    124    fclose(s_NVFile);
    125    // Set file handle to NULL
    126 //
    127     s_NVFile = NULL;
    128 #endif
    129     return;
    130 }
    131 //
    132 //
    133 //          _plat__IsNvAvailable()
    134 //
    135 //      Check if NV is available
    136 //
    137 //      Return Value                      Meaning
    138 //
    139 //      0                                 NV is available
    140 //      1                                 NV is not available due to write failure
    141 //      2                                 NV is not available due to rate limit
    142 //
    143 LIB_EXPORT int
    144 _plat__IsNvAvailable(
    145     void
    146     )
    147 {
    148     // NV is not available if the TPM is in failure mode
    149     if(!s_NvIsAvailable)
    150         return 1;
    151 #ifdef FILE_BACKED_NV
    152    if(s_NVFile == NULL)
    153        return 1;
    154 #endif
    155     return 0;
    156 }
    157 //
    158 //
    159 //          _plat__NvMemoryRead()
    160 //
    161 //      Function: Read a chunk of NV memory
    162 //
    163 LIB_EXPORT void
    164 _plat__NvMemoryRead(
    165     unsigned int           startOffset,       // IN: read start
    166     unsigned int           size,              // IN: size of bytes to read
    167     void                  *data               // OUT: data buffer
    168     )
    169 {
    170     assert(startOffset + size <= NV_MEMORY_SIZE);
    171     // Copy data from RAM
    172     memcpy(data, &s_NV[startOffset], size);
    173     return;
    174 }
    175 //
    176 //
    177 //          _plat__NvIsDifferent()
    178 //
    179 //      This function checks to see if the NV is different from the test value. This is so that NV will not be written if
    180 //      it has not changed.
    181 //
    182 //
    183 //
    184 //
    185 //      Return Value                  Meaning
    186 //
    187 //      TRUE                          the NV location is different from the test value
    188 //      FALSE                         the NV location is the same as the test value
    189 //
    190 LIB_EXPORT BOOL
    191 _plat__NvIsDifferent(
    192    unsigned int        startOffset,       // IN: read start
    193    unsigned int        size,              // IN: size of bytes to read
    194    void               *data               // IN: data buffer
    195    )
    196 {
    197    return (memcmp(&s_NV[startOffset], data, size) != 0);
    198 }
    199 //
    200 //
    201 //         _plat__NvMemoryWrite()
    202 //
    203 //      This function is used to update NV memory. The write is to a memory copy of NV. At the end of the
    204 //      current command, any changes are written to the actual NV memory.
    205 //
    206 LIB_EXPORT void
    207 _plat__NvMemoryWrite(
    208    unsigned int        startOffset,       // IN: write start
    209    unsigned int        size,              // IN: size of bytes to write
    210    void               *data               // OUT: data buffer
    211    )
    212 {
    213    assert(startOffset + size <= NV_MEMORY_SIZE);
    214    // Copy the data to the NV image
    215    memcpy(&s_NV[startOffset], data, size);
    216 }
    217 //
    218 //
    219 //         _plat__NvMemoryMove()
    220 //
    221 //      Function: Move a chunk of NV memory from source to destination This function should ensure that if
    222 //      there overlap, the original data is copied before it is written
    223 //
    224 LIB_EXPORT void
    225 _plat__NvMemoryMove(
    226    unsigned int        sourceOffset,      // IN: source offset
    227    unsigned int        destOffset,        // IN: destination offset
    228    unsigned int        size               // IN: size of data being moved
    229    )
    230 {
    231    assert(sourceOffset + size <= NV_MEMORY_SIZE);
    232    assert(destOffset + size <= NV_MEMORY_SIZE);
    233    // Move data in RAM
    234    memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
    235    return;
    236 }
    237 //
    238 //
    239 //         _plat__NvCommit()
    240 //
    241 //      Update NV chip
    242 //
    243 //
    244 //
    245 //      Return Value                      Meaning
    246 //
    247 //      0                                 NV write success
    248 //      non-0                             NV write fail
    249 //
    250 LIB_EXPORT int
    251 _plat__NvCommit(
    252    void
    253    )
    254 {
    255 #ifdef FILE_BACKED_NV
    256    // If NV file is not available, return failure
    257    if(s_NVFile == NULL)
    258        return 1;
    259    // Write RAM data to NV
    260    fseek(s_NVFile, 0, SEEK_SET);
    261    fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
    262    return 0;
    263 #else
    264    return 0;
    265 #endif
    266 }
    267 //
    268 //
    269 //       _plat__SetNvAvail()
    270 //
    271 //      Set the current NV state to available. This function is for testing purpose only. It is not part of the
    272 //      platform NV logic
    273 //
    274 LIB_EXPORT void
    275 _plat__SetNvAvail(
    276    void
    277    )
    278 {
    279    s_NvIsAvailable = TRUE;
    280    return;
    281 }
    282 //
    283 //
    284 //       _plat__ClearNvAvail()
    285 //
    286 //      Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the
    287 //      platform NV logic
    288 //
    289 LIB_EXPORT void
    290 _plat__ClearNvAvail(
    291    void
    292    )
    293 {
    294    s_NvIsAvailable = FALSE;
    295    return;
    296 }
    297