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#define MEMORY_LIB_C
9#include "MemoryLib_fp.h"
10//
11//     These buffers are set aside to hold command and response values. In this implementation, it is not
12//     guaranteed that the code will stop accessing the s_actionInputBuffer before starting to put values in the
13//     s_actionOutputBuffer so different buffers are required. However, the s_actionInputBuffer and
14//     s_responseBuffer are not needed at the same time and they could be the same buffer.
15//
16//          Functions on BYTE Arrays
17//
18//          MemoryMove()
19//
20//     This function moves data from one place in memory to another. No safety checks of any type are
21//     performed. If source and data buffer overlap, then the move is done as if an intermediate buffer were
22//     used.
23//
24//     NOTE:           This function is used by MemoryCopy(), MemoryCopy2B(), and MemoryConcat2b() and requires that the caller
25//                     know the maximum size of the destination buffer so that there is no possibility of buffer overrun.
26//
27LIB_EXPORT void
28MemoryMove(
29      void              *destination,          //   OUT: move destination
30      const void        *source,               //   IN: move source
31      UINT32             size,                 //   IN: number of octets to moved
32      UINT32             dSize                 //   IN: size of the receive buffer
33      )
34{
35      const BYTE *p = (BYTE *)source;
36      BYTE *q = (BYTE *)destination;
37      if(destination == NULL || source == NULL)
38          return;
39      pAssert(size <= dSize);
40      // if the destination buffer has a lower address than the
41      // source, then moving bytes in ascending order is safe.
42      dSize -= size;
43      if (p>q || (p+size <= q))
44      {
45          while(size--)
46              *q++ = *p++;
47      }
48      // If the destination buffer has a higher address than the
49      // source, then move bytes from the end to the beginning.
50      else if (p < q)
51      {
52          p += size;
53          q += size;
54//
55          while (size--)
56              *--q = *--p;
57      }
58      // If the source and destination address are the same, nothing to move.
59      return;
60}
61//
62//         MemoryEqual()
63//
64//     This function indicates if two buffers have the same values in the indicated number of bytes.
65//
66//     Return Value                     Meaning
67//
68//     TRUE                             all octets are the same
69//     FALSE                            all octets are not the same
70//
71LIB_EXPORT BOOL
72MemoryEqual(
73      const void       *buffer1,             // IN: compare buffer1
74      const void       *buffer2,             // IN: compare buffer2
75      UINT32            size                 // IN: size of bytes being compared
76      )
77{
78      BOOL          equal = TRUE;
79      const BYTE   *b1, *b2;
80      b1 = (BYTE *)buffer1;
81      b2 = (BYTE *)buffer2;
82      // Compare all bytes so that there is no leakage of information
83      // due to timing differences.
84      for(; size > 0; size--)
85          equal = (*b1++ == *b2++) && equal;
86      return equal;
87}
88//
89//
90//         MemoryCopy2B()
91//
92//     This function copies a TPM2B. This can be used when the TPM2B types are the same or different. No
93//     size checking is done on the destination so the caller should make sure that the destination is large
94//     enough.
95//
96//      This function returns the number of octets in the data buffer of the TPM2B.
97//
98LIB_EXPORT INT16
99MemoryCopy2B(
100   TPM2B               *dest,                // OUT: receiving TPM2B
101   const TPM2B         *source,              // IN: source TPM2B
102   UINT16               dSize                // IN: size of the receiving buffer
103   )
104{
105   if(dest == NULL)
106       return 0;
107   if(source == NULL)
108       dest->size = 0;
109   else
110   {
111       dest->size = source->size;
112       MemoryMove(dest->buffer, source->buffer, dest->size, dSize);
113   }
114   return dest->size;
115}
116//
117//
118//          MemoryConcat2B()
119//
120//      This function will concatenate the buffer contents of a TPM2B to an the buffer contents of another TPM2B
121//      and adjust the size accordingly (a := (a | b)).
122//
123LIB_EXPORT void
124MemoryConcat2B(
125   TPM2B               *aInOut,              // IN/OUT: destination 2B
126   TPM2B               *bIn,                 // IN: second 2B
127   UINT16               aSize                // IN: The size of aInOut.buffer (max values for
128                                             //     aInOut.size)
129   )
130{
131   MemoryMove(&aInOut->buffer[aInOut->size],
132              bIn->buffer,
133              bIn->size,
134              aSize - aInOut->size);
135   aInOut->size = aInOut->size + bIn->size;
136   return;
137}
138//
139//
140//          Memory2BEqual()
141//
142//      This function will compare two TPM2B structures. To be equal, they need to be the same size and the
143//      buffer contexts need to be the same in all octets.
144//
145//      Return Value                      Meaning
146//
147//      TRUE                              size and buffer contents are the same
148//      FALSE                             size or buffer contents are not the same
149//
150LIB_EXPORT BOOL
151Memory2BEqual(
152   const TPM2B         *aIn,                 // IN: compare value
153   const TPM2B         *bIn                  // IN: compare value
154   )
155{
156   if(aIn->size != bIn->size)
157       return FALSE;
158    return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size);
159}
160//
161//
162//          MemorySet()
163//
164//      This function will set all the octets in the specified memory range to the specified octet value.
165//
166//      NOTE:            the dSize parameter forces the caller to know how big the receiving buffer is to make sure that there is no
167//                       possibility that the caller will inadvertently run over the end of the buffer.
168//
169LIB_EXPORT void
170MemorySet(
171    void                 *destination,           // OUT: memory destination
172    char                  value,                 // IN: fill value
173    UINT32                size                   // IN: number of octets to fill
174    )
175{
176    char *p = (char *)destination;
177    while (size--)
178        *p++ = value;
179    return;
180}
181#ifndef EMBEDDED_MODE
182//
183//
184//          MemoryGetActionInputBuffer()
185//
186//      This function returns the address of the buffer into which the command parameters will be unmarshaled in
187//      preparation for calling the command actions.
188//
189BYTE *
190MemoryGetActionInputBuffer(
191    UINT32                 size                  // Size, in bytes, required for the input
192                                                 // unmarshaling
193    )
194{
195    BYTE           *buf = NULL;
196    if(size > 0)
197    {
198        // In this implementation, a static buffer is set aside for action output.
199        // Other implementations may apply additional optimization based on command
200        // code or other factors.
201        UINT32      *p = s_actionInputBuffer;
202        buf = (BYTE *)p;
203        pAssert(size < sizeof(s_actionInputBuffer));
204       // size of an element in the buffer
205#define SZ      sizeof(s_actionInputBuffer[0])
206       for(size = (size + SZ - 1) / SZ; size > 0; size--)
207           *p++ = 0;
208#undef SZ
209   }
210   return buf;
211}
212//
213//
214//          MemoryGetActionOutputBuffer()
215//
216//      This function returns the address of the buffer into which the command action code places its output
217//      values.
218//
219void *
220MemoryGetActionOutputBuffer(
221      TPM_CC             command            // Command that requires the buffer
222      )
223{
224      // In this implementation, a static buffer is set aside for action output.
225      // Other implementations may apply additional optimization based on the command
226      // code or other factors.
227      command = 0;        // Unreferenced parameter
228      return s_actionOutputBuffer;
229}
230#endif // EMBEDDED_MODE  ^^^^^ not defined.
231
232//
233//
234//       MemoryGetResponseBuffer()
235//
236//      This function returns the address into which the command response is marshaled from values in the
237//      action output buffer.
238//
239BYTE*
240MemoryGetResponseBuffer(
241      TPM_CC             command            // Command that requires the buffer
242      )
243{
244      // In this implementation, a static buffer is set aside for responses.
245      // Other implementation may apply additional optimization based on the command
246      // code or other factors.
247      command = 0;        // Unreferenced parameter
248      return s_responseBuffer;
249}
250//
251//
252//       MemoryRemoveTrailingZeros()
253//
254//      This function is used to adjust the length of an authorization value. It adjusts the size of the TPM2B so
255//      that it does not include octets at the end of the buffer that contain zero. The function returns the number
256//      of non-zero octets in the buffer.
257//
258UINT16
259MemoryRemoveTrailingZeros (
260      TPM2B_AUTH        *auth               // IN/OUT: value to adjust
261      )
262{
263      BYTE         *a = &auth->t.buffer[auth->t.size-1];
264      for(; auth->t.size > 0; auth->t.size--)
265      {
266          if(*a--)
267              break;
268      }
269      return auth->t.size;
270}
271