/** * 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; uint8_t bDone = 0; off_t rewindPos = 0; void *obj; tlvrecord_t rec; if(bRewind) rewindPos = ftello(fp); *bHasRecHashes = 0; *bHasIntermedHashes = 0; *bs = NULL; while(!bDone) { /* we will err out on EOF */ if((r = rsgt_tlvrd(fp, &rec, &obj)) != 0) goto done; switch(rec.tlvtype) { case 0x0900: ++nRecs; *bHasRecHashes = 1; break; case 0x0901: *bHasIntermedHashes = 1; break; case 0x0902: *bs = (block_sig_t*) obj; bDone = 1; break; default:fprintf(fp, "unknown tlv record %4.4x\n", rec.tlvtype); break; } if(!bDone) rsgt_objfree(rec.tlvtype, obj); } 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 BLOCK_SIG during verification phase */ static int rsgt_tlvrdVrfyBlockSig(FILE *fp, block_sig_t **bs, tlvrecord_t *rec) { int r; if((r = rsgt_tlvrd(fp, rec, bs)) != 0) goto done; if(rec->tlvtype != 0x0902) { r = RSGTE_MISS_BLOCKSIG; rsgt_objfree(rec->tlvtype, *bs); goto done; } r = 0; done: return r; }
static int rsgt_tlvrdTreeHash(FILE *fp, FILE *outfp, imprint_t **imp) { int r; tlvrecord_t rec; if((r = rsgt_tlvrd(fp, &rec, imp)) != 0) goto done; if(rec.tlvtype != 0x0901) { r = RSGTE_MISS_TREE_HASH; rsgt_objfree(rec.tlvtype, *imp); goto done; } if(outfp != NULL) if((r = rsgt_tlvwrite(outfp, &rec)) != 0) goto done; r = 0; done: return r; }
static void dumpFile(char *name) { FILE *fp; char hdr[9]; void *obj; tlvrecord_t rec; int r = -1; if(!strcmp(name, "-")) fp = stdin; else { printf("Processing file %s:\n", name); if((fp = fopen(name, "r")) == NULL) { perror(name); goto err; } } if((r = rsgt_tlvrdHeader(fp, (uchar*)hdr)) != 0) goto err; if(!strcmp(hdr, "LOGSIG10")) printf("File Header: Version 10 (deprecated) - conversion needed.\n"); else if(!strcmp(hdr, "LOGSIG11")) printf("File Header: Version 11\n"); else printf("File Header: '%s'\n", hdr); while(1) { /* we will err out on EOF */ if((r = rsgt_tlvrd(fp, &rec, &obj)) != 0) { if(feof(fp)) break; else goto err; } rsgt_tlvprint(stdout, rec.tlvtype, obj, verbose); rsgt_objfree(rec.tlvtype, obj); } if(fp != stdin) fclose(fp); return; err: fprintf(stderr, "error %d (%s) processing file %s\n", r, RSGTE2String(r), name); }