aboutsummaryrefslogtreecommitdiff
path: root/MemoryLib.c
blob: 178848e7d82dc10f4015c6f778f9a9762fbfcdc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
// 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;
}