C++程序  |  297行  |  7.74 KB

// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 4: Supporting Routines
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include     <memory.h>
#include     <stdio.h>
#include     <string.h>

#include     "PlatformData.h"
#include     "TpmError.h"
#include     "assert.h"

#ifndef EMBEDDED_MODE
#define FILE_BACKED_NV
#endif

#if defined FILE_BACKED_NV
static   FILE*                  s_NVFile;
#endif
static   unsigned char          s_NV[NV_MEMORY_SIZE];
static   BOOL                   s_NvIsAvailable;
static   BOOL                   s_NV_unrecoverable;
static   BOOL                   s_NV_recoverable;
//
//
//          Functions
//
//          _plat__NvErrors()
//
//     This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the
//     NV loading process
//
LIB_EXPORT void
_plat__NvErrors(
     BOOL                 recoverable,
     BOOL                 unrecoverable
     )
{
     s_NV_unrecoverable = unrecoverable;
     s_NV_recoverable = recoverable;
}
//
//
//          _plat__NVEnable()
//
//     Enable NV memory.
//     This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the
//     integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV
//     state would be read in, decrypted and integrity checked.
//     The recovery from an integrity failure depends on where the error occurred. It it was in the state that is
//     discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go
//     into failure mode.
//
//     Return Value                      Meaning
//
//     0                                 if success
//     >0                                if receive recoverable error
//     <0                                if unrecoverable error
//
LIB_EXPORT int
_plat__NVEnable(
     void                *platParameter       // IN: platform specific parameter
     )
{
     // Start assuming everything is OK
   s_NV_unrecoverable = FALSE;
   s_NV_recoverable = FALSE;
#ifdef FILE_BACKED_NV
   if(s_NVFile != NULL) return 0;
   // Try to open an exist NVChip file for read/write
   s_NVFile = fopen("NVChip", "r+b");
   if(NULL != s_NVFile)
   {
       // See if the NVChip file is empty
       fseek(s_NVFile, 0, SEEK_END);
       if(0 == ftell(s_NVFile))
           s_NVFile = NULL;
   }
   if(s_NVFile == NULL)
   {
       // Initialize all the byte in the new file to 0
       memset(s_NV, 0, NV_MEMORY_SIZE);
          // If NVChip file does not exist, try to create it for read/write
          s_NVFile = fopen("NVChip", "w+b");
          // Start initialize at the end of new file
          fseek(s_NVFile, 0, SEEK_END);
          // Write 0s to NVChip file
          fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
   }
   else
   {
       // If NVChip file exist, assume the size is correct
       fseek(s_NVFile, 0, SEEK_END);
       assert(ftell(s_NVFile) == NV_MEMORY_SIZE);
       // read NV file data to memory
       fseek(s_NVFile, 0, SEEK_SET);
       assert(1 == fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile));
   }
#endif
   // NV contents have been read and the error checks have been performed. For
   // simulation purposes, use the signaling interface to indicate if an error is
   // to be simulated and the type of the error.
   if(s_NV_unrecoverable)
       return -1;
   return s_NV_recoverable;
}
//
//
//         _plat__NVDisable()
//
//     Disable NV memory
//
LIB_EXPORT void
_plat__NVDisable(
   void
   )
{
#ifdef     FILE_BACKED_NV
   assert(s_NVFile != NULL);
   // Close NV file
   fclose(s_NVFile);
   // Set file handle to NULL
//
    s_NVFile = NULL;
#endif
    return;
}
//
//
//          _plat__IsNvAvailable()
//
//      Check if NV is available
//
//      Return Value                      Meaning
//
//      0                                 NV is available
//      1                                 NV is not available due to write failure
//      2                                 NV is not available due to rate limit
//
LIB_EXPORT int
_plat__IsNvAvailable(
    void
    )
{
    // NV is not available if the TPM is in failure mode
    if(!s_NvIsAvailable)
        return 1;
#ifdef FILE_BACKED_NV
   if(s_NVFile == NULL)
       return 1;
#endif
    return 0;
}
//
//
//          _plat__NvMemoryRead()
//
//      Function: Read a chunk of NV memory
//
LIB_EXPORT void
_plat__NvMemoryRead(
    unsigned int           startOffset,       // IN: read start
    unsigned int           size,              // IN: size of bytes to read
    void                  *data               // OUT: data buffer
    )
{
    assert(startOffset + size <= NV_MEMORY_SIZE);
    // Copy data from RAM
    memcpy(data, &s_NV[startOffset], size);
    return;
}
//
//
//          _plat__NvIsDifferent()
//
//      This function checks to see if the NV is different from the test value. This is so that NV will not be written if
//      it has not changed.
//
//
//
//
//      Return Value                  Meaning
//
//      TRUE                          the NV location is different from the test value
//      FALSE                         the NV location is the same as the test value
//
LIB_EXPORT BOOL
_plat__NvIsDifferent(
   unsigned int        startOffset,       // IN: read start
   unsigned int        size,              // IN: size of bytes to read
   void               *data               // IN: data buffer
   )
{
   return (memcmp(&s_NV[startOffset], data, size) != 0);
}
//
//
//         _plat__NvMemoryWrite()
//
//      This function is used to update NV memory. The write is to a memory copy of NV. At the end of the
//      current command, any changes are written to the actual NV memory.
//
LIB_EXPORT void
_plat__NvMemoryWrite(
   unsigned int        startOffset,       // IN: write start
   unsigned int        size,              // IN: size of bytes to write
   void               *data               // OUT: data buffer
   )
{
   assert(startOffset + size <= NV_MEMORY_SIZE);
   // Copy the data to the NV image
   memcpy(&s_NV[startOffset], data, size);
}
//
//
//         _plat__NvMemoryMove()
//
//      Function: Move a chunk of NV memory from source to destination This function should ensure that if
//      there overlap, the original data is copied before it is written
//
LIB_EXPORT void
_plat__NvMemoryMove(
   unsigned int        sourceOffset,      // IN: source offset
   unsigned int        destOffset,        // IN: destination offset
   unsigned int        size               // IN: size of data being moved
   )
{
   assert(sourceOffset + size <= NV_MEMORY_SIZE);
   assert(destOffset + size <= NV_MEMORY_SIZE);
   // Move data in RAM
   memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
   return;
}
//
//
//         _plat__NvCommit()
//
//      Update NV chip
//
//
//
//      Return Value                      Meaning
//
//      0                                 NV write success
//      non-0                             NV write fail
//
LIB_EXPORT int
_plat__NvCommit(
   void
   )
{
#ifdef FILE_BACKED_NV
   // If NV file is not available, return failure
   if(s_NVFile == NULL)
       return 1;
   // Write RAM data to NV
   fseek(s_NVFile, 0, SEEK_SET);
   fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
   return 0;
#else
   return 0;
#endif
}
//
//
//       _plat__SetNvAvail()
//
//      Set the current NV state to available. This function is for testing purpose only. It is not part of the
//      platform NV logic
//
LIB_EXPORT void
_plat__SetNvAvail(
   void
   )
{
   s_NvIsAvailable = TRUE;
   return;
}
//
//
//       _plat__ClearNvAvail()
//
//      Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the
//      platform NV logic
//
LIB_EXPORT void
_plat__ClearNvAvail(
   void
   )
{
   s_NvIsAvailable = FALSE;
   return;
}