Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 9 | #include "MemoryLib_fp.h" |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | // |
| 27 | LIB_EXPORT void |
| 28 | MemoryMove( |
| 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 | // |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | // |
| 71 | LIB_EXPORT BOOL |
| 72 | MemoryEqual( |
| 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 | { |
nagendra modadugu | e760ff5 | 2017-05-11 15:17:16 -0700 | [diff] [blame] | 78 | BOOL diff = FALSE; |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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--) |
nagendra modadugu | e760ff5 | 2017-05-11 15:17:16 -0700 | [diff] [blame] | 85 | diff |= *b1++ ^ *b2++; |
| 86 | return !diff; |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | // |
| 98 | LIB_EXPORT INT16 |
| 99 | MemoryCopy2B( |
| 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 | // |
| 123 | LIB_EXPORT void |
| 124 | MemoryConcat2B( |
| 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 | // |
| 150 | LIB_EXPORT BOOL |
| 151 | Memory2BEqual( |
| 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 | // |
| 169 | LIB_EXPORT void |
| 170 | MemorySet( |
| 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 | } |
Vadim Bendebury | 7878aef | 2015-08-12 12:57:26 -0700 | [diff] [blame] | 181 | #ifndef EMBEDDED_MODE |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | // |
| 189 | BYTE * |
| 190 | MemoryGetActionInputBuffer( |
| 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 | // |
| 219 | void * |
| 220 | MemoryGetActionOutputBuffer( |
| 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 | } |
Vadim Bendebury | 7878aef | 2015-08-12 12:57:26 -0700 | [diff] [blame] | 230 | #endif // EMBEDDED_MODE ^^^^^ not defined. |
| 231 | |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 | // |
Jocelyn Bohr | a4ed3aa | 2015-07-30 10:44:16 -0700 | [diff] [blame] | 239 | BYTE* |
Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 240 | MemoryGetResponseBuffer( |
| 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 | // |
| 258 | UINT16 |
| 259 | MemoryRemoveTrailingZeros ( |
| 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 | } |