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