1 /********************************************************************************/
2 /*										*/
3 /*			    TSS and Application File Utilities			*/
4 /*			     Written by Ken Goldman				*/
5 /*		       IBM Thomas J. Watson Research Center			*/
6 /*										*/
7 /* (c) Copyright IBM Corporation 2015 - 2019					*/
8 /*										*/
9 /* All rights reserved.								*/
10 /* 										*/
11 /* Redistribution and use in source and binary forms, with or without		*/
12 /* modification, are permitted provided that the following conditions are	*/
13 /* met:										*/
14 /* 										*/
15 /* Redistributions of source code must retain the above copyright notice,	*/
16 /* this list of conditions and the following disclaimer.			*/
17 /* 										*/
18 /* Redistributions in binary form must reproduce the above copyright		*/
19 /* notice, this list of conditions and the following disclaimer in the		*/
20 /* documentation and/or other materials provided with the distribution.		*/
21 /* 										*/
22 /* Neither the names of the IBM Corporation nor the names of its		*/
23 /* contributors may be used to endorse or promote products derived from		*/
24 /* this software without specific prior written permission.			*/
25 /* 										*/
26 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS		*/
27 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT		*/
28 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR	*/
29 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT		*/
30 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,	*/
31 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT		*/
32 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,	*/
33 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY	*/
34 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT		*/
35 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE	*/
36 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.		*/
37 /********************************************************************************/
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <errno.h>
43 
44 #include <ibmtss/tssresponsecode.h>
45 #include <ibmtss/tsserror.h>
46 #include <ibmtss/tssprint.h>
47 #include <ibmtss/tssfile.h>
48 
49 extern int tssVerbose;
50 extern int tssVverbose;
51 
52 /* TSS_File_Open() opens the 'filename' for 'mode'
53  */
54 
TSS_File_Open(FILE ** file,const char * filename,const char * mode)55 int TSS_File_Open(FILE **file,
56 		  const char *filename,
57 		  const char* mode)
58 {
59     int 	rc = 0;
60 
61     if (rc == 0) {
62 	*file = fopen(filename, mode);
63 	if (*file == NULL) {
64 	    if (tssVerbose) printf("TSS_File_Open: Error opening %s for %s, %s\n",
65 				   filename, mode, strerror(errno));
66 	    rc = TSS_RC_FILE_OPEN;
67 	}
68     }
69     return rc;
70 }
71 
72 /* TSS_File_ReadBinaryFile() reads 'filename'.  The results are put into 'data', which must be freed
73    by the caller.  'length' indicates the number of bytes read.
74 
75 */
76 
TSS_File_ReadBinaryFile(unsigned char ** data,size_t * length,const char * filename)77 TPM_RC TSS_File_ReadBinaryFile(unsigned char **data,     /* must be freed by caller */
78 			       size_t *length,
79 			       const char *filename)
80 {
81     int		rc = 0;
82     long	lrc;
83     size_t	src;
84     int		irc;
85     FILE	*file = NULL;
86 
87     *data = NULL;
88     *length = 0;
89     /* open the file */
90     if (rc == 0) {
91 	rc = TSS_File_Open(&file, filename, "rb");				/* closed @1 */
92     }
93     /* determine the file length */
94     if (rc == 0) {
95 	irc = fseek(file, 0L, SEEK_END);	/* seek to end of file */
96 	if (irc == -1L) {
97 	    if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error seeking to end of %s\n",
98 				   filename);
99 	    rc = TSS_RC_FILE_SEEK;
100 	}
101     }
102     if (rc == 0) {
103 	lrc = ftell(file);			/* get position in the stream */
104 	if (lrc == -1L) {
105 	    if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error ftell'ing %s\n", filename);
106 	    rc = TSS_RC_FILE_FTELL;
107 	}
108 	else {
109 	    *length = (size_t)lrc;		/* save the length */
110 	}
111     }
112     if (rc == 0) {
113 	irc = fseek(file, 0L, SEEK_SET);	/* seek back to the beginning of the file */
114 	if (irc == -1L) {
115 	    if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error seeking to beginning of %s\n",
116 				   filename);
117 	    rc = TSS_RC_FILE_SEEK;
118 	}
119     }
120     /* allocate a buffer for the actual data */
121     if ((rc == 0) && (*length != 0)) {
122 	rc = TSS_Malloc(data, *length);
123     }
124     /* read the contents of the file into the data buffer */
125     if ((rc == 0) && *length != 0) {
126 	src = fread(*data, 1, *length, file);
127 	if (src != *length) {
128 	    if (tssVerbose)
129 		printf("TSS_File_ReadBinaryFile: Error reading %s, %u bytes, got %lu\n",
130 		       filename, (unsigned int)*length, (unsigned long)src);
131 	    rc = TSS_RC_FILE_READ;
132 	}
133     }
134     if (file != NULL) {
135 	irc = fclose(file);		/* @1 */
136 	if (irc != 0) {
137 	    if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error closing %s\n",
138 				   filename);
139 	    rc = TSS_RC_FILE_CLOSE;
140 	}
141     }
142     if (rc != 0) {
143 	if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error reading %s\n", filename);
144 	free(*data);
145 	*data = NULL;
146     }
147     return rc;
148 }
149 
150 /* TSS_File_WriteBinaryFile() writes 'data' of 'length' to 'filename'
151  */
152 
TSS_File_WriteBinaryFile(const unsigned char * data,size_t length,const char * filename)153 TPM_RC TSS_File_WriteBinaryFile(const unsigned char *data,
154 				size_t length,
155 				const char *filename)
156 {
157     long	rc = 0;
158     size_t	src;
159     int		irc;
160     FILE	*file = NULL;
161 
162     /* open the file */
163     if (rc == 0) {
164 	rc = TSS_File_Open(&file, filename, "wb");	/* closed @1 */
165     }
166     /* write the contents of the data buffer into the file */
167     if (rc == 0) {
168 	src = fwrite(data, 1, length, file);
169 	if (src != length) {
170 	    if (tssVerbose)
171 		printf("TSS_File_WriteBinaryFile: Error writing %s, %lu bytes, got %lu\n",
172 		       filename, (unsigned long)length, (unsigned long)src);
173 	    rc = TSS_RC_FILE_WRITE;
174 	}
175     }
176     if (file != NULL) {
177 	irc = fclose(file);		/* @1 */
178 	if (irc != 0) {
179 	    if (tssVerbose) printf("TSS_File_WriteBinaryFile: Error closing %s\n",
180 				   filename);
181 	    rc = TSS_RC_FILE_CLOSE;
182 	}
183     }
184     return rc;
185 }
186 
187 /* TSS_File_ReadStructure() is a general purpose "read a structure" function.
188 
189    It reads the filename, and then unmarshals the structure using "unmarshalFunction".
190 */
191 
TSS_File_ReadStructure(void * structure,UnmarshalFunction_t unmarshalFunction,const char * filename)192 TPM_RC TSS_File_ReadStructure(void 			*structure,
193 			      UnmarshalFunction_t 	unmarshalFunction,
194 			      const char 		*filename)
195 {
196     TPM_RC 	rc = 0;
197     uint8_t	*buffer = NULL;		/* for the free */
198     uint8_t	*buffer1 = NULL;	/* for unmarshaling */
199     size_t 	length = 0;
200 
201     if (rc == 0) {
202 	rc = TSS_File_ReadBinaryFile(&buffer,     /* freed @1 */
203 				     &length,
204 				     filename);
205     }
206     if (rc == 0) {
207 	uint32_t ilength = length;
208 	buffer1 = buffer;
209 	rc = unmarshalFunction(structure, &buffer1, &ilength);
210     }
211     free(buffer);	/* @1 */
212     return rc;
213 }
214 
215 /* TSS_File_ReadStructureFlag() is a general purpose "read a structure" function.
216 
217    It reads the filename, and then unmarshals the structure using "unmarshalFunction".
218 
219    It is similar to TSS_File_ReadStructure() but is used when the structure unmarshal function
220    requires the allowNull flag.
221 */
222 
TSS_File_ReadStructureFlag(void * structure,UnmarshalFunctionFlag_t unmarshalFunction,BOOL allowNull,const char * filename)223 TPM_RC TSS_File_ReadStructureFlag(void 				*structure,
224 				  UnmarshalFunctionFlag_t 	unmarshalFunction,
225 				  BOOL 				allowNull,
226 				  const char 			*filename)
227 {
228     TPM_RC 	rc = 0;
229     uint8_t	*buffer = NULL;		/* for the free */
230     uint8_t	*buffer1 = NULL;	/* for unmarshaling */
231     size_t 	length = 0;
232 
233     if (rc == 0) {
234 	rc = TSS_File_ReadBinaryFile(&buffer,     /* freed @1 */
235 				     &length,
236 				     filename);
237     }
238     if (rc == 0) {
239 	uint32_t ilength = length;
240 	buffer1 = buffer;
241 	rc = unmarshalFunction(structure, &buffer1, &ilength, allowNull);
242     }
243     free(buffer);	/* @1 */
244     return rc;
245 }
246 
247 /* TSS_File_WriteStructure() is a general purpose "write a structure" function.
248 
249    It marshals the structure using "marshalFunction", and then writes it to filename.
250 */
251 
TSS_File_WriteStructure(void * structure,MarshalFunction_t marshalFunction,const char * filename)252 TPM_RC TSS_File_WriteStructure(void 			*structure,
253 			       MarshalFunction_t 	marshalFunction,
254 			       const char 		*filename)
255 {
256     TPM_RC 	rc = 0;
257     uint16_t	written = 0;
258     uint8_t	*buffer = NULL;		/* for the free */
259 
260     if (rc == 0) {
261 	rc = TSS_Structure_Marshal(&buffer,	/* freed @1 */
262 				   &written,
263 				   structure,
264 				   marshalFunction);
265     }
266     if (rc == 0) {
267 	rc = TSS_File_WriteBinaryFile(buffer,
268 				      written,
269 				      filename);
270     }
271     free(buffer);	/* @1 */
272     return rc;
273 }
274 
275 /* TSS_File_Read2B() reads 'filename' and copies the data to 'tpm2b', checking targetSize
276 
277  */
278 
TSS_File_Read2B(TPM2B * tpm2b,uint16_t targetSize,const char * filename)279 TPM_RC TSS_File_Read2B(TPM2B 		*tpm2b,
280 		       uint16_t 	targetSize,
281 		       const char 	*filename)
282 {
283     TPM_RC 	rc = 0;
284     uint8_t	*buffer = NULL;
285     size_t 	length = 0;
286 
287     if (rc == 0) {
288 	rc = TSS_File_ReadBinaryFile(&buffer,     /* freed @1 */
289 				     &length,
290 				     filename);
291     }
292     if (rc == 0) {
293 	if (length > 0xffff) {	/* overflow TPM2B uint16_t */
294 	    if (tssVerbose) printf("TSS_File_Read2B: size %u greater than 0xffff\n",
295 				   (unsigned int)length);
296 	    rc = TSS_RC_INSUFFICIENT_BUFFER;
297 	}
298     }
299     /* copy it into the TPM2B */
300     if (rc == 0) {
301 	rc = TSS_TPM2B_Create(tpm2b, buffer, (uint16_t)length, targetSize);
302     }
303     free(buffer);	/* @1 */
304     return rc;
305 }
306 
307 /* FIXME need to add - ignore failure if does not exist */
308 
TSS_File_DeleteFile(const char * filename)309 TPM_RC TSS_File_DeleteFile(const char *filename)
310 {
311     TPM_RC 	rc = 0;
312     int		irc;
313 
314     if (rc == 0) {
315 	irc = remove(filename);
316 	if (irc != 0) {
317 	    rc = TSS_RC_FILE_REMOVE;
318 	}
319     }
320     return rc;
321 }
322