/********************************************************************************/ /* */ /* TSS and Application File Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2015 - 2019 */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include #include #include #include #include extern int tssVerbose; extern int tssVverbose; /* TSS_File_Open() opens the 'filename' for 'mode' */ int TSS_File_Open(FILE **file, const char *filename, const char* mode) { int rc = 0; if (rc == 0) { *file = fopen(filename, mode); if (*file == NULL) { if (tssVerbose) printf("TSS_File_Open: Error opening %s for %s, %s\n", filename, mode, strerror(errno)); rc = TSS_RC_FILE_OPEN; } } return rc; } /* TSS_File_ReadBinaryFile() reads 'filename'. The results are put into 'data', which must be freed by the caller. 'length' indicates the number of bytes read. */ TPM_RC TSS_File_ReadBinaryFile(unsigned char **data, /* must be freed by caller */ size_t *length, const char *filename) { int rc = 0; long lrc; size_t src; int irc; FILE *file = NULL; *data = NULL; *length = 0; /* open the file */ if (rc == 0) { rc = TSS_File_Open(&file, filename, "rb"); /* closed @1 */ } /* determine the file length */ if (rc == 0) { irc = fseek(file, 0L, SEEK_END); /* seek to end of file */ if (irc == -1L) { if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error seeking to end of %s\n", filename); rc = TSS_RC_FILE_SEEK; } } if (rc == 0) { lrc = ftell(file); /* get position in the stream */ if (lrc == -1L) { if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error ftell'ing %s\n", filename); rc = TSS_RC_FILE_FTELL; } else { *length = (size_t)lrc; /* save the length */ } } if (rc == 0) { irc = fseek(file, 0L, SEEK_SET); /* seek back to the beginning of the file */ if (irc == -1L) { if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error seeking to beginning of %s\n", filename); rc = TSS_RC_FILE_SEEK; } } /* allocate a buffer for the actual data */ if ((rc == 0) && (*length != 0)) { rc = TSS_Malloc(data, *length); } /* read the contents of the file into the data buffer */ if ((rc == 0) && *length != 0) { src = fread(*data, 1, *length, file); if (src != *length) { if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error reading %s, %u bytes, got %lu\n", filename, (unsigned int)*length, (unsigned long)src); rc = TSS_RC_FILE_READ; } } if (file != NULL) { irc = fclose(file); /* @1 */ if (irc != 0) { if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error closing %s\n", filename); rc = TSS_RC_FILE_CLOSE; } } if (rc != 0) { if (tssVerbose) printf("TSS_File_ReadBinaryFile: Error reading %s\n", filename); free(*data); *data = NULL; } return rc; } /* TSS_File_WriteBinaryFile() writes 'data' of 'length' to 'filename' */ TPM_RC TSS_File_WriteBinaryFile(const unsigned char *data, size_t length, const char *filename) { long rc = 0; size_t src; int irc; FILE *file = NULL; /* open the file */ if (rc == 0) { rc = TSS_File_Open(&file, filename, "wb"); /* closed @1 */ } /* write the contents of the data buffer into the file */ if (rc == 0) { src = fwrite(data, 1, length, file); if (src != length) { if (tssVerbose) printf("TSS_File_WriteBinaryFile: Error writing %s, %lu bytes, got %lu\n", filename, (unsigned long)length, (unsigned long)src); rc = TSS_RC_FILE_WRITE; } } if (file != NULL) { irc = fclose(file); /* @1 */ if (irc != 0) { if (tssVerbose) printf("TSS_File_WriteBinaryFile: Error closing %s\n", filename); rc = TSS_RC_FILE_CLOSE; } } return rc; } /* TSS_File_ReadStructure() is a general purpose "read a structure" function. It reads the filename, and then unmarshals the structure using "unmarshalFunction". */ TPM_RC TSS_File_ReadStructure(void *structure, UnmarshalFunction_t unmarshalFunction, const char *filename) { TPM_RC rc = 0; uint8_t *buffer = NULL; /* for the free */ uint8_t *buffer1 = NULL; /* for unmarshaling */ size_t length = 0; if (rc == 0) { rc = TSS_File_ReadBinaryFile(&buffer, /* freed @1 */ &length, filename); } if (rc == 0) { uint32_t ilength = length; buffer1 = buffer; rc = unmarshalFunction(structure, &buffer1, &ilength); } free(buffer); /* @1 */ return rc; } /* TSS_File_ReadStructureFlag() is a general purpose "read a structure" function. It reads the filename, and then unmarshals the structure using "unmarshalFunction". It is similar to TSS_File_ReadStructure() but is used when the structure unmarshal function requires the allowNull flag. */ TPM_RC TSS_File_ReadStructureFlag(void *structure, UnmarshalFunctionFlag_t unmarshalFunction, BOOL allowNull, const char *filename) { TPM_RC rc = 0; uint8_t *buffer = NULL; /* for the free */ uint8_t *buffer1 = NULL; /* for unmarshaling */ size_t length = 0; if (rc == 0) { rc = TSS_File_ReadBinaryFile(&buffer, /* freed @1 */ &length, filename); } if (rc == 0) { uint32_t ilength = length; buffer1 = buffer; rc = unmarshalFunction(structure, &buffer1, &ilength, allowNull); } free(buffer); /* @1 */ return rc; } /* TSS_File_WriteStructure() is a general purpose "write a structure" function. It marshals the structure using "marshalFunction", and then writes it to filename. */ TPM_RC TSS_File_WriteStructure(void *structure, MarshalFunction_t marshalFunction, const char *filename) { TPM_RC rc = 0; uint16_t written = 0; uint8_t *buffer = NULL; /* for the free */ if (rc == 0) { rc = TSS_Structure_Marshal(&buffer, /* freed @1 */ &written, structure, marshalFunction); } if (rc == 0) { rc = TSS_File_WriteBinaryFile(buffer, written, filename); } free(buffer); /* @1 */ return rc; } /* TSS_File_Read2B() reads 'filename' and copies the data to 'tpm2b', checking targetSize */ TPM_RC TSS_File_Read2B(TPM2B *tpm2b, uint16_t targetSize, const char *filename) { TPM_RC rc = 0; uint8_t *buffer = NULL; size_t length = 0; if (rc == 0) { rc = TSS_File_ReadBinaryFile(&buffer, /* freed @1 */ &length, filename); } if (rc == 0) { if (length > 0xffff) { /* overflow TPM2B uint16_t */ if (tssVerbose) printf("TSS_File_Read2B: size %u greater than 0xffff\n", (unsigned int)length); rc = TSS_RC_INSUFFICIENT_BUFFER; } } /* copy it into the TPM2B */ if (rc == 0) { rc = TSS_TPM2B_Create(tpm2b, buffer, (uint16_t)length, targetSize); } free(buffer); /* @1 */ return rc; } /* FIXME need to add - ignore failure if does not exist */ TPM_RC TSS_File_DeleteFile(const char *filename) { TPM_RC rc = 0; int irc; if (rc == 0) { irc = remove(filename); if (irc != 0) { rc = TSS_RC_FILE_REMOVE; } } return rc; }