1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
|
/* 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. 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 bKeepRecordHashes;
uint8_t bKeepTreeHashes;
uint64_t blockSizeLimit;
char *timestamper;
void (*errFunc)(void *, unsigned char*);
void *usrptr; /* for error function */
};
typedef struct gtctx_s *gtctx;
typedef struct gtfile_s *gtfile;
typedef struct gterrctx_s gterrctx_t;
typedef struct imprint_s imprint_t;
typedef struct block_sig_s block_sig_t;
typedef struct tlvrecord_s tlvrecord_t;
/* this describes a file, as far as librsgt is concerned */
struct gtfile_s {
/* 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 */
uint8_t disabled; /* permits to disable this file --> set to 1 */
uint64_t blockSizeLimit;
uint8_t *IV; /* initial value for blinding masks */
imprint_t *x_prev; /* last leaf hash (maybe of previous block) --> preserve on term */
unsigned char *sigfilename;
unsigned char *statefilename;
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 members for the associated TLV file */
char tlvBuf[4096];
int tlvIdx; /* current index into tlvBuf */
gtctx ctx;
};
struct tlvrecord_s {
uint16_t tlvtype;
uint16_t tlvlen;
uint8_t hdr[4]; /* the raw header (as persisted to file) */
uint8_t lenHdr; /* length of raw header */
uint8_t data[64*1024]; /* the actual data part (of length tlvlen) */
};
/* The following structure describes the "error context" to be used
* for verification and similiar reader functions. While verifying,
* we need some information (like filenames or block numbers) that
* is not readily available from the other objects (or not even known
* to librsgt). In order to provide meaningful error messages, this
* information must be passed in from the external callers. In order
* to centralize information (and make it more manageable), we use
* ths error context here, which contains everything needed to
* generate good error messages. Members of this structure are
* maintained both by library users (the callers) as well as
* the library itself. Who does what simply depends on who has
* the relevant information.
*/
struct gterrctx_s {
FILE *fp; /**< file for error messages */
char *filename;
uint8_t verbose;
uint64_t recNumInFile;
uint64_t recNum;
uint64_t blkNum;
uint8_t treeLevel;
GTDataHash *computedHash;
GTDataHash *lefthash, *righthash; /* hashes to display if tree hash fails */
imprint_t *fileHash;
int gtstate; /* status from last relevant GT.*() function call */
char *errRec;
char *frstRecInBlk; /* This holds the first message seen inside the current block */
};
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;
};
/* the following defines the gtstate file record. Currently, this record
* is fixed, we may change that over time.
*/
struct rsgtstatefile {
char hdr[8]; /* must be "GTSTAT10" */
uint8_t hashID;
uint8_t lenHash;
/* after that, the hash value is contained within the file */
};
/* Flags and record types for TLV handling */
#define RSGT_FLAG_NONCRIT 0x80
#define RSGT_FLAG_FORWARD 0x40
#define RSGT_FLAG_TLV16 0x20
#define RSGT_TYPE_MASK 0x1f
/* error states */
#define RSGTE_IO 1 /* any kind of io error */
#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 */
#define RSGTE_TS_EXTEND 6/* error extending timestamp */
#define RSGTE_INVLD_RECCNT 7/* mismatch between actual records and records
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) */
#define RSGTE_MISS_BLOCKSIG 16 /* block signature record missing when expected */
#define RSGTE_INVLD_TIMESTAMP 17 /* RFC3161 timestamp is invalid */
#define RSGTE_TS_DERDECODE 18 /* error DER-Decoding a timestamp */
#define RSGTE_TS_DERENCODE 19 /* error DER-Encoding a timestamp */
#define RSGTE_HASH_CREATE 20 /* error creating a hash */
/* the following function maps RSGTE_* state to a string - must be updated
* whenever a new state is added.
* Note: it is thread-safe to call this function, as it returns a pointer
* into constant memory pool.
*/
static inline char *
RSGTE2String(int err)
{
switch(err) {
case 0:
return "success";
case RSGTE_IO:
return "i/o error";
case RSGTE_FMT:
return "data format error";
case RSGTE_INVLTYP:
return "invalid/unexpected tlv record type";
case RSGTE_OOM:
return "out of memory";
case RSGTE_LEN:
return "length record problem";
case RSGTE_TS_EXTEND:
return "error extending timestamp";
case RSGTE_INVLD_RECCNT:
return "mismatch between actual record count and number in block signature record";
case RSGTE_INVLHDR:
return "invalid file header";
case RSGTE_EOF:
return "EOF";
case RSGTE_MISS_REC_HASH:
return "record hash missing";
case RSGTE_MISS_TREE_HASH:
return "tree hash missing";
case RSGTE_INVLD_REC_HASH:
return "record hash mismatch";
case RSGTE_INVLD_TREE_HASH:
return "tree hash mismatch";
case RSGTE_INVLD_REC_HASHID:
return "invalid record hash ID";
case RSGTE_INVLD_TREE_HASHID:
return "invalid tree hash ID";
case RSGTE_MISS_BLOCKSIG:
return "missing block signature record";
case RSGTE_INVLD_TIMESTAMP:
return "RFC3161 timestamp invalid";
case RSGTE_TS_DERDECODE:
return "error DER-decoding RFC3161 timestamp";
case RSGTE_TS_DERENCODE:
return "error DER-encoding RFC3161 timestamp";
case RSGTE_HASH_CREATE:
return "error creating hash";
default:
return "unknown error";
}
}
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(enum GTHashAlgorithm 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 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)
{
switch(sigID) {
case SIGID_RFC3161:
return "RFC3161";
default:return "[unknown]";
}
}
static inline uint16_t
getIVLen(block_sig_t *bs)
{
return hashOutputLengthOctets(bs->hashID);
}
static inline void
rsgtSetTimestamper(gtctx ctx, char *timestamper)
{
free(ctx->timestamper);
ctx->timestamper = strdup(timestamper);
}
static inline void
rsgtSetBlockSizeLimit(gtctx ctx, uint64_t limit)
{
ctx->blockSizeLimit = limit;
}
static inline void
rsgtSetKeepRecordHashes(gtctx ctx, int val)
{
ctx->bKeepRecordHashes = val;
}
static inline void
rsgtSetKeepTreeHashes(gtctx ctx, int val)
{
ctx->bKeepTreeHashes = val;
}
int rsgtSetHashFunction(gtctx ctx, char *algName);
int rsgtInit(char *usragent);
void rsgtExit(void);
gtctx rsgtCtxNew(void);
void rsgtsetErrFunc(gtctx ctx, void (*func)(void*, unsigned char *), void *usrptr);
gtfile rsgtCtxOpenFile(gtctx ctx, unsigned char *logfn);
int rsgtfileDestruct(gtfile gf);
void rsgtCtxDel(gtctx ctx);
void sigblkInit(gtfile gf);
int sigblkAddRecord(gtfile gf, const unsigned char *rec, const size_t len);
int sigblkFinish(gtfile gf);
imprint_t * rsgtImprintFromGTDataHash(GTDataHash *hash);
void rsgtimprintDel(imprint_t *imp);
/* reader functions */
int rsgt_tlvrdHeader(FILE *fp, unsigned char *hdr);
int rsgt_tlvrd(FILE *fp, tlvrecord_t *rec, void *obj);
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, FILE *nsigfp, unsigned char *rec, size_t len, gterrctx_t *ectx);
int verifyBLOCK_SIG(block_sig_t *bs, gtfile gf, FILE *sigfp, FILE *nsigfp, uint8_t bExtend, gterrctx_t *ectx);
void rsgt_errctxInit(gterrctx_t *ectx);
void rsgt_errctxExit(gterrctx_t *ectx);
void rsgt_errctxSetErrRec(gterrctx_t *ectx, char *rec);
void rsgt_errctxFrstRecInBlk(gterrctx_t *ectx, char *rec);
void rsgt_objfree(uint16_t tlvtype, void *obj);
/* TODO: replace these? */
int hash_m(gtfile gf, GTDataHash **m);
int hash_r(gtfile gf, GTDataHash **r, const unsigned char *rec, const size_t len);
int hash_node(gtfile gf, GTDataHash **node, GTDataHash *m, GTDataHash *r, uint8_t level);
extern char *rsgt_read_puburl; /**< url of publication server */
extern uint8_t rsgt_read_showVerified;
#endif /* #ifndef INCLUDED_LIBRSGT_H */
|