1 /********************************************************************************/
2 /* */
3 /* TSS and Application Utilities */
4 /* Written by Ken Goldman */
5 /* IBM Thomas J. Watson Research Center */
6 /* $Id: tssutils.c 1294 2018-08-09 19:08:34Z kgoldman $ */
7 /* */
8 /* (c) Copyright IBM Corporation 2015 - 2018 */
9 /* */
10 /* All rights reserved. */
11 /* */
12 /* Redistribution and use in source and binary forms, with or without */
13 /* modification, are permitted provided that the following conditions are */
14 /* met: */
15 /* */
16 /* Redistributions of source code must retain the above copyright notice, */
17 /* this list of conditions and the following disclaimer. */
18 /* */
19 /* Redistributions in binary form must reproduce the above copyright */
20 /* notice, this list of conditions and the following disclaimer in the */
21 /* documentation and/or other materials provided with the distribution. */
22 /* */
23 /* Neither the names of the IBM Corporation nor the names of its */
24 /* contributors may be used to endorse or promote products derived from */
25 /* this software without specific prior written permission. */
26 /* */
27 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
28 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
29 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
30 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
31 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
32 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
33 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
34 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
35 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
36 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
37 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
38 /********************************************************************************/
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <errno.h>
44
45 #ifdef TPM_POSIX
46 #include <netinet/in.h>
47 #endif
48 #ifdef TPM_WINDOWS
49 #include <winsock2.h>
50 #endif
51
52 #include <ibmtss/tssutils.h>
53 #include <ibmtss/tssresponsecode.h>
54 #include <ibmtss/tsserror.h>
55 #include <ibmtss/tssprint.h>
56
57 /* the TSS context must be larger when files are not used, since TSS object and NV state is held in
58 the volatile context. The major factor is the number of TSS_OBJECT_PUBLIC slots. See
59 tssproperties.c */
60 #ifdef TPM_TSS_NOFILE
61 #define TSS_ALLOC_MAX 0x12000 /* 73k bytes */
62 #else
63 #define TSS_ALLOC_MAX 0x10000 /* 64k bytes */
64 #endif
65
66 extern int tssVerbose;
67 extern int tssVverbose;
68
69 /* TSS_Malloc() is a general purpose wrapper around malloc()
70 */
71
TSS_Malloc(unsigned char ** buffer,uint32_t size)72 TPM_RC TSS_Malloc(unsigned char **buffer, uint32_t size)
73 {
74 TPM_RC rc = 0;
75
76 /* assertion test. The coding style requires that all allocated pointers are initialized to
77 NULL. A non-NULL value indicates either a missing initialization or a pointer reuse (a
78 memory leak). */
79 if (rc == 0) {
80 if (*buffer != NULL) {
81 if (tssVerbose)
82 printf("TSS_Malloc: Error (fatal), *buffer %p should be NULL before malloc\n",
83 *buffer);
84 rc = TSS_RC_ALLOC_INPUT;
85 }
86 }
87 /* verify that the size is not "too large" */
88 if (rc == 0) {
89 if (size > TSS_ALLOC_MAX) {
90 if (tssVerbose) printf("TSS_Malloc: Error, size %u greater than maximum allowed\n",
91 size);
92 rc = TSS_RC_MALLOC_SIZE;
93 }
94 }
95 /* verify that the size is not 0, this would be implementation defined and should never occur */
96 if (rc == 0) {
97 if (size == 0) {
98 if (tssVerbose) printf("TSS_Malloc: Error (fatal), size is zero\n");
99 rc = TSS_RC_MALLOC_SIZE;
100 }
101 }
102 if (rc == 0) {
103 *buffer = malloc(size);
104 if (*buffer == NULL) {
105 if (tssVerbose) printf("TSS_Malloc: Error allocating %u bytes\n", size);
106 rc = TSS_RC_OUT_OF_MEMORY;
107 }
108 }
109 return rc;
110 }
111
TSS_Realloc(unsigned char ** buffer,uint32_t size)112 TPM_RC TSS_Realloc(unsigned char **buffer, uint32_t size)
113 {
114 TPM_RC rc = 0;
115 unsigned char *tmpptr = NULL;
116
117 /* verify that the size is not "too large" */
118 if (rc == 0) {
119 if (size > TSS_ALLOC_MAX) {
120 if (tssVerbose) printf("TSS_Realloc: Error, size %u greater than maximum allowed\n",
121 size);
122 rc = TSS_RC_MALLOC_SIZE;
123 }
124 }
125 /* verify that the size is not 0, this should never occur */
126 if (rc == 0) {
127 if (size == 0) {
128 if (tssVerbose) printf("TSS_Malloc: Error (fatal), size is zero\n");
129 rc = TSS_RC_MALLOC_SIZE;
130 }
131 }
132 if (rc == 0) {
133 tmpptr = realloc(*buffer, size);
134 if (tmpptr == NULL) {
135 if (tssVerbose) printf("TSS_Realloc: Error reallocating %u bytes\n", size);
136 rc = TSS_RC_OUT_OF_MEMORY;
137 }
138 }
139 if (rc == 0) {
140 *buffer = tmpptr;
141 }
142 return rc;
143 }
144
145
146 /* TSS_Structure_Marshal() is a general purpose "marshal a structure" function.
147
148 It marshals the structure using "marshalFunction", and returns the malloc'ed stream.
149
150 */
151
TSS_Structure_Marshal(uint8_t ** buffer,uint16_t * written,void * structure,MarshalFunction_t marshalFunction)152 TPM_RC TSS_Structure_Marshal(uint8_t **buffer, /* freed by caller */
153 uint16_t *written,
154 void *structure,
155 MarshalFunction_t marshalFunction)
156 {
157 TPM_RC rc = 0;
158 uint8_t *buffer1 = NULL; /* for marshaling, moves pointer */
159
160 /* marshal once to calculates the byte length */
161 if (rc == 0) {
162 *written = 0;
163 rc = marshalFunction(structure, written, NULL, NULL);
164 }
165 if (rc == 0) {
166 rc = TSS_Malloc(buffer, *written);
167 }
168 if (rc == 0) {
169 buffer1 = *buffer;
170 *written = 0;
171 rc = marshalFunction(structure, written, &buffer1, NULL);
172 }
173 return rc;
174 }
175
176 /* TSS_TPM2B_Copy() copies source to target if the source fits the target size */
177
TSS_TPM2B_Copy(TPM2B * target,TPM2B * source,uint16_t targetSize)178 TPM_RC TSS_TPM2B_Copy(TPM2B *target, TPM2B *source, uint16_t targetSize)
179 {
180 TPM_RC rc = 0;
181
182 if (rc == 0) {
183 if (source->size > targetSize) {
184 if (tssVerbose) printf("TSS_TPM2B_Copy: size %u greater than target %u\n",
185 source->size, targetSize);
186 rc = TSS_RC_INSUFFICIENT_BUFFER;
187 }
188 }
189 if (rc == 0) {
190 memmove(target->buffer, source->buffer, source->size);
191 target->size = source->size;
192 }
193 return rc;
194 }
195
196 /* TSS_TPM2B_Append() appends the source TPM2B to the target TPM2B.
197
198 It checks that the source fits the target size. The target size is the total size, not the size
199 remaining.
200 */
201
TSS_TPM2B_Append(TPM2B * target,TPM2B * source,uint16_t targetSize)202 TPM_RC TSS_TPM2B_Append(TPM2B *target, TPM2B *source, uint16_t targetSize)
203 {
204 TPM_RC rc = 0;
205
206 if (rc == 0) {
207 if (target->size + source->size > targetSize) {
208 if (tssVerbose) printf("TSS_TPM2B_Append: size %u greater than target %u\n",
209 target->size + source->size, targetSize);
210 rc = TSS_RC_INSUFFICIENT_BUFFER;
211 }
212 }
213 if (rc == 0) {
214 memmove(target->buffer + target->size, source->buffer, source->size);
215 target->size += source->size;
216 }
217 return rc;
218 }
219
220 /* TSS_TPM2B_Create() copies the buffer of 'size' into target, checking targetSize */
221
TSS_TPM2B_Create(TPM2B * target,uint8_t * buffer,uint16_t size,uint16_t targetSize)222 TPM_RC TSS_TPM2B_Create(TPM2B *target, uint8_t *buffer, uint16_t size, uint16_t targetSize)
223 {
224 TPM_RC rc = 0;
225
226 if (rc == 0) {
227 if (size > targetSize) {
228 if (tssVerbose) printf("TSS_TPM2B_Create: size %u greater than target %u\n",
229 size, targetSize);
230 rc = TSS_RC_INSUFFICIENT_BUFFER;
231 }
232 }
233 if (rc == 0) {
234 target->size = size;
235 if (size != 0) { /* because buffer can be NULL if size os 0 */
236 memmove(target->buffer, buffer, size);
237 }
238 }
239 return rc;
240 }
241
242 /* TSS_TPM2B_CreateUint32() creates a TPM2B from a uint32_t, typically a permanent handle */
243
TSS_TPM2B_CreateUint32(TPM2B * target,uint32_t source,uint16_t targetSize)244 TPM_RC TSS_TPM2B_CreateUint32(TPM2B *target, uint32_t source, uint16_t targetSize)
245 {
246 TPM_RC rc = 0;
247
248 if (rc == 0) {
249 if (sizeof(uint32_t) > targetSize) {
250 if (tssVerbose) printf("TSS_TPM2B_CreateUint32: size %u greater than target %u\n",
251 (unsigned int)sizeof(uint32_t), targetSize);
252 rc = TSS_RC_INSUFFICIENT_BUFFER;
253 }
254 }
255 if (rc == 0) {
256 uint32_t sourceNbo = htonl(source);
257 memmove(target->buffer, (uint8_t *)&sourceNbo, sizeof(uint32_t));
258 target->size = sizeof(uint32_t);
259 }
260 return rc;
261 }
262
263 /* TSS_TPM2B_StringCopy() copies a NUL terminated string (omitting the NUL) from source to target.
264
265 It checks that the string will fit in targetSize.
266
267 If source is NULL, creates a TPM2B of size 0.
268 */
269
TSS_TPM2B_StringCopy(TPM2B * target,const char * source,uint16_t targetSize)270 TPM_RC TSS_TPM2B_StringCopy(TPM2B *target, const char *source, uint16_t targetSize)
271 {
272 TPM_RC rc = 0;
273 size_t length;
274 uint16_t length16;
275
276 if (source != NULL) {
277 if (rc == 0) {
278 length = strlen(source);
279 if (length > 0xffff) { /* overflow TPM2B uint16_t */
280 if (tssVerbose) printf("TSS_TPM2B_StringCopy: size %u greater than 0xffff\n",
281 (unsigned int)length);
282 rc = TSS_RC_INSUFFICIENT_BUFFER;
283 }
284 }
285 if (rc == 0) {
286 length16 = (uint16_t )length; /* cast safe after range test */
287 if (length16 > targetSize) {
288 if (tssVerbose) printf("TSS_TPM2B_StringCopy: size %u greater than target %u\n",
289 length16, targetSize);
290 rc = TSS_RC_INSUFFICIENT_BUFFER;
291 }
292 }
293 if (rc == 0) {
294 target->size = length16;
295 memcpy(target->buffer, source, length);
296 }
297 }
298 else {
299 target->size = 0;
300 }
301 return rc;
302 }
303
TSS_TPM2B_Compare(TPM2B * expect,TPM2B * actual)304 int TSS_TPM2B_Compare(TPM2B *expect, TPM2B *actual)
305 {
306 int irc;
307 int match = YES;
308
309 if (match == YES) {
310 if (expect->size != actual->size) {
311 match = NO;
312 }
313 }
314 if (match == YES) {
315 irc = memcmp(expect->buffer, actual->buffer, expect->size);
316 if (irc != 0) {
317 match = NO;
318 }
319 }
320 return match;
321 }
322
323 /* TSS_GetDigestSize() returns the digest size in bytes based on the hash algorithm.
324
325 Returns 0 for an unknown algorithm.
326 */
327
328 /* NOTE: Marked as const function in header */
329
TSS_GetDigestSize(TPM_ALG_ID hashAlg)330 uint16_t TSS_GetDigestSize(TPM_ALG_ID hashAlg)
331 {
332 uint16_t size;
333
334 switch (hashAlg) {
335 #ifdef TPM_ALG_SHA1
336 case TPM_ALG_SHA1:
337 size = SHA1_DIGEST_SIZE;
338 break;
339 #endif
340 #ifdef TPM_ALG_SHA256
341 case TPM_ALG_SHA256:
342 size = SHA256_DIGEST_SIZE;
343 break;
344 #endif
345 #ifdef TPM_ALG_SHA384
346 case TPM_ALG_SHA384:
347 size = SHA384_DIGEST_SIZE;
348 break;
349 #endif
350 #ifdef TPM_ALG_SHA512
351 case TPM_ALG_SHA512:
352 size = SHA512_DIGEST_SIZE;
353 break;
354 #endif
355 #if 0
356 case TPM_ALG_SM3_256:
357 size = SM3_256_DIGEST_SIZE;
358 break;
359 #endif
360 default:
361 size = 0;
362 }
363 return size;
364 }
365