diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/librsgt.h | 10 | ||||
-rw-r--r-- | runtime/librsgt_read.c | 127 |
2 files changed, 128 insertions, 9 deletions
diff --git a/runtime/librsgt.h b/runtime/librsgt.h index b2de73bd..d9d221ea 100644 --- a/runtime/librsgt.h +++ b/runtime/librsgt.h @@ -110,11 +110,16 @@ struct rsgtstatefile { }; /* error states */ -#define RSGTE_IO 1 /* any kind of io error, including EOF */ +#define RSGTE_IO 1 /* any kind of io error */ #define RSGTE_FMT 2 /* data fromat error */ #define RSGTE_INVLTYP 3 /* invalid TLV type record (unexcpected at this point) */ #define RSGTE_OOM 4 /* ran out of memory */ #define RSGTE_LEN 5 /* error related to length records */ +#define RSGTE_NO_BLKSIG 6/* block signature record is missing --> invalid block */ +#define RSGTE_INVLD_RECCNT 7/* mismatch between actual records and records + given in block-sig record */ +#define RSGTE_INVLHDR 8/* invalid file header */ +#define RSGTE_EOF 9 /* specific EOF */ static inline uint16_t @@ -225,5 +230,8 @@ void sigblkFinish(gtfile gf); int rsgt_tlvrdHeader(FILE *fp, unsigned char *hdr); int rsgt_tlvrd(FILE *fp, uint16_t *tlvtype, uint16_t *tlvlen, void *obj); void rsgt_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose); +void rsgt_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose); +int rsgt_getBlockParams(FILE *fp, uint8_t bRewind, block_sig_t **bs, uint8_t *bHasRecHashes, uint8_t *bHasIntermedHashes); +int rsgt_chkFileHdr(FILE *fp, char *expect); #endif /* #ifndef INCLUDED_LIBRSGT_H */ diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c index be78580d..961e50c5 100644 --- a/runtime/librsgt_read.c +++ b/runtime/librsgt_read.c @@ -50,7 +50,7 @@ static int rsgt_read_debug = 0; /* macro to obtain next char from file including error tracking */ #define NEXTC if((c = fgetc(fp)) == EOF) { \ - r = RSGTE_IO; \ + r = feof(fp) ? RSGTE_EOF : RSGTE_IO; \ goto done; \ } @@ -118,6 +118,17 @@ rsgt_tlvrdOctetString(FILE *fp, uint8_t **data, size_t len) done: return r; } static int +rsgt_tlvrdSkipVal(FILE *fp, size_t len) +{ + size_t i; + int c, r = 1; + for(i = 0 ; i < len ; ++i) { + NEXTC; + } + r = 0; +done: return r; +} +static int rsgt_tlvrdHASH_ALGO(FILE *fp, uint8_t *hashAlg) { int r = 1; @@ -314,14 +325,14 @@ done: return r; * otherwise everything. */ static void -outputHexBlob(uint8_t *blob, uint16_t len, uint8_t verbose) +outputHexBlob(FILE *fp, uint8_t *blob, uint16_t len, uint8_t verbose) { unsigned i; if(verbose || len <= 6) { for(i = 0 ; i < len ; ++i) - printf("%2.2x", blob[i]); + fprintf(fp, "%2.2x", blob[i]); } else { - printf("%2.2x%2.2x[...]%2.2x%2.2x", + fprintf(fp, "%2.2x%2.2x[...]%2.2x%2.2x", blob[0], blob[1], blob[len-2], blob[len-2]); } @@ -342,7 +353,7 @@ static void rsgt_printIMPRINT(FILE *fp, char *name, imprint_t *imp, uint8_t verbose) { fprintf(fp, "%s", name); - outputHexBlob(imp->data, imp->len, verbose); + outputHexBlob(fp, imp->data, imp->len, verbose); fputc('\n', fp); } @@ -376,19 +387,19 @@ rsgt_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose) fprintf(fp, "\tPrevious Block Hash:\n"); fprintf(fp, "\t Algorithm..: %s\n", hashAlgName(bs->lastHash.hashID)); fprintf(fp, "\t Hash.......: "); - outputHexBlob(bs->lastHash.data, bs->lastHash.len, verbose); + outputHexBlob(fp, bs->lastHash.data, bs->lastHash.len, verbose); fputc('\n', fp); if(blobIsZero(bs->lastHash.data, bs->lastHash.len)) fprintf(fp, "\t NOTE: New Hash Chain Start!\n"); fprintf(fp, "\tHash Algorithm: %s\n", hashAlgName(bs->hashID)); fprintf(fp, "\tIV............: "); - outputHexBlob(bs->iv, getIVLen(bs), verbose); + outputHexBlob(fp, bs->iv, getIVLen(bs), verbose); fputc('\n', fp); fprintf(fp, "\tRecord Count..: %llu\n", bs->recCount); fprintf(fp, "\tSignature Type: %s\n", sigTypeName(bs->sigID)); fprintf(fp, "\tSignature Len.: %u\n", bs->sig.der.len); fprintf(fp, "\tSignature.....: "); - outputHexBlob(bs->sig.der.data, bs->sig.der.len, verbose); + outputHexBlob(fp, bs->sig.der.data, bs->sig.der.len, verbose); fputc('\n', fp); } @@ -417,3 +428,103 @@ rsgt_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose) break; } } + + +/** + * Read block parameters. This detects if the block contains the + * individual log hashes, the intermediate hashes and the overall + * block paramters (from the signature block). As we do not have any + * begin of block record, we do not know e.g. the hash algorithm or IV + * until reading the block signature record. And because the file is + * purely sequential and variable size, we need to read all records up to + * the next signature record. + * If a caller intends to verify a log file based on the parameters, + * he must re-read the file from the begining (we could keep things + * in memory, but this is impractical for large blocks). In order + * to facitate this, the function permits to rewind to the original + * read location when it is done. + * + * @param[in] fp file pointer of tlv file + * @param[in] bRewind 0 - do not rewind at end of procesing, 1 - do so + * @param[out] bs block signature record + * @param[out] bHasRecHashes 0 if record hashes are present, 1 otherwise + * @param[out] bHasIntermedHashes 0 if intermediate hashes are present, + * 1 otherwise + * + * @returns 0 if ok, something else otherwise + */ +int +rsgt_getBlockParams(FILE *fp, uint8_t bRewind, block_sig_t **bs, + uint8_t *bHasRecHashes, uint8_t *bHasIntermedHashes) +{ + int r; + uint64_t nRecs = 0; + uint16_t tlvtype, tlvlen; + uint8_t bDone = 0; + off_t rewindPos = 0; + + if(bRewind) + rewindPos = ftello(fp); + *bHasRecHashes = 0; + *bHasIntermedHashes = 0; + *bs = NULL; + + while(!bDone) { /* we will err out on EOF */ + if((r = rsgt_tlvrdTL(fp, &tlvtype, &tlvlen)) != 0) goto done; + switch(tlvtype) { + case 0x0900: + ++nRecs; + *bHasRecHashes = 1; + rsgt_tlvrdSkipVal(fp, tlvlen); + break; + case 0x0901: + *bHasIntermedHashes = 1; + rsgt_tlvrdSkipVal(fp, tlvlen); + break; + case 0x0902: + r = rsgt_tlvrdBLOCK_SIG(fp, bs, tlvlen); + if(r != 0) goto done; + bDone = 1; + break; + default:fprintf(fp, "unknown tlv record %4.4x\n", tlvtype); + break; + } + } + + if(*bHasRecHashes && (nRecs != (*bs)->recCount)) { + r = RSGTE_INVLD_RECCNT; + goto done; + } + + if(bRewind) { + if(fseeko(fp, rewindPos, SEEK_SET) != 0) { + r = RSGTE_IO; + goto done; + } + } +done: + return r; +} + + +/** + * Read the file header and compare it to the expected value. + * The file pointer is placed right after the header. + * @param[in] fp file pointer of tlv file + * @param[in] excpect expected header (e.g. "LOGSIG10") + * @returns 0 if ok, something else otherwise + */ +int +rsgt_chkFileHdr(FILE *fp, char *expect) +{ + int r; + char hdr[9]; + + if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto done; + if(strcmp(hdr, expect)) + r = RSGTE_INVLHDR; + else + r = 0; +done: + return r; +} |