summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/Makefile.am2
-rw-r--r--runtime/librsgt.c70
-rw-r--r--runtime/librsgt.h88
-rw-r--r--runtime/librsgt_read.c348
4 files changed, 452 insertions, 56 deletions
diff --git a/runtime/Makefile.am b/runtime/Makefile.am
index 20824494..c429394d 100644
--- a/runtime/Makefile.am
+++ b/runtime/Makefile.am
@@ -178,7 +178,7 @@ endif
# support library for guardtime
#
if ENABLE_GUARDTIME
- librsgt_la_SOURCES = librsgt.c
+ librsgt_la_SOURCES = librsgt.c librsgt_read.c
pkglib_LTLIBRARIES += lmsig_gt.la
lmsig_gt_la_SOURCES = lmsig_gt.c
diff --git a/runtime/librsgt.c b/runtime/librsgt.c
index 8aa80771..e5187c42 100644
--- a/runtime/librsgt.c
+++ b/runtime/librsgt.c
@@ -48,7 +48,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#define MAXFNAME 1024 /* TODO: include correct header */
+#define MAXFNAME 1024
#include <gt_http.h>
@@ -59,45 +59,6 @@ typedef unsigned char uchar;
#define VERSION "no-version"
#endif
-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)
{
@@ -108,7 +69,6 @@ outputhash(GTDataHash *hash)
}
-
void
rsgtInit(char *usragent)
{
@@ -144,7 +104,6 @@ tlvbufPhysWrite(gtctx ctx)
ssize_t iTotalWritten;
ssize_t iWritten;
char *pWriteBuf;
- fprintf(stderr, "emu: writing TLV file!\n");
lenBuf = ctx->tlvIdx;
pWriteBuf = ctx->tlvBuf;
@@ -171,8 +130,6 @@ tlvbufPhysWrite(gtctx ctx)
pWriteBuf += iWritten;
} while(lenBuf > 0); /* Warning: do..while()! */
- //DBGOPRINT((obj_t*) pThis, "file %d write wrote %d bytes\n", pThis->fd, (int) iWritten);
-
finalize_it:
ctx->tlvIdx = 0;
}
@@ -228,7 +185,10 @@ tlv8Write(gtctx ctx, int flags, int tlvtype, int len)
void
tlv16Write(gtctx ctx, int flags, int tlvtype, uint16_t len)
{
- tlvbufAddOctet(ctx, ((flags|1) << 13)|tlvtype);
+ 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);
}
@@ -245,11 +205,12 @@ 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 */;
+ tlvlen = 2 + 1 /* hash algo TLV */ +
+ 2 + hashOutputLengthOctets(ctx->hashAlg) /* iv */ +
+ 2 + 1 + ctx->lenBlkStrtHash /* last hash */ +
+ 2 + 8 /* rec-count (64 bit integer) */ +
+ 4 + lenDer /* rfc-3161 */;
+printf("TTTT: tlvlen %u, lenDer %u\n", tlvlen, lenDer);
/* write top-level TLV object (block-sig */
tlv16Write(ctx, 0x00, 0x0902, tlvlen);
/* and now write the children */
@@ -258,13 +219,14 @@ tlvWriteBlockSig(gtctx ctx, uchar *der, uint16_t lenDer)
tlv8Write(ctx, 0x00, 0x00, 1);
tlvbufAddOctet(ctx, hashIdentifier(ctx->hashAlg));
/* block-iv */
- tlv8Write(ctx, 0x00, 0x01, 1);
+ tlv8Write(ctx, 0x00, 0x01, hashOutputLengthOctets(ctx->hashAlg));
tlvbufAddOctetString(ctx, ctx->IV, hashOutputLengthOctets(ctx->hashAlg));
/* last-hash */
- tlv8Write(ctx, 0x00, 0x02, 1);
+ tlv8Write(ctx, 0x00, 0x02, ctx->lenBlkStrtHash+1);
+ tlvbufAddOctet(ctx, hashIdentifier(ctx->hashAlg));
tlvbufAddOctetString(ctx, ctx->blkStrtHash, ctx->lenBlkStrtHash);
/* rec-count */
- tlv8Write(ctx, 0x00, 0x03, 1);
+ tlv8Write(ctx, 0x00, 0x03, 8);
tlvbufAddInt64(ctx, ctx->nRecords);
/* rfc-3161 */
tlv16Write(ctx, 0x00, 0x906, lenDer);
@@ -274,7 +236,6 @@ tlvWriteBlockSig(gtctx ctx, uchar *der, uint16_t lenDer)
void tlvClose(gtctx ctx)
{
tlvFlush(ctx);
- fprintf(stderr, "emu: close tlv file\n");
close(ctx->fd);
ctx->fd = -1;
}
@@ -285,7 +246,6 @@ void tlvClose(gtctx ctx)
*/
void tlvOpen(gtctx ctx, char *hdr, unsigned lenHdr)
{
- fprintf(stderr, "emu: open tlv file '%s'\n", ctx->sigfilename);
ctx->fd = open((char*)ctx->sigfilename,
O_WRONLY/*|O_APPEND*/|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600);
// FIXME: check fd == -1
diff --git a/runtime/librsgt.h b/runtime/librsgt.h
index cb1829e9..4ce0be30 100644
--- a/runtime/librsgt.h
+++ b/runtime/librsgt.h
@@ -70,6 +70,8 @@ struct block_sig_s {
uint8_t hashID;
uint8_t sigID; /* what type of *signature*? */
uint8_t *iv;
+ // TODO: think about the situation where the last hash is
+ // different from the current one (e.g. config change!)
imprint_t lastHash;
uint64_t recCount;
struct {
@@ -80,6 +82,87 @@ struct block_sig_s {
} sig;
};
+/* error states */
+#define RSGTE_IO 1 /* any kind of io error, including EOF */
+#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 */
+
+
+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 inline char *
+hashAlgName(uint8_t hashID)
+{
+ switch(hashID) {
+ case GT_HASHALG_SHA1:
+ return "SHA1";
+ case GT_HASHALG_RIPEMD160:
+ return "RIPEMD-160";
+ case GT_HASHALG_SHA224:
+ return "SHA2-224";
+ case GT_HASHALG_SHA256:
+ return "SHA2-256";
+ case GT_HASHALG_SHA384:
+ return "SHA2-384";
+ case GT_HASHALG_SHA512:
+ return "SHA2-512";
+ default:return "[unknown]";
+ }
+}
+static inline char *
+sigTypeName(uint8_t sigID)
+{
+ switch(sigID) {
+ case SIGID_RFC3161:
+ return "RFC3161";
+ default:return "[unknown]";
+ }
+}
+static inline uint16_t
+getIVLen(block_sig_t *bs)
+{
+ return hashOutputLengthOctets(bs->hashID);
+}
+
void rsgtInit(char *usragent);
void rsgtExit(void);
gtctx rsgtCtxNew(unsigned char *logfn, enum GTHashAlgorithm hashAlg);
@@ -88,4 +171,9 @@ 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);
+/* reader functions */
+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);
+
#endif /* #ifndef INCLUDED_LIBRSGT_H */
diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c
new file mode 100644
index 00000000..fa489a0f
--- /dev/null
+++ b/runtime/librsgt_read.c
@@ -0,0 +1,348 @@
+/* librsgt_read.c - rsyslog's guardtime support library
+ * This includes functions used for reading signature (and
+ * other related) files.
+ *
+ * This part of the library uses C stdio and expects that the
+ * caller will open and close the file to be read itself.
+ *
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "librsgt.h"
+
+typedef unsigned char uchar;
+#ifndef VERSION
+#define VERSION "no-version"
+#endif
+#define MAXFNAME 1024
+
+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; \
+ goto done; \
+ }
+
+/* check return state of operation and abort, if non-OK */
+#define CHKr(code) if((r = code) != 0) goto done
+
+/**
+ * Read a header from a binary file.
+ * @param[in] fp file pointer for processing
+ * @param[in] hdr buffer for the header. Must be 9 bytes
+ * (8 for header + NUL byte)
+ * @returns 0 if ok, something else otherwise
+ */
+int
+rsgt_tlvrdHeader(FILE *fp, uchar *hdr)
+{
+ int r;
+ if(fread(hdr, 8, 1, fp) != 1) {
+ r = RSGTE_IO;
+ goto done;
+ }
+ hdr[8] = '\0';
+ r = 0;
+done: return r;
+}
+
+/* read type & length */
+static int
+rsgt_tlvrdTL(FILE *fp, uint16_t *tlvtype, uint16_t *tlvlen)
+{
+ int r = 1;
+ int c;
+
+ NEXTC;
+ *tlvtype = c & 0x1f;
+ if(c & 0x20) { /* tlv16? */
+ NEXTC;
+ *tlvtype = (*tlvtype << 8) | c;
+ NEXTC;
+ *tlvlen = c << 8;
+ NEXTC;
+ *tlvlen |= c;
+ } else {
+ NEXTC;
+ *tlvlen = c;
+ }
+ if(rsgt_read_debug)
+ printf("read tlvtype %4.4x, len %u\n", (unsigned) *tlvtype,
+ (unsigned) *tlvlen);
+ r = 0;
+done: return r;
+}
+
+static int
+rsgt_tlvrdOctetString(FILE *fp, uint8_t **data, size_t len)
+{
+ size_t i;
+ int c, r = 1;
+ if((*data = (uint8_t*)malloc(len)) == NULL) {r=RSGTE_OOM;goto done;}
+ for(i = 0 ; i < len ; ++i) {
+ NEXTC;
+ (*data)[i] = c;
+ }
+ r = 0;
+done: return r;
+}
+static int
+rsgt_tlvrdHASH_ALGO(FILE *fp, uint8_t *hashAlg)
+{
+ int r = 1;
+ int c;
+ uint16_t tlvtype, tlvlen;
+
+ CHKr(rsgt_tlvrdTL(fp, &tlvtype, &tlvlen));
+ if(!(tlvtype == 0x00 && tlvlen == 1)) {
+ r = RSGTE_FMT;
+ goto done;
+ }
+ NEXTC;
+ *hashAlg = c;
+ r = 0;
+done: return r;
+}
+static int
+rsgt_tlvrdBLOCK_IV(FILE *fp, uint8_t **iv)
+{
+ int r = 1;
+ uint16_t tlvtype, tlvlen;
+
+ CHKr(rsgt_tlvrdTL(fp, &tlvtype, &tlvlen));
+ if(!(tlvtype == 0x01)) {
+ r = RSGTE_INVLTYP;
+ goto done;
+ }
+ CHKr(rsgt_tlvrdOctetString(fp, iv, tlvlen));
+ r = 0;
+done: return r;
+}
+static int
+rsgt_tlvrdLAST_HASH(FILE *fp, imprint_t *imp)
+{
+ int r = 1;
+ int c;
+ uint16_t tlvtype, tlvlen;
+
+ CHKr(rsgt_tlvrdTL(fp, &tlvtype, &tlvlen));
+ if(!(tlvtype == 0x02)) { r = RSGTE_INVLTYP; goto done; }
+ NEXTC;
+ imp->hashID = c;
+ imp->len = tlvlen - 1;
+ CHKr(rsgt_tlvrdOctetString(fp, &imp->data, tlvlen-1));
+ r = 0;
+done: return r;
+}
+static int
+rsgt_tlvrdREC_COUNT(FILE *fp, uint64_t *cnt, size_t *lenInt)
+{
+ int r = 1;
+ int i;
+ int c;
+ uint64_t val;
+ uint16_t tlvtype, tlvlen;
+
+ if((r = rsgt_tlvrdTL(fp, &tlvtype, &tlvlen)) != 0) goto done;
+ if(!(tlvtype == 0x03 && tlvlen <= 8)) { r = RSGTE_INVLTYP; goto done; }
+ *lenInt = tlvlen;
+ val = 0;
+ for(i = 0 ; i < tlvlen ; ++i) {
+ NEXTC;
+ val = (val << 8) + c;
+ }
+ *cnt = val;
+ r = 0;
+done: return r;
+}
+static int
+rsgt_tlvrdSIG(FILE *fp, block_sig_t *bs)
+{
+ int r = 1;
+ uint16_t tlvtype, tlvlen;
+
+ CHKr(rsgt_tlvrdTL(fp, &tlvtype, &tlvlen));
+ if(!(tlvtype == 0x0906)) { r = RSGTE_INVLTYP; goto done; }
+ bs->sig.der.len = tlvlen;
+ bs->sigID = SIGID_RFC3161;
+ CHKr(rsgt_tlvrdOctetString(fp, &(bs->sig.der.data), tlvlen));
+ r = 0;
+done: return r;
+}
+
+static int
+rsgt_tlvrdBLOCK_SIG(FILE *fp, block_sig_t **blocksig, uint16_t tlvlen)
+{
+ int r = 1;
+ size_t lenInt = 0;
+ uint16_t sizeRead;
+ block_sig_t *bs;
+ if((bs = calloc(1, sizeof(block_sig_t))) == NULL) {
+ r = RSGTE_OOM;
+ goto done;
+ }
+ CHKr(rsgt_tlvrdHASH_ALGO(fp, &(bs->hashID)));
+ CHKr(rsgt_tlvrdBLOCK_IV(fp, &(bs->iv)));
+ CHKr(rsgt_tlvrdLAST_HASH(fp, &(bs->lastHash)));
+ CHKr(rsgt_tlvrdREC_COUNT(fp, &(bs->recCount), &lenInt));
+ CHKr(rsgt_tlvrdSIG(fp, bs));
+ sizeRead = 2 + 1 /* hash algo TLV */ +
+ 2 + getIVLen(bs) /* iv */ +
+ 2 + 1 + bs->lastHash.len /* last hash */ +
+ 2 + lenInt /* rec-count */ +
+ 4 + bs->sig.der.len /* rfc-3161 */;
+ if(sizeRead != tlvlen) {
+ printf("lenght record error!\n");
+ r = RSGTE_LEN;
+ goto done;
+ }
+ *blocksig = bs;
+ r = 0;
+done: return r;
+}
+
+
+/**
+ * Read the next "object" from file. This usually is
+ * a single TLV, but may be something larger, for
+ * example in case of a block-sig TLV record.
+ * Unknown type records are ignored (or run aborted
+ * if we are not permitted to skip).
+ *
+ * @param[in] fp file pointer for processing
+ * @param[out] tlvtype type of tlv record (top-level for
+ * structured objects.
+ * @param[out] tlvlen length of the tlv record value
+ * @param[out] obj pointer to object; This is a proper
+ * tlv record structure, which must be casted
+ * by the caller according to the reported type.
+ * The object must be freed by the caller (TODO: better way?)
+ *
+ * @returns 0 if ok, something else otherwise
+ */
+int
+rsgt_tlvrd(FILE *fp, uint16_t *tlvtype, uint16_t *tlvlen, void *obj)
+{
+ int r = 1;
+
+ if((r = rsgt_tlvrdTL(fp, tlvtype, tlvlen)) != 0) goto done;
+ switch(*tlvtype) {
+ case 0x0902:
+ r = rsgt_tlvrdBLOCK_SIG(fp, obj, *tlvlen);
+ if(r != 0) goto done;
+ break;
+ }
+ r = 0;
+done: return r;
+}
+
+
+/* if verbose==0, only the first and last two octets are shown,
+ * otherwise everything.
+ */
+static void
+outputHexBlob(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]);
+ } else {
+ printf("%2.2x%2.2x[...]%2.2x%2.2x",
+ blob[0], blob[1],
+ blob[len-2], blob[len-2]);
+ }
+}
+
+/* return if a blob is all zero */
+static inline int
+blobIsZero(uint8_t *blob, uint16_t len)
+{
+ int i;
+ for(i = 0 ; i < len ; ++i)
+ if(blob[i] != 0)
+ return 0;
+ return 1;
+}
+/**
+ * Output a human-readable representation of a block_sig_t
+ * to proviced file pointer. This function is mainly inteded for
+ * debugging purposes or dumping tlv files.
+ *
+ * @param[in] fp file pointer to send output to
+ * @param[in] bsig ponter to block_sig_t to output
+ * @param[in] verbose if 0, abbreviate blob hexdump, else complete
+ */
+void
+rsgt_printBLOCK_SIG(FILE *fp, block_sig_t *bs, uint8_t verbose)
+{
+ fprintf(fp, "Block Signature Record [0x0902]:\n");
+ 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);
+ 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);
+ 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);
+ fputc('\n', fp);
+}
+
+
+/**
+ * Output a human-readable representation of a tlv object.
+ *
+ * @param[in] fp file pointer to send output to
+ * @param[in] tlvtype type of tlv object (record)
+ * @param[in] verbose if 0, abbreviate blob hexdump, else complete
+ */
+void
+rsgt_tlvprint(FILE *fp, uint16_t tlvtype, void *obj, uint8_t verbose)
+{
+ switch(tlvtype) {
+ case 0x0902:
+ rsgt_printBLOCK_SIG(fp, obj, verbose);
+ break;
+ default:fprintf(fp, "unknown tlv record %4.4x\n", tlvtype);
+ break;
+ }
+}