summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2013-03-17 13:06:02 +0100
committerRainer Gerhards <rgerhards@adiscon.com>2013-03-17 13:06:02 +0100
commitd2467c38d42f590deecd807741324fc0e5522a8a (patch)
treec9d56cee1e0119ba9bd5f516a68bd7e1269712fe /runtime
parent44b4922825df794f678cd4ad18d940ff114b943f (diff)
downloadrsyslog-d2467c38d42f590deecd807741324fc0e5522a8a.tar.gz
rsyslog-d2467c38d42f590deecd807741324fc0e5522a8a.tar.bz2
rsyslog-d2467c38d42f590deecd807741324fc0e5522a8a.zip
logsig: milestone/verfier: record hashes are verified
Diffstat (limited to 'runtime')
-rw-r--r--runtime/librsgt.c6
-rw-r--r--runtime/librsgt.h33
-rw-r--r--runtime/librsgt_read.c126
-rw-r--r--runtime/lmsig_gt.c12
4 files changed, 172 insertions, 5 deletions
diff --git a/runtime/librsgt.c b/runtime/librsgt.c
index 83a2fe05..e49011f4 100644
--- a/runtime/librsgt.c
+++ b/runtime/librsgt.c
@@ -514,7 +514,7 @@ bufAddLevel(uchar *buf, size_t *len, uint8_t level)
}
-static void
+void
hash_m(gtfile gf, GTDataHash **m)
{
#warning Overall: check GT API return states!
@@ -527,7 +527,7 @@ hash_m(gtfile gf, GTDataHash **m)
GTDataHash_create(gf->hashAlg, concatBuf, len, m);
}
-static inline void
+void
hash_r(gtfile gf, GTDataHash **r, const uchar *rec, const size_t len)
{
// r = hash(canonicalize(rec));
@@ -535,7 +535,7 @@ hash_r(gtfile gf, GTDataHash **r, const uchar *rec, const size_t len)
}
-static void
+void
hash_node(gtfile gf, GTDataHash **node, GTDataHash *m, GTDataHash *r,
uint8_t level)
{
diff --git a/runtime/librsgt.h b/runtime/librsgt.h
index d9d221ea..35ee96b5 100644
--- a/runtime/librsgt.h
+++ b/runtime/librsgt.h
@@ -120,6 +120,12 @@ struct rsgtstatefile {
given in block-sig record */
#define RSGTE_INVLHDR 8/* invalid file header */
#define RSGTE_EOF 9 /* specific EOF */
+#define RSGTE_MISS_REC_HASH 10 /* record hash missing when expected */
+#define RSGTE_MISS_TREE_HASH 11 /* tree hash missing when expected */
+#define RSGTE_INVLD_REC_HASH 12 /* invalid record hash (failed verification) */
+#define RSGTE_INVLD_TREE_HASH 13 /* invalid tree hash (failed verification) */
+#define RSGTE_INVLD_REC_HASHID 14 /* invalid record hash ID (failed verification) */
+#define RSGTE_INVLD_TREE_HASHID 15 /* invalid tree hash ID (failed verification) */
static inline uint16_t
@@ -180,6 +186,26 @@ hashAlgName(uint8_t hashID)
default:return "[unknown]";
}
}
+static inline enum GTHashAlgorithm
+hashID2Alg(uint8_t hashID)
+{
+ switch(hashID) {
+ case 0x00:
+ return GT_HASHALG_SHA1;
+ case 0x02:
+ return GT_HASHALG_RIPEMD160;
+ case 0x03:
+ return GT_HASHALG_SHA224;
+ case 0x01:
+ return GT_HASHALG_SHA256;
+ case 0x04:
+ return GT_HASHALG_SHA384;
+ case 0x05:
+ return GT_HASHALG_SHA512;
+ default:
+ return 0xff;
+ }
+}
static inline char *
sigTypeName(uint8_t sigID)
{
@@ -233,5 +259,12 @@ 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);
+gtfile rsgt_vrfyConstruct_gf(void);
+void rsgt_vrfyBlkInit(gtfile gf, block_sig_t *bs, uint8_t bHasRecHashes, uint8_t bHasIntermedHashes);
+int rsgt_vrfy_nextRec(block_sig_t *bs, gtfile gf, FILE *sigfp, unsigned char *rec, size_t lenRec);
+/* TODO: replace these? */
+void hash_m(gtfile gf, GTDataHash **m);
+void hash_r(gtfile gf, GTDataHash **r, const unsigned char *rec, const size_t len);
+void hash_node(gtfile gf, GTDataHash **node, GTDataHash *m, GTDataHash *r, uint8_t level);
#endif /* #ifndef INCLUDED_LIBRSGT_H */
diff --git a/runtime/librsgt_read.c b/runtime/librsgt_read.c
index 961e50c5..ca52cb93 100644
--- a/runtime/librsgt_read.c
+++ b/runtime/librsgt_read.c
@@ -277,6 +277,22 @@ rsgt_tlvrdIMPRINT(FILE *fp, imprint_t **imprint, uint16_t tlvlen)
done: return r;
}
+static int
+rsgt_tlvrdRecHash(FILE *fp, imprint_t **imp)
+{
+ int r;
+ uint16_t tlvtype, tlvlen;
+
+ if((r = rsgt_tlvrdTL(fp, &tlvtype, &tlvlen)) != 0) goto done;
+printf("read tlvtype %4.4x\n", tlvtype);
+ if(tlvtype != 0x0900) {
+ r = RSGTE_MISS_REC_HASH;
+ goto done;
+ }
+ if((r = rsgt_tlvrdIMPRINT(fp, imp, tlvlen)) != 0) goto done;
+ r = 0;
+done: return r;
+}
/**;
* Read the next "object" from file. This usually is
@@ -528,3 +544,113 @@ rsgt_chkFileHdr(FILE *fp, char *expect)
done:
return r;
}
+
+gtfile
+rsgt_vrfyConstruct_gf(void)
+{
+ gtfile gf;
+ if((gf = calloc(1, sizeof(struct gtfile_s))) == NULL)
+ goto done;
+ gf->x_prev = NULL;
+
+done: return gf;
+}
+
+void
+rsgt_vrfyBlkInit(gtfile gf, block_sig_t *bs, uint8_t bHasRecHashes, uint8_t bHasIntermedHashes)
+{
+printf("bs->hashID %d\n", bs->hashID);
+ gf->hashAlg = hashID2Alg(bs->hashID);
+ gf->bKeepRecordHashes = bHasRecHashes;
+ gf->bKeepTreeHashes = bHasIntermedHashes;
+ free(gf->IV);
+ gf->IV = malloc(getIVLen(bs));
+ memcpy(gf->IV, bs->iv, getIVLen(bs));
+}
+
+static int
+rsgt_vrfy_chkRecHash(gtfile gf, FILE *sigfp, GTDataHash *recHash)
+{
+ int r = 0;
+ imprint_t *imp;
+
+ if(!gf->bKeepRecordHashes)
+ goto done;
+ if((r = rsgt_tlvrdRecHash(sigfp, &imp)) != 0)
+ goto done;
+ if(imp->hashID != hashIdentifier(gf->hashAlg)) {
+ r = RSGTE_INVLD_REC_HASHID;
+ goto done;
+ }
+printf("imp hash:");
+outputHexBlob(stdout, imp->data, hashOutputLengthOctets(imp->hashID), 1);
+printf("\nrec hash:");
+outputHexBlob(stdout, recHash->digest, hashOutputLengthOctets(imp->hashID), 1);
+printf("\n");
+ if(memcmp(imp->data, recHash->digest,
+ hashOutputLengthOctets(imp->hashID))) {
+ r = RSGTE_INVLD_REC_HASH;
+ goto done;
+ }
+printf("record hash is OK\n");
+ r = 0;
+done:
+ return r;
+}
+
+int
+rsgt_vrfy_nextRec(block_sig_t *bs, gtfile gf, FILE *sigfp, unsigned char *rec,
+ size_t len)
+{
+ int r = 0;
+ GTDataHash *x; /* current hash */
+ GTDataHash *m, *recHash, *t;
+ uint8_t j;
+
+printf("hasRecHash %d, verify: %s", gf->bKeepRecordHashes, rec);
+ hash_m(gf, &m);
+ hash_r(gf, &recHash, rec, len);
+ if(gf->bKeepRecordHashes) {
+ r = rsgt_vrfy_chkRecHash(gf, sigfp, recHash);
+ if(r != 0) goto done;
+ }
+ hash_node(gf, &x, m, recHash, 1); /* hash leaf */
+ /* persists x here if Merkle tree needs to be persisted! */
+ //if(gf->bKeepTreeHashes)
+ //tlvWriteHash(gf, 0x0901, x);
+ /* add x to the forest as new leaf, update roots list */
+ t = x;
+ 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(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(gf->bKeepTreeHashes)
+ //tlvWriteHash(gf, 0x0901, t);
+ }
+ }
+ if(t != NULL) {
+ /* new level, append "at the top" */
+ gf->roots_hash[gf->nRoots] = t;
+ gf->roots_valid[gf->nRoots] = 1;
+ ++gf->nRoots;
+ assert(gf->nRoots < MAX_ROOTS);
+ t = NULL;
+ }
+ 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(recHash);
+done:
+ return r;
+}
diff --git a/runtime/lmsig_gt.c b/runtime/lmsig_gt.c
index 021cd9f8..54a795a1 100644
--- a/runtime/lmsig_gt.c
+++ b/runtime/lmsig_gt.c
@@ -130,12 +130,20 @@ dbgprintf("DDDD: onFileOpen: %s\n", fn);
RETiRet;
}
+/* Note: we assume that the record is terminated by a \n.
+ * As of the GuardTime paper, \n is not part of the signed
+ * message, so we subtract one from the record size. This
+ * may cause issues with non-standard formats, but let's
+ * see how things evolve (the verifier will not work in
+ * any case when the records are not \n delimited...).
+ * rgerhards, 2013-03-17
+ */
static rsRetVal
OnRecordWrite(void *pF, uchar *rec, rs_size_t lenRec)
{
DEFiRet;
-dbgprintf("DDDD: onRecordWrite (%d): %s\n", lenRec, rec);
- sigblkAddRecord(pF, rec, lenRec);
+dbgprintf("DDDD: onRecordWrite (%d): %s\n", lenRec-1, rec);
+ sigblkAddRecord(pF, rec, lenRec-1);
RETiRet;
}