diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2013-03-06 15:44:11 +0100 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2013-03-06 15:44:11 +0100 |
commit | 497d1e09638c6e819f0e02b7f940a8a826b63265 (patch) | |
tree | 77cdc4beb6195fec5b105ba9d6c8e02fe64cf3b1 | |
parent | 027441b337a3dc2c0017df6eebf473445f628d52 (diff) | |
download | rsyslog-497d1e09638c6e819f0e02b7f940a8a826b63265.tar.gz rsyslog-497d1e09638c6e819f0e02b7f940a8a826b63265.tar.bz2 rsyslog-497d1e09638c6e819f0e02b7f940a8a826b63265.zip |
logsig: write block-sig record
also some general improvements, e.g. random data is now gathered
correctly
-rw-r--r-- | runtime/librsgt.c | 181 | ||||
-rw-r--r-- | runtime/librsgt.h | 91 | ||||
-rw-r--r-- | runtime/lmsig_gt.c | 2 | ||||
-rw-r--r-- | tools/logsigner.c | 2 |
4 files changed, 218 insertions, 58 deletions
diff --git a/runtime/librsgt.c b/runtime/librsgt.c index e1d760c6..8aa80771 100644 --- a/runtime/librsgt.c +++ b/runtime/librsgt.c @@ -58,7 +58,45 @@ typedef unsigned char uchar; #ifndef VERSION #define VERSION "no-version" #endif -#define LOGSIGHDR "LOGSIG10" + +static inline uint16_t +hashOutputLengthOctets(uint8_t hashID) +{ + switch(hashID) { + case GT_HASHALG_SHA1: /* paper: SHA1 */ + return 20; + case GT_HASHALG_RIPEMD160: /* paper: RIPEMD-160 */ + return 20; + case GT_HASHALG_SHA224: /* paper: SHA2-224 */ + return 28; + case GT_HASHALG_SHA256: /* paper: SHA2-256 */ + return 32; + case GT_HASHALG_SHA384: /* paper: SHA2-384 */ + return 48; + case GT_HASHALG_SHA512: /* paper: SHA2-512 */ + return 64; + default:return 32; + } +} +static inline uint8_t +hashIdentifier(uint8_t hashID) +{ + switch(hashID) { + case GT_HASHALG_SHA1: /* paper: SHA1 */ + return 0x00; + case GT_HASHALG_RIPEMD160: /* paper: RIPEMD-160 */ + return 0x02; + case GT_HASHALG_SHA224: /* paper: SHA2-224 */ + return 0x03; + case GT_HASHALG_SHA256: /* paper: SHA2-256 */ + return 0x01; + case GT_HASHALG_SHA384: /* paper: SHA2-384 */ + return 0x04; + case GT_HASHALG_SHA512: /* paper: SHA2-512 */ + return 0x05; + default:return 0xff; + } +} static void outputhash(GTDataHash *hash) @@ -76,8 +114,6 @@ rsgtInit(char *usragent) { int ret = GT_OK; - srand(time(NULL) * 7); /* see comments in seedIV() */ - ret = GT_init(); if(ret != GT_OK) { fprintf(stderr, "GT_init() failed: %d (%s)\n", @@ -160,20 +196,26 @@ tlvbufAddOctet(gtctx ctx, int8_t octet) ctx->tlvBuf[ctx->tlvIdx++] = octet; } static inline void -tlvbufAddOctetString(gtctx ctx, int8_t *octet, int size) +tlvbufAddOctetString(gtctx ctx, uint8_t *octet, int size) { int i; for(i = 0 ; i < size ; ++i) tlvbufAddOctet(ctx, octet[i]); } static inline void -tlvbufAddInteger(gtctx ctx, uint32_t val) +tlvbufAddInt32(gtctx ctx, uint32_t val) { tlvbufAddOctet(ctx, (val >> 24) & 0xff); tlvbufAddOctet(ctx, (val >> 16) & 0xff); tlvbufAddOctet(ctx, (val >> 8) & 0xff); tlvbufAddOctet(ctx, val & 0xff); } +static inline void +tlvbufAddInt64(gtctx ctx, uint64_t val) +{ + tlvbufAddInt32(ctx, (val >> 32) & 0xffffffff); + tlvbufAddInt32(ctx, val & 0xffffffff); +} void @@ -199,13 +241,34 @@ tlvFlush(gtctx ctx) } void -tlvWriteBlockSig(gtctx ctx, uchar *der, size_t der_len) +tlvWriteBlockSig(gtctx ctx, uchar *der, uint16_t lenDer) { + unsigned tlvlen; + + tlvlen = 1 + 1 /* hash algo TLV */ + + 1 + hashOutputLengthOctets(ctx->hashAlg) /* iv */ + + 1 + 1 + ctx->lenBlkStrtHash /* last hash */ + + 1 + 8 /* rec-count (64 bit integer) */ + + 2 + lenDer /* rfc-3161 */; + /* write top-level TLV object (block-sig */ + tlv16Write(ctx, 0x00, 0x0902, tlvlen); + /* and now write the children */ //FIXME: flags??? + /* hash-algo */ tlv8Write(ctx, 0x00, 0x00, 1); - tlvbufAddOctet(ctx, 0x02); // TODO: hash identifier (Tab. 2)! - tlv16Write(ctx, 0x00, 0x906, (uint16_t) der_len); - tlvbufAddOctetString(ctx, (int8_t*) der, (int) der_len); + tlvbufAddOctet(ctx, hashIdentifier(ctx->hashAlg)); + /* block-iv */ + tlv8Write(ctx, 0x00, 0x01, 1); + tlvbufAddOctetString(ctx, ctx->IV, hashOutputLengthOctets(ctx->hashAlg)); + /* last-hash */ + tlv8Write(ctx, 0x00, 0x02, 1); + tlvbufAddOctetString(ctx, ctx->blkStrtHash, ctx->lenBlkStrtHash); + /* rec-count */ + tlv8Write(ctx, 0x00, 0x03, 1); + tlvbufAddInt64(ctx, ctx->nRecords); + /* rfc-3161 */ + tlv16Write(ctx, 0x00, 0x906, lenDer); + tlvbufAddOctetString(ctx, der, lenDer); } void tlvClose(gtctx ctx) @@ -228,36 +291,62 @@ void tlvOpen(gtctx ctx, char *hdr, unsigned lenHdr) // FIXME: check fd == -1 memcpy(ctx->tlvBuf, hdr, lenHdr); ctx->tlvIdx = lenHdr; + /* we now need to obtain the last previous hash, so that + * we can continue the hash chain. + */ + // ... + /* in case we did not have a previous hash (or could not + * obtain it), we start with zero. + */ + ctx->lenBlkStrtHash = hashOutputLengthOctets(ctx->hashAlg); + ctx->blkStrtHash = calloc(1, ctx->lenBlkStrtHash); } +/* + * As of some Linux and security expert I spoke to, /dev/urandom + * provides very strong random numbers, even if it runs out of + * entropy. As far as he knew, this is save for all applications + * (and he had good proof that I currently am not permitted to + * reproduce). -- rgerhards, 2013-03-04 + */ void seedIV(gtctx ctx) { - /* FIXME: this currently is "kindergarten cryptography" - use a - * sufficiently strong PRNG instead! Just a PoC so far! Do NOT - * use in production!!! - * As of some Linux and security expert I spoke to, /dev/urandom - * provides very strong random numbers, even if it runs out of - * entropy. As far as he knew, this is save for all applications - * (and he had good proof that I currently am not permitted to - * reproduce). -- rgerhards, 2013-03-04 + int hashlen; + int fd; + + hashlen = hashOutputLengthOctets(ctx->hashAlg); + ctx->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 + * option, especially when not running under Linux (for Linux, + * unavailability of /dev/urandom is just a theoretic thing, it + * will always work...). -- TODO -- rgerhards, 2013-03-06 */ - ctx->IV = rand() * 1000037; + if((fd = open("/dev/urandom", O_RDONLY)) > 0) { + read(fd, ctx->IV, hashlen); + close(fd); + } } gtctx -rsgtCtxNew(unsigned char *logfn) +rsgtCtxNew(unsigned char *logfn, enum GTHashAlgorithm hashAlg) { char fn[MAXFNAME+1]; gtctx ctx; ctx = calloc(1, sizeof(struct gtctx_s)); + ctx->x_prev = NULL; + ctx->hashAlg = hashAlg; + ctx->timestamper = strdup( + "http://stamper.guardtime.net/gt-signingservice"); snprintf(fn, sizeof(fn), "%s.gtsig", logfn); fn[MAXFNAME] = '\0'; /* be on save side */ ctx->sigfilename = (uchar*) strdup(fn); tlvOpen(ctx, LOGSIGHDR, sizeof(LOGSIGHDR)-1); return ctx; } - + void rsgtCtxDel(gtctx ctx) { @@ -278,10 +367,6 @@ void sigblkInit(gtctx ctx) { seedIV(ctx); -// if(ctx->x_prev == NULL) { - ctx->x_prev = NULL; - /* FIXME: do the real thing - or in a later step as currently? */ -// } memset(ctx->roots_valid, 0, sizeof(ctx->roots_valid)/sizeof(char)); ctx->nRoots = 0; ctx->nRecords = 0; @@ -297,13 +382,14 @@ bufAddIV(gtctx ctx, uchar *buf, size_t *len) *len += sizeof(ctx->IV); } + /* concat: add hash to buffer */ static inline void bufAddHash(gtctx ctx, uchar *buf, size_t *len, GTDataHash *hash) { if(hash == NULL) { - memset(buf+*len, 0, 32); /* FIXME: depends on hash function! */ - *len += 32; + memcpy(buf+*len, ctx->blkStrtHash, ctx->lenBlkStrtHash); + *len += ctx->lenBlkStrtHash; } else { memcpy(buf+*len, hash->digest, hash->digest_length); *len += hash->digest_length; @@ -311,7 +397,7 @@ bufAddHash(gtctx ctx, uchar *buf, size_t *len, GTDataHash *hash) } /* concat: add tree level to buffer */ static inline void -bufAddLevel(gtctx ctx, uchar *buf, size_t *len, int level) +bufAddLevel(uchar *buf, size_t *len, int level) { memcpy(buf+*len, &level, sizeof(level)); *len += sizeof(level); @@ -321,23 +407,21 @@ bufAddLevel(gtctx ctx, uchar *buf, size_t *len, int level) static void hash_m(gtctx ctx, GTDataHash **m) { +#warning Overall: check GT API return states! // m = hash(concat(ctx->x_prev, IV)); - int r; uchar concatBuf[16*1024]; size_t len = 0; bufAddHash(ctx, concatBuf, &len, ctx->x_prev); bufAddIV(ctx, concatBuf, &len); - r = GTDataHash_create(GT_HASHALG_SHA256, concatBuf, len, m); + GTDataHash_create(ctx->hashAlg, concatBuf, len, m); } static void hash_r(gtctx ctx, GTDataHash **r, const uchar *rec, const size_t len) { // r = hash(canonicalize(rec)); - int ret; - - ret = GTDataHash_create(GT_HASHALG_SHA256, rec, len, r); + GTDataHash_create(ctx->hashAlg, rec, len, r); } @@ -345,22 +429,21 @@ static void hash_node(gtctx ctx, GTDataHash **node, GTDataHash *m, GTDataHash *r, int level) { // x = hash(concat(m, r, 0)); /* hash leaf */ - int ret; uchar concatBuf[16*1024]; size_t len = 0; bufAddHash(ctx, concatBuf, &len, m); bufAddHash(ctx, concatBuf, &len, r); - bufAddLevel(ctx, concatBuf, &len, level); - ret = GTDataHash_create(GT_HASHALG_SHA256, concatBuf, len, node); + bufAddLevel(concatBuf, &len, level); + GTDataHash_create(ctx->hashAlg, concatBuf, len, node); } + void sigblkAddRecord(gtctx ctx, const uchar *rec, const size_t len) { GTDataHash *x; /* current hash */ GTDataHash *m, *r, *t; int8_t j; - //int ret; hash_m(ctx, &m); hash_r(ctx, &r, rec, len); @@ -391,6 +474,7 @@ sigblkAddRecord(gtctx ctx, const uchar *rec, const size_t len) ++ctx->nRecords; /* cleanup */ + /* note: x is freed later as part of roots cleanup */ GTDataHash_free(m); GTDataHash_free(r); } @@ -398,15 +482,13 @@ sigblkAddRecord(gtctx ctx, const uchar *rec, const size_t len) static void timestampIt(gtctx ctx, GTDataHash *hash) { + unsigned char *der; + size_t lenDer; int r = GT_OK; GTTimestamp *timestamp = NULL; - unsigned char *der = NULL; - char *sigFile = "logsigner.TIMESTAMP"; - size_t der_len; /* Get the timestamp. */ - r = GTHTTP_createTimestampHash(hash, - "http://stamper.guardtime.net/gt-signingservice", ×tamp); + r = GTHTTP_createTimestampHash(hash, ctx->timestamper, ×tamp); if(r != GT_OK) { fprintf(stderr, "GTHTTP_createTimestampHash() failed: %d (%s)\n", @@ -415,28 +497,15 @@ timestampIt(gtctx ctx, GTDataHash *hash) } /* Encode timestamp. */ - r = GTTimestamp_getDEREncoded(timestamp, &der, &der_len); + r = GTTimestamp_getDEREncoded(timestamp, &der, &lenDer); if(r != GT_OK) { fprintf(stderr, "GTTimestamp_getDEREncoded() failed: %d (%s)\n", r, GT_getErrorString(r)); goto done; } - tlvWriteBlockSig(ctx, der, der_len); + tlvWriteBlockSig(ctx, der, lenDer); -#if 0 - /* Save DER-encoded timestamp to file. */ - r = GT_saveFile(sigFile, der, der_len); - if(r != GT_OK) { - fprintf(stderr, "Cannot save timestamp to file %s: %d (%s)\n", - sigFile, r, GT_getErrorString(r)); - if(r == GT_IO_ERROR) { - fprintf(stderr, "\t%d (%s)\n", errno, strerror(errno)); - } - goto done; - } - printf("Timestamping succeeded!\n"); -#endif done: GT_free(der); GTTimestamp_free(timestamp); diff --git a/runtime/librsgt.h b/runtime/librsgt.h new file mode 100644 index 00000000..cb1829e9 --- /dev/null +++ b/runtime/librsgt.h @@ -0,0 +1,91 @@ +/* librsgt.h - rsyslog's guardtime support library + * + * Copyright 2013 Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INCLUDED_LIBRSGT_H +#define INCLUDED_LIBRSGT_H +#include <gt_base.h> + +/* Max number of roots inside the forest. This permits blocks of up to + * 2^MAX_ROOTS records. We assume that 64 is sufficient for all use + * cases ;) [and 64 is not really a waste of memory, so we do not even + * try to work with reallocs and such...] + */ +#define MAX_ROOTS 64 +#define LOGSIGHDR "LOGSIG10" + +/* context for gt calls. All state data is kept here, this permits + * multiple concurrent callers. + */ +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 */ + char *timestamper; + unsigned char *sigfilename; + int fd; + unsigned char *blkStrtHash; /* last hash from previous block */ + uint16_t lenBlkStrtHash; + uint64_t nRecords; /* current number of records in current block */ + uint64_t bInBlk; /* are we currently inside a blk --> need to finish on close */ + int8_t nRoots; + /* algo engineering: roots structure is split into two arrays + * in order to improve cache hits. + */ + int8_t roots_valid[MAX_ROOTS]; + GTDataHash *roots_hash[MAX_ROOTS]; + /* data mambers for the associated TLV file */ + char tlvBuf[4096]; + int tlvIdx; /* current index into tlvBuf */ +}; +typedef struct gtctx_s *gtctx; + +typedef struct imprint_s imprint_t; +typedef struct block_sig_s block_sig_t; + +struct imprint_s { + uint8_t hashID; + int len; + uint8_t *data; +}; + +#define SIGID_RFC3161 0 +struct block_sig_s { + uint8_t hashID; + uint8_t sigID; /* what type of *signature*? */ + uint8_t *iv; + imprint_t lastHash; + uint64_t recCount; + struct { + struct { + uint8_t *data; + size_t len; /* must be size_t due to GT API! */ + } der; + } sig; +}; + +void rsgtInit(char *usragent); +void rsgtExit(void); +gtctx rsgtCtxNew(unsigned char *logfn, enum GTHashAlgorithm hashAlg); +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); +#endif /* #ifndef INCLUDED_LIBRSGT_H */ diff --git a/runtime/lmsig_gt.c b/runtime/lmsig_gt.c index 578e51e5..8be3e045 100644 --- a/runtime/lmsig_gt.c +++ b/runtime/lmsig_gt.c @@ -61,7 +61,7 @@ OnFileOpen(void *pT, uchar *fn) lmsig_gt_t *pThis = (lmsig_gt_t*) pT; DEFiRet; dbgprintf("DDDD: onFileOpen: %s\n", fn); - pThis->ctx = rsgtCtxNew(fn); + pThis->ctx = rsgtCtxNew(fn, GT_HASHALG_SHA256); sigblkInit(pThis->ctx); RETiRet; diff --git a/tools/logsigner.c b/tools/logsigner.c index f11371aa..f6887696 100644 --- a/tools/logsigner.c +++ b/tools/logsigner.c @@ -120,7 +120,7 @@ processFile(char *name) char line[64*1024+1]; gtctx ctx = NULL; - ctx = rsgtCtxNew((unsigned char*)"SIGFILE"); + ctx = rsgtCtxNew((unsigned char*)"SIGFILE", GT_HASHALG_SHA256); sigblkInit(ctx); if(!strcmp(name, "-")) fp = stdin; |