diff options
-rw-r--r-- | runtime/librsgt.c | 359 | ||||
-rw-r--r-- | runtime/librsgt.h | 36 | ||||
-rw-r--r-- | runtime/lmsig_gt.c | 17 | ||||
-rw-r--r-- | runtime/sigprov.h | 6 | ||||
-rw-r--r-- | tools/omfile.c | 56 |
5 files changed, 262 insertions, 212 deletions
diff --git a/runtime/librsgt.c b/runtime/librsgt.c index f2ad2727..83a2fe05 100644 --- a/runtime/librsgt.c +++ b/runtime/librsgt.c @@ -88,19 +88,34 @@ rsgtExit(void) } +static inline gtfile +rsgtfileConstruct(gtctx ctx) +{ + gtfile gf; + if((gf = calloc(1, sizeof(struct gtfile_s))) == NULL) + goto done; + gf->ctx = ctx; + gf->hashAlg = ctx->hashAlg; + gf->bKeepRecordHashes = ctx->bKeepRecordHashes; + gf->bKeepTreeHashes = ctx->bKeepTreeHashes; + gf->x_prev = NULL; + +done: return gf; +} + static inline void -tlvbufPhysWrite(gtctx ctx) +tlvbufPhysWrite(gtfile gf) { ssize_t lenBuf; ssize_t iTotalWritten; ssize_t iWritten; char *pWriteBuf; - lenBuf = ctx->tlvIdx; - pWriteBuf = ctx->tlvBuf; + lenBuf = gf->tlvIdx; + pWriteBuf = gf->tlvBuf; iTotalWritten = 0; do { - iWritten = write(ctx->fd, pWriteBuf, lenBuf); + iWritten = write(gf->fd, pWriteBuf, lenBuf); if(iWritten < 0) { //char errStr[1024]; int err = errno; @@ -122,14 +137,14 @@ tlvbufPhysWrite(gtctx ctx) } while(lenBuf > 0); /* Warning: do..while()! */ finalize_it: - ctx->tlvIdx = 0; + gf->tlvIdx = 0; } static inline void -tlvbufChkWrite(gtctx ctx) +tlvbufChkWrite(gtfile gf) { - if(ctx->tlvIdx == sizeof(ctx->tlvBuf)) { - tlvbufPhysWrite(ctx); + if(gf->tlvIdx == sizeof(gf->tlvBuf)) { + tlvbufPhysWrite(gf); } } @@ -138,17 +153,17 @@ tlvbufChkWrite(gtctx ctx) * output is written only on flush or close. */ static inline void -tlvbufAddOctet(gtctx ctx, int8_t octet) +tlvbufAddOctet(gtfile gf, int8_t octet) { - tlvbufChkWrite(ctx); - ctx->tlvBuf[ctx->tlvIdx++] = octet; + tlvbufChkWrite(gf); + gf->tlvBuf[gf->tlvIdx++] = octet; } static inline void -tlvbufAddOctetString(gtctx ctx, uint8_t *octet, int size) +tlvbufAddOctetString(gtfile gf, uint8_t *octet, int size) { int i; for(i = 0 ; i < size ; ++i) - tlvbufAddOctet(ctx, octet[i]); + tlvbufAddOctet(gf, octet[i]); } /* return the actual length in to-be-written octets of an integer */ static inline uint8_t @@ -171,95 +186,95 @@ tlvbufGetInt64OctetSize(uint64_t val) return 1; } static inline void -tlvbufAddInt64(gtctx ctx, uint64_t val) +tlvbufAddInt64(gtfile gf, uint64_t val) { uint8_t doWrite = 0; if(val >> 56) - tlvbufAddOctet(ctx, (val >> 56) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, (val >> 56) & 0xff), doWrite = 1; if(doWrite || ((val >> 48) & 0xff)) - tlvbufAddOctet(ctx, (val >> 48) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, (val >> 48) & 0xff), doWrite = 1; if(doWrite || ((val >> 40) & 0xff)) - tlvbufAddOctet(ctx, (val >> 40) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, (val >> 40) & 0xff), doWrite = 1; if(doWrite || ((val >> 32) & 0xff)) - tlvbufAddOctet(ctx, (val >> 32) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, (val >> 32) & 0xff), doWrite = 1; if(doWrite || ((val >> 24) & 0xff)) - tlvbufAddOctet(ctx, (val >> 24) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, (val >> 24) & 0xff), doWrite = 1; if(doWrite || ((val >> 16) & 0xff)) - tlvbufAddOctet(ctx, (val >> 16) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, (val >> 16) & 0xff), doWrite = 1; if(doWrite || ((val >> 8) & 0xff)) - tlvbufAddOctet(ctx, (val >> 8) & 0xff), doWrite = 1; - tlvbufAddOctet(ctx, val & 0xff); + tlvbufAddOctet(gf, (val >> 8) & 0xff), doWrite = 1; + tlvbufAddOctet(gf, val & 0xff); } void -tlv8Write(gtctx ctx, int flags, int tlvtype, int len) +tlv8Write(gtfile gf, int flags, int tlvtype, int len) { - tlvbufAddOctet(ctx, (flags << 5)|tlvtype); - tlvbufAddOctet(ctx, len & 0xff); + tlvbufAddOctet(gf, (flags << 5)|tlvtype); + tlvbufAddOctet(gf, len & 0xff); } void -tlv16Write(gtctx ctx, int flags, int tlvtype, uint16_t len) +tlv16Write(gtfile gf, int flags, int tlvtype, uint16_t len) { uint16_t typ; typ = ((flags|1) << 13)|tlvtype; - tlvbufAddOctet(ctx, typ >> 8); - tlvbufAddOctet(ctx, typ & 0xff); - tlvbufAddOctet(ctx, (len >> 8) & 0xff); - tlvbufAddOctet(ctx, len & 0xff); + tlvbufAddOctet(gf, typ >> 8); + tlvbufAddOctet(gf, typ & 0xff); + tlvbufAddOctet(gf, (len >> 8) & 0xff); + tlvbufAddOctet(gf, len & 0xff); } void -tlvFlush(gtctx ctx) +tlvFlush(gtfile gf) { - if(ctx->tlvIdx != 0) - tlvbufPhysWrite(ctx); + if(gf->tlvIdx != 0) + tlvbufPhysWrite(gf); } void -tlvWriteHash(gtctx ctx, uint16_t tlvtype, GTDataHash *r) +tlvWriteHash(gtfile gf, uint16_t tlvtype, GTDataHash *r) { unsigned tlvlen; tlvlen = 1 + r->digest_length; - tlv16Write(ctx, 0x00, tlvtype, tlvlen); - tlvbufAddOctet(ctx, hashIdentifier(ctx->hashAlg)); - tlvbufAddOctetString(ctx, r->digest, r->digest_length); + tlv16Write(gf, 0x00, tlvtype, tlvlen); + tlvbufAddOctet(gf, hashIdentifier(gf->hashAlg)); + tlvbufAddOctetString(gf, r->digest, r->digest_length); } void -tlvWriteBlockSig(gtctx ctx, uchar *der, uint16_t lenDer) +tlvWriteBlockSig(gtfile gf, uchar *der, uint16_t lenDer) { unsigned tlvlen; uint8_t tlvlenRecords; - tlvlenRecords = tlvbufGetInt64OctetSize(ctx->nRecords); + tlvlenRecords = tlvbufGetInt64OctetSize(gf->nRecords); tlvlen = 2 + 1 /* hash algo TLV */ + - 2 + hashOutputLengthOctets(ctx->hashAlg) /* iv */ + - 2 + 1 + ctx->lenBlkStrtHash /* last hash */ + + 2 + hashOutputLengthOctets(gf->hashAlg) /* iv */ + + 2 + 1 + gf->lenBlkStrtHash /* last hash */ + 2 + tlvlenRecords /* rec-count */ + 4 + lenDer /* rfc-3161 */; /* write top-level TLV object (block-sig */ - tlv16Write(ctx, 0x00, 0x0902, tlvlen); + tlv16Write(gf, 0x00, 0x0902, tlvlen); /* and now write the children */ //FIXME: flags??? /* hash-algo */ - tlv8Write(ctx, 0x00, 0x00, 1); - tlvbufAddOctet(ctx, hashIdentifier(ctx->hashAlg)); + tlv8Write(gf, 0x00, 0x00, 1); + tlvbufAddOctet(gf, hashIdentifier(gf->hashAlg)); /* block-iv */ - tlv8Write(ctx, 0x00, 0x01, hashOutputLengthOctets(ctx->hashAlg)); - tlvbufAddOctetString(ctx, ctx->IV, hashOutputLengthOctets(ctx->hashAlg)); + tlv8Write(gf, 0x00, 0x01, hashOutputLengthOctets(gf->hashAlg)); + tlvbufAddOctetString(gf, gf->IV, hashOutputLengthOctets(gf->hashAlg)); /* last-hash */ - tlv8Write(ctx, 0x00, 0x02, ctx->lenBlkStrtHash+1); - tlvbufAddOctet(ctx, hashIdentifier(ctx->hashAlg)); - tlvbufAddOctetString(ctx, ctx->blkStrtHash, ctx->lenBlkStrtHash); + tlv8Write(gf, 0x00, 0x02, gf->lenBlkStrtHash+1); + tlvbufAddOctet(gf, hashIdentifier(gf->hashAlg)); + tlvbufAddOctetString(gf, gf->blkStrtHash, gf->lenBlkStrtHash); /* rec-count */ - tlv8Write(ctx, 0x00, 0x03, tlvlenRecords); - tlvbufAddInt64(ctx, ctx->nRecords); + tlv8Write(gf, 0x00, 0x03, tlvlenRecords); + tlvbufAddInt64(gf, gf->nRecords); /* rfc-3161 */ - tlv16Write(ctx, 0x00, 0x906, lenDer); - tlvbufAddOctetString(ctx, der, lenDer); + tlv16Write(gf, 0x00, 0x906, lenDer); + tlvbufAddOctetString(gf, der, lenDer); } /* read rsyslog log state file; if we cannot access it or the @@ -268,85 +283,85 @@ tlvWriteBlockSig(gtctx ctx, uchar *der, uint16_t lenDer) * The context is initialized accordingly. */ static void -readStateFile(gtctx ctx) +readStateFile(gtfile gf) { int fd; struct rsgtstatefile sf; - fd = open((char*)ctx->statefilename, O_RDONLY|O_NOCTTY|O_CLOEXEC, 0600); + fd = open((char*)gf->statefilename, O_RDONLY|O_NOCTTY|O_CLOEXEC, 0600); if(fd == -1) goto err; if(read(fd, &sf, sizeof(sf)) != sizeof(sf)) goto err; if(strncmp(sf.hdr, "GTSTAT10", 8)) goto err; - ctx->lenBlkStrtHash = sf.lenHash; - ctx->blkStrtHash = calloc(1, ctx->lenBlkStrtHash); - if(read(fd, ctx->blkStrtHash, ctx->lenBlkStrtHash) - != ctx->lenBlkStrtHash) { - free(ctx->blkStrtHash); + gf->lenBlkStrtHash = sf.lenHash; + gf->blkStrtHash = calloc(1, gf->lenBlkStrtHash); + if(read(fd, gf->blkStrtHash, gf->lenBlkStrtHash) + != gf->lenBlkStrtHash) { + free(gf->blkStrtHash); goto err; } return; err: - ctx->lenBlkStrtHash = hashOutputLengthOctets(ctx->hashAlg); - ctx->blkStrtHash = calloc(1, ctx->lenBlkStrtHash); + gf->lenBlkStrtHash = hashOutputLengthOctets(gf->hashAlg); + gf->blkStrtHash = calloc(1, gf->lenBlkStrtHash); } /* persist all information that we need to re-open and append * to a log signature file. */ static void -writeStateFile(gtctx ctx) +writeStateFile(gtfile gf) { int fd; struct rsgtstatefile sf; - fd = open((char*)ctx->statefilename, + fd = open((char*)gf->statefilename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0600); if(fd == -1) goto done; memcpy(sf.hdr, "GTSTAT10", 8); - sf.hashID = hashIdentifier(ctx->hashAlg); - sf.lenHash = ctx->x_prev->digest_length; + sf.hashID = hashIdentifier(gf->hashAlg); + sf.lenHash = gf->x_prev->digest_length; write(fd, &sf, sizeof(sf)); - write(fd, ctx->x_prev->digest, ctx->x_prev->digest_length); + write(fd, gf->x_prev->digest, gf->x_prev->digest_length); close(fd); done: return; } -void tlvClose(gtctx ctx) +void tlvClose(gtfile gf) { - tlvFlush(ctx); - close(ctx->fd); - ctx->fd = -1; - writeStateFile(ctx); + tlvFlush(gf); + close(gf->fd); + gf->fd = -1; + writeStateFile(gf); } /* note: if file exists, the last hash for chaining must * be read from file. */ -void tlvOpen(gtctx ctx, char *hdr, unsigned lenHdr) +void tlvOpen(gtfile gf, char *hdr, unsigned lenHdr) { - ctx->fd = open((char*)ctx->sigfilename, + gf->fd = open((char*)gf->sigfilename, O_WRONLY|O_APPEND|O_NOCTTY|O_CLOEXEC, 0600); - if(ctx->fd == -1) { + if(gf->fd == -1) { /* looks like we need to create a new file */ - ctx->fd = open((char*)ctx->sigfilename, + gf->fd = open((char*)gf->sigfilename, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600); // FIXME: check fd == -1 - memcpy(ctx->tlvBuf, hdr, lenHdr); - ctx->tlvIdx = lenHdr; + memcpy(gf->tlvBuf, hdr, lenHdr); + gf->tlvIdx = lenHdr; } else { - ctx->tlvIdx = 0; /* header already present! */ + gf->tlvIdx = 0; /* header already present! */ } /* we now need to obtain the last previous hash, so that * we can continue the hash chain. */ - readStateFile(ctx); + readStateFile(gf); } /* @@ -357,13 +372,13 @@ void tlvOpen(gtctx ctx, char *hdr, unsigned lenHdr) * reproduce). -- rgerhards, 2013-03-04 */ void -seedIV(gtctx ctx) +seedIV(gtfile gf) { int hashlen; int fd; - hashlen = hashOutputLengthOctets(ctx->hashAlg); - ctx->IV = malloc(hashlen); /* do NOT zero-out! */ + hashlen = hashOutputLengthOctets(gf->hashAlg); + gf->IV = malloc(hashlen); /* do NOT zero-out! */ /* if we cannot obtain data from /dev/urandom, we use whatever * is present at the current memory location as random data. Of * course, this is very weak and we should consider a different @@ -372,7 +387,7 @@ seedIV(gtctx ctx) * will always work...). -- TODO -- rgerhards, 2013-03-06 */ if((fd = open("/dev/urandom", O_RDONLY)) > 0) { - read(fd, ctx->IV, hashlen); + read(fd, gf->IV, hashlen); close(fd); } } @@ -382,25 +397,30 @@ rsgtCtxNew(void) { gtctx ctx; ctx = calloc(1, sizeof(struct gtctx_s)); - ctx->x_prev = NULL; ctx->hashAlg = GT_HASHALG_SHA256; ctx->timestamper = strdup( "http://stamper.guardtime.net/gt-signingservice"); return ctx; } -int +/* either returns gtfile object or NULL if something went wrong */ +gtfile rsgtCtxOpenFile(gtctx ctx, unsigned char *logfn) { + gtfile gf; char fn[MAXFNAME+1]; + + if((gf = rsgtfileConstruct(ctx)) == NULL) + goto done; + snprintf(fn, sizeof(fn), "%s.gtsig", logfn); fn[MAXFNAME] = '\0'; /* be on save side */ - ctx->sigfilename = (uchar*) strdup(fn); + gf->sigfilename = (uchar*) strdup(fn); snprintf(fn, sizeof(fn), "%s.gtstate", logfn); fn[MAXFNAME] = '\0'; /* be on save side */ - ctx->statefilename = (uchar*) strdup(fn); - tlvOpen(ctx, LOGSIGHDR, sizeof(LOGSIGHDR)-1); - return 0; + gf->statefilename = (uchar*) strdup(fn); + tlvOpen(gf, LOGSIGHDR, sizeof(LOGSIGHDR)-1); +done: return gf; } @@ -425,54 +445,61 @@ rsgtSetHashFunction(gtctx ctx, char *algName) r = 1; return r; } + void -rsgtCtxDel(gtctx ctx) +rsgtfileDestruct(gtfile gf) { - if(ctx == NULL) + if(gf == NULL) goto done; - if(ctx->bInBlk) - sigblkFinish(ctx); - tlvClose(ctx); - free(ctx->sigfilename); - free(ctx); - /* TODO: persist! */ + if(gf->bInBlk) + sigblkFinish(gf); + tlvClose(gf); + free(gf->sigfilename); + free(gf); done: return; } +void +rsgtCtxDel(gtctx ctx) +{ + if(ctx != NULL) + free(ctx); +} + /* new sigblk is initialized, but maybe in existing ctx */ void -sigblkInit(gtctx ctx) +sigblkInit(gtfile gf) { - seedIV(ctx); - memset(ctx->roots_valid, 0, sizeof(ctx->roots_valid)/sizeof(char)); - ctx->nRoots = 0; - ctx->nRecords = 0; - ctx->bInBlk = 1; + seedIV(gf); + memset(gf->roots_valid, 0, sizeof(gf->roots_valid)/sizeof(char)); + gf->nRoots = 0; + gf->nRecords = 0; + gf->bInBlk = 1; } /* concat: add IV to buffer */ static inline void -bufAddIV(gtctx ctx, uchar *buf, size_t *len) +bufAddIV(gtfile gf, uchar *buf, size_t *len) { - memcpy(buf+*len, &ctx->IV, sizeof(ctx->IV)); - *len += sizeof(ctx->IV); + memcpy(buf+*len, &gf->IV, sizeof(gf->IV)); + *len += sizeof(gf->IV); } /* concat: add hash to buffer */ static inline void -bufAddHash(gtctx ctx, uchar *buf, size_t *len, GTDataHash *hash) +bufAddHash(gtfile gf, uchar *buf, size_t *len, GTDataHash *hash) { if(hash == NULL) { // TODO: how to get the REAL HASH ID? --> add field! - buf[*len] = hashIdentifier(ctx->hashAlg); + buf[*len] = hashIdentifier(gf->hashAlg); ++(*len); - memcpy(buf+*len, ctx->blkStrtHash, ctx->lenBlkStrtHash); - *len += ctx->lenBlkStrtHash; + memcpy(buf+*len, gf->blkStrtHash, gf->lenBlkStrtHash); + *len += gf->lenBlkStrtHash; } else { - buf[*len] = hashIdentifier(ctx->hashAlg); + buf[*len] = hashIdentifier(gf->hashAlg); ++(*len); memcpy(buf+*len, hash->digest, hash->digest_length); *len += hash->digest_length; @@ -488,97 +515,97 @@ bufAddLevel(uchar *buf, size_t *len, uint8_t level) static void -hash_m(gtctx ctx, GTDataHash **m) +hash_m(gtfile gf, GTDataHash **m) { #warning Overall: check GT API return states! - // m = hash(concat(ctx->x_prev, IV)); + // m = hash(concat(gf->x_prev, IV)); uchar concatBuf[16*1024]; size_t len = 0; - bufAddHash(ctx, concatBuf, &len, ctx->x_prev); - bufAddIV(ctx, concatBuf, &len); - GTDataHash_create(ctx->hashAlg, concatBuf, len, m); + bufAddHash(gf, concatBuf, &len, gf->x_prev); + bufAddIV(gf, concatBuf, &len); + GTDataHash_create(gf->hashAlg, concatBuf, len, m); } static inline void -hash_r(gtctx ctx, GTDataHash **r, const uchar *rec, const size_t len) +hash_r(gtfile gf, GTDataHash **r, const uchar *rec, const size_t len) { // r = hash(canonicalize(rec)); - GTDataHash_create(ctx->hashAlg, rec, len, r); + GTDataHash_create(gf->hashAlg, rec, len, r); } static void -hash_node(gtctx ctx, GTDataHash **node, GTDataHash *m, GTDataHash *r, +hash_node(gtfile gf, GTDataHash **node, GTDataHash *m, GTDataHash *r, uint8_t level) { // x = hash(concat(m, r, 0)); /* hash leaf */ uchar concatBuf[16*1024]; size_t len = 0; - bufAddHash(ctx, concatBuf, &len, m); - bufAddHash(ctx, concatBuf, &len, r); + bufAddHash(gf, concatBuf, &len, m); + bufAddHash(gf, concatBuf, &len, r); bufAddLevel(concatBuf, &len, level); - GTDataHash_create(ctx->hashAlg, concatBuf, len, node); + GTDataHash_create(gf->hashAlg, concatBuf, len, node); } void -sigblkAddRecord(gtctx ctx, const uchar *rec, const size_t len) +sigblkAddRecord(gtfile gf, const uchar *rec, const size_t len) { GTDataHash *x; /* current hash */ GTDataHash *m, *r, *t; uint8_t j; - hash_m(ctx, &m); - hash_r(ctx, &r, rec, len); - if(ctx->bKeepRecordHashes) - tlvWriteHash(ctx, 0x0900, r); - hash_node(ctx, &x, m, r, 1); /* hash leaf */ + hash_m(gf, &m); + hash_r(gf, &r, rec, len); + if(gf->bKeepRecordHashes) + tlvWriteHash(gf, 0x0900, r); + hash_node(gf, &x, m, r, 1); /* hash leaf */ /* persists x here if Merkle tree needs to be persisted! */ - if(ctx->bKeepTreeHashes) - tlvWriteHash(ctx, 0x0901, x); + if(gf->bKeepTreeHashes) + tlvWriteHash(gf, 0x0901, x); /* add x to the forest as new leaf, update roots list */ t = x; - for(j = 0 ; j < ctx->nRoots ; ++j) { - if(ctx->roots_valid[j] == 0) { - ctx->roots_hash[j] = t; - ctx->roots_valid[j] = 1; + for(j = 0 ; j < gf->nRoots ; ++j) { + if(gf->roots_valid[j] == 0) { + gf->roots_hash[j] = t; + gf->roots_valid[j] = 1; t = NULL; break; } else if(t != NULL) { /* hash interim node */ - hash_node(ctx, &t, ctx->roots_hash[j], t, j+2); - ctx->roots_valid[j] = 0; - GTDataHash_free(ctx->roots_hash[j]); + hash_node(gf, &t, gf->roots_hash[j], t, j+2); + gf->roots_valid[j] = 0; + GTDataHash_free(gf->roots_hash[j]); // TODO: check if this is correct location (paper!) - if(ctx->bKeepTreeHashes) - tlvWriteHash(ctx, 0x0901, t); + if(gf->bKeepTreeHashes) + tlvWriteHash(gf, 0x0901, t); } } if(t != NULL) { /* new level, append "at the top" */ - ctx->roots_hash[ctx->nRoots] = t; - ctx->roots_valid[ctx->nRoots] = 1; - ++ctx->nRoots; - assert(ctx->nRoots < MAX_ROOTS); + gf->roots_hash[gf->nRoots] = t; + gf->roots_valid[gf->nRoots] = 1; + ++gf->nRoots; + assert(gf->nRoots < MAX_ROOTS); t = NULL; } - ctx->x_prev = x; /* single var may be sufficient */ - ++ctx->nRecords; + gf->x_prev = x; /* single var may be sufficient */ + ++gf->nRecords; /* cleanup */ /* note: x is freed later as part of roots cleanup */ GTDataHash_free(m); GTDataHash_free(r); - if(ctx->nRecords == ctx->blockSizeLimit) { - sigblkFinish(ctx); - sigblkInit(ctx); + if(gf->nRecords == gf->blockSizeLimit) { + sigblkFinish(gf); + sigblkInit(gf); } } static void -timestampIt(gtctx ctx, GTDataHash *hash) +timestampIt(gtfile gf, GTDataHash *hash) { unsigned char *der; size_t lenDer; @@ -586,7 +613,7 @@ timestampIt(gtctx ctx, GTDataHash *hash) GTTimestamp *timestamp = NULL; /* Get the timestamp. */ - r = GTHTTP_createTimestampHash(hash, ctx->timestamper, ×tamp); + r = GTHTTP_createTimestampHash(hash, gf->ctx->timestamper, ×tamp); if(r != GT_OK) { fprintf(stderr, "GTHTTP_createTimestampHash() failed: %d (%s)\n", @@ -602,7 +629,7 @@ timestampIt(gtctx ctx, GTDataHash *hash) goto done; } - tlvWriteBlockSig(ctx, der, lenDer); + tlvWriteBlockSig(gf, der, lenDer); done: GT_free(der); @@ -611,32 +638,32 @@ done: void -sigblkFinish(gtctx ctx) +sigblkFinish(gtfile gf) { GTDataHash *root, *rootDel; int8_t j; - if(ctx->nRecords == 0) + if(gf->nRecords == 0) goto done; root = NULL; - for(j = 0 ; j < ctx->nRoots ; ++j) { + for(j = 0 ; j < gf->nRoots ; ++j) { if(root == NULL) { - root = ctx->roots_hash[j]; - ctx->roots_valid[j] = 0; /* guess this is redundant with init, maybe del */ - } else if(ctx->roots_valid[j]) { + root = gf->roots_hash[j]; + gf->roots_valid[j] = 0; /* guess this is redundant with init, maybe del */ + } else if(gf->roots_valid[j]) { rootDel = root; - hash_node(ctx, &root, ctx->roots_hash[j], root, j+2); - ctx->roots_valid[j] = 0; /* guess this is redundant with init, maybe del */ + hash_node(gf, &root, gf->roots_hash[j], root, j+2); + gf->roots_valid[j] = 0; /* guess this is redundant with init, maybe del */ GTDataHash_free(rootDel); } } - timestampIt(ctx, root); + timestampIt(gf, root); - free(ctx->blkStrtHash); - ctx->lenBlkStrtHash = ctx->x_prev->digest_length; - ctx->blkStrtHash = malloc(ctx->lenBlkStrtHash); - memcpy(ctx->blkStrtHash, ctx->x_prev->digest, ctx->lenBlkStrtHash); + free(gf->blkStrtHash); + gf->lenBlkStrtHash = gf->x_prev->digest_length; + gf->blkStrtHash = malloc(gf->lenBlkStrtHash); + memcpy(gf->blkStrtHash, gf->x_prev->digest, gf->lenBlkStrtHash); done: - ctx->bInBlk = 0; + gf->bInBlk = 0; } diff --git a/runtime/librsgt.h b/runtime/librsgt.h index a4ea7cc1..b2de73bd 100644 --- a/runtime/librsgt.h +++ b/runtime/librsgt.h @@ -30,17 +30,31 @@ #define MAX_ROOTS 64 #define LOGSIGHDR "LOGSIG10" -/* context for gt calls. All state data is kept here, this permits - * multiple concurrent callers. +/* context for gt calls. This primarily serves as a container for the + * config settings. The actual file-specific data is kept in gtfile. */ struct gtctx_s { enum GTHashAlgorithm hashAlg; - uint8_t *IV; /* initial value for blinding masks (where to do we get it from?) */ - GTDataHash *x_prev; /* last leaf hash (maybe of previous block) --> preserve on term */ uint8_t bKeepRecordHashes; uint8_t bKeepTreeHashes; uint64_t blockSizeLimit; char *timestamper; +}; +typedef struct gtctx_s *gtctx; + +/* this describes a file, as far as librsgt is concerned */ +struct gtfile_s { + gtctx ctx; + /* the following data items are mirrored from gtctx to + * increase cache hit ratio (they are frequently accesed). + */ + enum GTHashAlgorithm hashAlg; + uint8_t bKeepRecordHashes; + uint8_t bKeepTreeHashes; + /* end mirrored properties */ + uint64_t blockSizeLimit; + uint8_t *IV; /* initial value for blinding masks */ + GTDataHash *x_prev; /* last leaf hash (maybe of previous block) --> preserve on term */ unsigned char *sigfilename; unsigned char *statefilename; int fd; @@ -54,11 +68,11 @@ struct gtctx_s { */ int8_t roots_valid[MAX_ROOTS]; GTDataHash *roots_hash[MAX_ROOTS]; - /* data mambers for the associated TLV file */ + /* data members for the associated TLV file */ char tlvBuf[4096]; int tlvIdx; /* current index into tlvBuf */ }; -typedef struct gtctx_s *gtctx; +typedef struct gtfile_s *gtfile; typedef struct imprint_s imprint_t; typedef struct block_sig_s block_sig_t; @@ -201,12 +215,12 @@ int rsgtSetHashFunction(gtctx ctx, char *algName); void rsgtInit(char *usragent); void rsgtExit(void); gtctx rsgtCtxNew(void); -int rsgtCtxOpenFile(gtctx ctx, unsigned char *logfn); +gtfile rsgtCtxOpenFile(gtctx ctx, unsigned char *logfn); +void rsgtfileDestruct(gtfile gf); void rsgtCtxDel(gtctx ctx); -void sigblkInit(gtctx ctx); -void sigblkAddRecord(gtctx ctx, const unsigned char *rec, const size_t len); -void sigblkFinish(gtctx ctx); -void rsgtCtxSetLogfileName(gtctx ctx, char *logfilename); +void sigblkInit(gtfile gf); +void sigblkAddRecord(gtfile gf, const unsigned char *rec, const size_t len); +void sigblkFinish(gtfile gf); /* reader functions */ int rsgt_tlvrdHeader(FILE *fp, unsigned char *hdr); int rsgt_tlvrd(FILE *fp, uint16_t *tlvtype, uint16_t *tlvlen, void *obj); diff --git a/runtime/lmsig_gt.c b/runtime/lmsig_gt.c index 474c573f..021cd9f8 100644 --- a/runtime/lmsig_gt.c +++ b/runtime/lmsig_gt.c @@ -118,35 +118,34 @@ SetCnfParam(void *pT, struct nvlst *lst) static rsRetVal -OnFileOpen(void *pT, uchar *fn) +OnFileOpen(void *pT, uchar *fn, gtfile *pgf) { lmsig_gt_t *pThis = (lmsig_gt_t*) pT; DEFiRet; dbgprintf("DDDD: onFileOpen: %s\n", fn); - rsgtCtxOpenFile(pThis->ctx, fn); - sigblkInit(pThis->ctx); + + *pgf = rsgtCtxOpenFile(pThis->ctx, fn); + sigblkInit(*pgf); RETiRet; } static rsRetVal -OnRecordWrite(void *pT, uchar *rec, rs_size_t lenRec) +OnRecordWrite(void *pF, uchar *rec, rs_size_t lenRec) { - lmsig_gt_t *pThis = (lmsig_gt_t*) pT; DEFiRet; dbgprintf("DDDD: onRecordWrite (%d): %s\n", lenRec, rec); - sigblkAddRecord(pThis->ctx, rec, lenRec); + sigblkAddRecord(pF, rec, lenRec); RETiRet; } static rsRetVal -OnFileClose(void *pT) +OnFileClose(void *pF) { - lmsig_gt_t *pThis = (lmsig_gt_t*) pT; DEFiRet; dbgprintf("DDDD: onFileClose\n"); - rsgtCtxDel(pThis->ctx); + rsgtfileDestruct(pF); RETiRet; } diff --git a/runtime/sigprov.h b/runtime/sigprov.h index 5abfb390..82587b7d 100644 --- a/runtime/sigprov.h +++ b/runtime/sigprov.h @@ -29,9 +29,9 @@ BEGINinterface(sigprov) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(void *ppThis); rsRetVal (*SetCnfParam)(void *ppThis, struct nvlst *lst); rsRetVal (*Destruct)(void *ppThis); - rsRetVal (*OnFileOpen)(void *pThis, uchar *fn); - rsRetVal (*OnRecordWrite)(void *pThis, uchar *rec, rs_size_t lenRec); - rsRetVal (*OnFileClose)(void *pThis); + rsRetVal (*OnFileOpen)(void *pThis, uchar *fn, void *pFileInstData); + rsRetVal (*OnRecordWrite)(void *pFileInstData, uchar *rec, rs_size_t lenRec); + rsRetVal (*OnFileClose)(void *pFileInstData); ENDinterface(sigprov) #define sigprovCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ #endif /* #ifndef INCLUDED_SIGPROV_H */ diff --git a/tools/omfile.c b/tools/omfile.c index e439d504..ba2ef3ae 100644 --- a/tools/omfile.c +++ b/tools/omfile.c @@ -119,6 +119,7 @@ getClockFileAccess(void) struct s_dynaFileCacheEntry { uchar *pName; /* name currently open, if dynamic name */ strm_t *pStrm; /* our output stream */ + void *sigprovFileData; /* opaque data ptr for provider use */ uint64 clkTickAccessed;/* for LRU - based on clockFileAccess */ }; typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; @@ -148,6 +149,7 @@ typedef struct _instanceData { uchar *sigprovNameFull;/* full internal signature provider name */ sigprov_if_t sigprov; /* ptr to signature provider interface */ void *sigprovData; /* opaque data ptr for provider use */ + void *sigprovFileData;/* opaque data ptr for file instance */ sbool useSigprov; /* quicker than checkig ptr (1 vs 8 bytes!) */ int iCurrElt; /* currently active cache element (-1 = none) */ int iCurrCacheSize; /* currently cache size (1-based) */ @@ -423,15 +425,16 @@ finalize_it: * if the entry should be d_free()ed and 0 if not. */ static rsRetVal -dynaFileDelCacheEntry(dynaFileCacheEntry **pCache, int iEntry, int bFreeEntry) +dynaFileDelCacheEntry(instanceData *pData, int iEntry, int bFreeEntry) { + dynaFileCacheEntry **pCache = pData->dynCache; DEFiRet; ASSERT(pCache != NULL); if(pCache[iEntry] == NULL) FINALIZE; - DBGPRINTF("Removed entry %d for file '%s' from dynaCache.\n", iEntry, + DBGPRINTF("Removing entry %d for file '%s' from dynaCache.\n", iEntry, pCache[iEntry]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[iEntry]->pName); if(pCache[iEntry]->pName != NULL) { @@ -441,9 +444,10 @@ dynaFileDelCacheEntry(dynaFileCacheEntry **pCache, int iEntry, int bFreeEntry) if(pCache[iEntry]->pStrm != NULL) { strm.Destruct(&pCache[iEntry]->pStrm); -#warning add sig capability here - if(pCache[iEntry]->pStrm != NULL) /* safety check -- TODO: remove if no longer necessary */ - abort(); + if(pData->useSigprov) { + pData->sigprov.OnFileClose(pCache[iEntry]->sigprovFileData); + pCache[iEntry]->sigprovFileData = NULL; + } } if(bFreeEntry) { @@ -468,7 +472,7 @@ dynaFileFreeCacheEntries(instanceData *pData) BEGINfunc; for(i = 0 ; i < pData->iCurrCacheSize ; ++i) { - dynaFileDelCacheEntry(pData->dynCache, i, 1); + dynaFileDelCacheEntry(pData, i, 1); } pData->iCurrElt = -1; /* invalidate current element */ ENDfunc; @@ -494,8 +498,10 @@ static rsRetVal closeFile(instanceData *pData) { DEFiRet; - if(pData->useSigprov) - pData->sigprov.OnFileClose(pData->sigprovData); + if(pData->useSigprov) { + pData->sigprov.OnFileClose(pData->sigprovFileData); + pData->sigprovFileData = NULL; + } strm.Destruct(&pData->pStrm); RETiRet; } @@ -506,7 +512,7 @@ static rsRetVal sigprovPrepare(instanceData *pData, uchar *fn) { DEFiRet; - pData->sigprov.OnFileOpen(pData->sigprovData, fn); + pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData); RETiRet; } @@ -594,7 +600,9 @@ prepareFile(instanceData *pData, uchar *newFileName) CHKiRet(strm.ConstructFinalize(pData->pStrm)); if(pData->useSigprov) +{ dbgprintf("DDDD: prepareFile, call sigprovPrepare\n"); sigprovPrepare(pData, szNameBuf); +} finalize_it: if(iRet != RS_RET_OK) { @@ -630,9 +638,7 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) pCache = pData->dynCache; - /* first check, if we still have the current file - * I *hope* this will be a performance enhancement. - */ + /* first check, if we still have the current file */ if( (pData->iCurrElt != -1) && !ustrcmp(newFileName, pCache[pData->iCurrElt]->pName)) { /* great, we are all set */ @@ -654,9 +660,11 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) if(iFirstFree == -1) iFirstFree = i; } else { /* got an element, let's see if it matches */ - if(!ustrcmp(newFileName, pCache[i]->pName)) { // RG: name == NULL? + if(!ustrcmp(newFileName, pCache[i]->pName)) { /* we found our element! */ pData->pStrm = pCache[i]->pStrm; + if(pData->useSigprov) + pData->sigprovFileData = pCache[i]->sigprovFileData; pData->iCurrElt = i; pCache[i]->clkTickAccessed = getClockFileAccess(); /* update "timestamp" for LRU */ FINALIZE; @@ -683,7 +691,7 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) * but it could be triggered in the common case of a failed open() system call. * rgerhards, 2010-03-22 */ - pData->pStrm = NULL; + pData->pStrm = pData->sigprovFileData = NULL; if(iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaFileCacheSize)) { /* there is space left, so set it to that index */ @@ -696,19 +704,17 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) * The cache array is only updated after the open was successful. -- rgerhards, 2010-03-21 */ if(iFirstFree == -1) { - dynaFileDelCacheEntry(pCache, iOldest, 0); + dynaFileDelCacheEntry(pData, iOldest, 0); STATSCOUNTER_INC(pData->ctrEvict, pData->mutCtrEvict); iFirstFree = iOldest; /* this one *is* now free ;) */ } else { /* we need to allocate memory for the cache structure */ - /* TODO: performance note: we could alloc all entries on startup, thus saving malloc - * overhead -- this may be something to consider in v5... - */ CHKmalloc(pCache[iFirstFree] = (dynaFileCacheEntry*) calloc(1, sizeof(dynaFileCacheEntry))); } /* Ok, we finally can open the file */ localRet = prepareFile(pData, newFileName); /* ignore exact error, we check fd below */ +dbgprintf("DDDD: prepareFile returned %d\n", localRet); /* check if we had an error */ if(localRet != RS_RET_OK) { @@ -730,6 +736,8 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pCache[iFirstFree]->pStrm = pData->pStrm; + if(pData->useSigprov) + pCache[iFirstFree]->sigprovFileData = pData->sigprovFileData; pCache[iFirstFree]->clkTickAccessed = getClockFileAccess(); pData->iCurrElt = iFirstFree; DBGPRINTF("Added new entry %d for file cache, file '%s'.\n", iFirstFree, newFileName); @@ -751,10 +759,11 @@ doWrite(instanceData *pData, uchar *pszBuf, int lenBuf) ASSERT(pData != NULL); ASSERT(pszBuf != NULL); +dbgprintf("DDDD: pData->sigprov %p\n", pData->sigprov); DBGPRINTF("write to stream, pData->pStrm %p, lenBuf %d\n", pData->pStrm, lenBuf); if(pData->pStrm != NULL){ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf)); - CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovData, pszBuf, lenBuf)); + CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovFileData, pszBuf, lenBuf)); } finalize_it: @@ -762,10 +771,7 @@ finalize_it: } -/* rgerhards 2004-11-11: write to a file output. This - * will be called for all outputs using file semantics, - * for example also for pipes. - */ +/* rgerhards 2004-11-11: write to a file output. */ static rsRetVal writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData) { @@ -773,11 +779,14 @@ writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData) ASSERT(pData != NULL); +dbgprintf("DDDD: enter writeFile, dyn: %d, name: %s\n", pData->bDynamicName, pData->f_fname); /* first check if we have a dynamic file name and, if so, * check if it still is ok or a new file needs to be created */ if(pData->bDynamicName) { +dbgprintf("DDDD: calling prepareDynFile\n"); CHKiRet(prepareDynFile(pData, ppString[1], iMsgOpts)); +dbgprintf("DDDD: done prepareDynFile\n"); } else { /* "regular", non-dynafile */ if(pData->pStrm == NULL) { CHKiRet(prepareFile(pData, pData->f_fname)); @@ -787,6 +796,7 @@ writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData) } } +dbgprintf("DDDD: calling doWrite()\n"); CHKiRet(doWrite(pData, ppString[0], strlen(CHAR_CONVERT(ppString[0])))); finalize_it: |