// 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 #define MEMORY_LIB_C #include "MemoryLib_fp.h" // // These buffers are set aside to hold command and response values. In this implementation, it is not // guaranteed that the code will stop accessing the s_actionInputBuffer before starting to put values in the // s_actionOutputBuffer so different buffers are required. However, the s_actionInputBuffer and // s_responseBuffer are not needed at the same time and they could be the same buffer. // // Functions on BYTE Arrays // // MemoryMove() // // This function moves data from one place in memory to another. No safety checks of any type are // performed. If source and data buffer overlap, then the move is done as if an intermediate buffer were // used. // // NOTE: This function is used by MemoryCopy(), MemoryCopy2B(), and MemoryConcat2b() and requires that the caller // know the maximum size of the destination buffer so that there is no possibility of buffer overrun. // LIB_EXPORT void MemoryMove( void *destination, // OUT: move destination const void *source, // IN: move source UINT32 size, // IN: number of octets to moved UINT32 dSize // IN: size of the receive buffer ) { const BYTE *p = (BYTE *)source; BYTE *q = (BYTE *)destination; if(destination == NULL || source == NULL) return; pAssert(size <= dSize); // if the destination buffer has a lower address than the // source, then moving bytes in ascending order is safe. dSize -= size; if (p>q || (p+size <= q)) { while(size--) *q++ = *p++; } // If the destination buffer has a higher address than the // source, then move bytes from the end to the beginning. else if (p < q) { p += size; q += size; // while (size--) *--q = *--p; } // If the source and destination address are the same, nothing to move. return; } // // MemoryEqual() // // This function indicates if two buffers have the same values in the indicated number of bytes. // // Return Value Meaning // // TRUE all octets are the same // FALSE all octets are not the same // LIB_EXPORT BOOL MemoryEqual( const void *buffer1, // IN: compare buffer1 const void *buffer2, // IN: compare buffer2 UINT32 size // IN: size of bytes being compared ) { BOOL diff = FALSE; const BYTE *b1, *b2; b1 = (BYTE *)buffer1; b2 = (BYTE *)buffer2; // Compare all bytes so that there is no leakage of information // due to timing differences. for(; size > 0; size--) diff |= *b1++ ^ *b2++; return !diff; } // // // MemoryCopy2B() // // This function copies a TPM2B. This can be used when the TPM2B types are the same or different. No // size checking is done on the destination so the caller should make sure that the destination is large // enough. // // This function returns the number of octets in the data buffer of the TPM2B. // LIB_EXPORT INT16 MemoryCopy2B( TPM2B *dest, // OUT: receiving TPM2B const TPM2B *source, // IN: source TPM2B UINT16 dSize // IN: size of the receiving buffer ) { if(dest == NULL) return 0; if(source == NULL) dest->size = 0; else { dest->size = source->size; MemoryMove(dest->buffer, source->buffer, dest->size, dSize); } return dest->size; } // // // MemoryConcat2B() // // This function will concatenate the buffer contents of a TPM2B to an the buffer contents of another TPM2B // and adjust the size accordingly (a := (a | b)). // LIB_EXPORT void MemoryConcat2B( TPM2B *aInOut, // IN/OUT: destination 2B TPM2B *bIn, // IN: second 2B UINT16 aSize // IN: The size of aInOut.buffer (max values for // aInOut.size) ) { MemoryMove(&aInOut->buffer[aInOut->size], bIn->buffer, bIn->size, aSize - aInOut->size); aInOut->size = aInOut->size + bIn->size; return; } // // // Memory2BEqual() // // This function will compare two TPM2B structures. To be equal, they need to be the same size and the // buffer contexts need to be the same in all octets. // // Return Value Meaning // // TRUE size and buffer contents are the same // FALSE size or buffer contents are not the same // LIB_EXPORT BOOL Memory2BEqual( const TPM2B *aIn, // IN: compare value const TPM2B *bIn // IN: compare value ) { if(aIn->size != bIn->size) return FALSE; return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size); } // // // MemorySet() // // This function will set all the octets in the specified memory range to the specified octet value. // // NOTE: the dSize parameter forces the caller to know how big the receiving buffer is to make sure that there is no // possibility that the caller will inadvertently run over the end of the buffer. // LIB_EXPORT void MemorySet( void *destination, // OUT: memory destination char value, // IN: fill value UINT32 size // IN: number of octets to fill ) { char *p = (char *)destination; while (size--) *p++ = value; return; } #ifndef EMBEDDED_MODE // // // MemoryGetActionInputBuffer() // // This function returns the address of the buffer into which the command parameters will be unmarshaled in // preparation for calling the command actions. // BYTE * MemoryGetActionInputBuffer( UINT32 size // Size, in bytes, required for the input // unmarshaling ) { BYTE *buf = NULL; if(size > 0) { // In this implementation, a static buffer is set aside for action output. // Other implementations may apply additional optimization based on command // code or other factors. UINT32 *p = s_actionInputBuffer; buf = (BYTE *)p; pAssert(size < sizeof(s_actionInputBuffer)); // size of an element in the buffer #define SZ sizeof(s_actionInputBuffer[0]) for(size = (size + SZ - 1) / SZ; size > 0; size--) *p++ = 0; #undef SZ } return buf; } // // // MemoryGetActionOutputBuffer() // // This function returns the address of the buffer into which the command action code places its output // values. // void * MemoryGetActionOutputBuffer( TPM_CC command // Command that requires the buffer ) { // In this implementation, a static buffer is set aside for action output. // Other implementations may apply additional optimization based on the command // code or other factors. command = 0; // Unreferenced parameter return s_actionOutputBuffer; } #endif // EMBEDDED_MODE ^^^^^ not defined. // // // MemoryGetResponseBuffer() // // This function returns the address into which the command response is marshaled from values in the // action output buffer. // BYTE* MemoryGetResponseBuffer( TPM_CC command // Command that requires the buffer ) { // In this implementation, a static buffer is set aside for responses. // Other implementation may apply additional optimization based on the command // code or other factors. command = 0; // Unreferenced parameter return s_responseBuffer; } // // // MemoryRemoveTrailingZeros() // // This function is used to adjust the length of an authorization value. It adjusts the size of the TPM2B so // that it does not include octets at the end of the buffer that contain zero. The function returns the number // of non-zero octets in the buffer. // UINT16 MemoryRemoveTrailingZeros ( TPM2B_AUTH *auth // IN/OUT: value to adjust ) { BYTE *a = &auth->t.buffer[auth->t.size-1]; for(; auth->t.size > 0; auth->t.size--) { if(*a--) break; } return auth->t.size; }