blob: 730e4d3024d5ab3ed33582daaa708bdcfb2e67b5 [file] [log] [blame]
// 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 "InternalRoutines.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;
}
//
//
// MemoryCopy()
//
// This function moves data from one place in memory to another. No safety checks of any type are
// performed. If the destination and source overlap, then the results are unpredictable. void MemoryCopy(
//
void *destination, // OUT: copy destination
//
void *source, // IN: copy source
UINT32 size, // IN: number of octets being copied
UINT32 dSize // IN: size of the receive buffer
//
// MemoryMove(destination, source, size, dSize);
//
//%#define MemoryCopy(destination, source, size, destSize) \
//% MemoryMove((destination), (source), (size), (destSize))
//
//
// 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 equal = TRUE;
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--)
equal = (*b1++ == *b2++) && equal;
return equal;
}
//
//
// 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;
}
//
//
// 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;
}
//
//
// 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;
}