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