1 /* lib_ksils12.c - rsyslog's KSI-LS12 support library
2 *
3 * Regarding the online algorithm for Merkle tree signing. Expected
4 * calling sequence is:
5 *
6 * sigblkConstruct
7 * for each signature block:
8 * sigblkInitKSI
9 * for each record:
10 * sigblkAddRecordKSI
11 * sigblkFinishKSI
12 * sigblkDestruct
13 *
14 * Obviously, the next call after sigblkFinsh must either be to
15 * sigblkInitKSI or sigblkDestruct (if no more signature blocks are
16 * to be emitted, e.g. on file close). sigblkDestruct saves state
17 * information (most importantly last block hash) and sigblkConstruct
18 * reads (or initilizes if not present) it.
19 *
20 * Copyright 2013-2018 Adiscon GmbH and Guardtime, Inc.
21 *
22 * This file is part of rsyslog.
23 *
24 * Licensed under the Apache License, Version 2.0 (the "License");
25 * you may not use this file except in compliance with the License.
26 * You may obtain a copy of the License at
27 *
28 * http://www.apache.org/licenses/LICENSE-2.0
29 * -or-
30 * see COPYING.ASL20 in the source distribution
31 *
32 * Unless required by applicable law or agreed to in writing, software
33 * distributed under the License is distributed on an "AS IS" BASIS,
34 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35 * See the License for the specific language governing permissions and
36 * limitations under the License.
37 */
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <errno.h>
44 #include <string.h>
45 #include <stdint.h>
46 #include <assert.h>
47 #include <unistd.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <stdarg.h>
52 #include <limits.h>
53
54 #include <ksi/ksi.h>
55 #include <ksi/tlv_element.h>
56 #include <ksi/hash.h>
57 #include <ksi/net_async.h>
58 #include <ksi/net_ha.h>
59 #include <ksi/net_uri.h>
60 #include <ksi/signature_builder.h>
61 #include "rsyslog.h"
62 #include "errmsg.h"
63 #include "lib_ksils12.h"
64 #include "lib_ksi_queue.h"
65
66 #ifndef VERSION
67 #define VERSION "no-version"
68 #endif
69
70 #define KSI_BUF_SIZE 4096
71
72 static const char *blockFileSuffix = ".logsig.parts/blocks.dat";
73 static const char *sigFileSuffix = ".logsig.parts/block-signatures.dat";
74 static const char *ls12FileSuffix = ".logsig";
75 static const char *blockCloseReason = "com.guardtime.blockCloseReason";
76
77
78 #define LS12_FILE_HEADER "LOGSIG12"
79 #define LS12_BLOCKFILE_HEADER "LOG12BLK"
80 #define LS12_SIGFILE_HEADER "LOG12SIG"
81 #define LS12_SIGNATURE_TIMEOUT 60
82
83 /* Worker queue item type identifier */
84 typedef enum QITEM_type_en {
85 QITEM_SIGNATURE_REQUEST = 0x00,
86 QITEM_CLOSE_FILE,
87 QITEM_NEW_FILE,
88 QITEM_QUIT
89 } QITEM_type;
90
91 /* Worker queue item status identifier */
92 typedef enum QITEM_status_en {
93 /* State assigned to any item added to queue (initial state). */
94 QITEM_WAITING = 0x00,
95
96 /* State assigned to #QITEM_SIGNATURE_REQUEST item when it is sent out. */
97 QITEM_SENT,
98
99 /* State assigned to #QITEM_SIGNATURE_REQUEST item when request failed or succeeded. */
100 QITEM_DONE
101 } QITEM_status;
102
103
104 /* Worker queue job item */
105 typedef struct QueueItem_st {
106 QITEM_type type;
107 QITEM_status status;
108 KSI_DataHash *root;
109 FILE *file; /* To keep track of the target signature file. */
110 uint64_t intarg1; /* Block time limit or record count or not used. */
111 uint64_t intarg2; /* Level of the sign request or not used. */
112 KSI_AsyncHandle *respHandle;
113 int ksi_status;
114 time_t request_time;
115 } QueueItem;
116
117 static bool queueAddCloseFile(rsksictx ctx, ksifile kf);
118 static bool queueAddNewFile(rsksictx ctx, ksifile kf);
119 static bool queueAddQuit(rsksictx ctx);
120 static bool queueAddSignRequest(rsksictx ctx, ksifile kf, KSI_DataHash *root, unsigned level);
121 static int sigblkFinishKSINoSignature(ksifile ksi, const char *reason);
122
123 void *signer_thread(void *arg);
124
125 static void __attribute__((format(printf, 2, 3)))
report(rsksictx ctx,const char * errmsg,...)126 report(rsksictx ctx, const char *errmsg, ...) {
127 char buf[1024];
128 int r;
129 va_list args;
130 va_start(args, errmsg);
131
132 r = vsnprintf(buf, sizeof (buf), errmsg, args);
133 buf[sizeof(buf)-1] = '\0';
134 va_end(args);
135
136 if(ctx->logFunc == NULL)
137 return;
138
139 if(r>0 && r<(int)sizeof(buf))
140 ctx->logFunc(ctx->usrptr, (uchar*)buf);
141 else
142 ctx->logFunc(ctx->usrptr, (uchar*)errmsg);
143 }
144
145 static void
reportErr(rsksictx ctx,const char * const errmsg)146 reportErr(rsksictx ctx, const char *const errmsg)
147 {
148 if(ctx->errFunc == NULL)
149 goto done;
150 ctx->errFunc(ctx->usrptr, (uchar*)errmsg);
151 done: return;
152 }
153
154 static const char *
level2str(int level)155 level2str(int level) {
156 switch (level) {
157 case KSI_LOG_DEBUG: return "DEBUG";
158 case KSI_LOG_INFO: return "INFO";
159 case KSI_LOG_NOTICE: return "NOTICE";
160 case KSI_LOG_WARN: return "WARN";
161 case KSI_LOG_ERROR: return "ERROR";
162 default: return "UNKNOWN LOG LEVEL";
163 }
164 }
165
166 void
reportKSIAPIErr(rsksictx ctx,ksifile ksi,const char * apiname,int ecode)167 reportKSIAPIErr(rsksictx ctx, ksifile ksi, const char *apiname, int ecode)
168 {
169 char errbuf[4096];
170 char ksi_errbuf[4096];
171 KSI_ERR_getBaseErrorMessage(ctx->ksi_ctx, ksi_errbuf, sizeof(ksi_errbuf), NULL, NULL);
172 snprintf(errbuf, sizeof(errbuf), "%s[%s:%d]: %s (%s)",
173 (ksi == NULL) ? (uchar*) "" : ksi->blockfilename,
174 apiname, ecode, KSI_getErrorString(ecode), ksi_errbuf);
175
176 errbuf[sizeof(errbuf)-1] = '\0';
177 reportErr(ctx, errbuf);
178 }
179
180 void
rsksisetErrFunc(rsksictx ctx,void (* func)(void *,uchar *),void * usrptr)181 rsksisetErrFunc(rsksictx ctx, void (*func)(void*, uchar *), void *usrptr)
182 {
183 ctx->usrptr = usrptr;
184 ctx->errFunc = func;
185 }
186
187 void
rsksisetLogFunc(rsksictx ctx,void (* func)(void *,uchar *),void * usrptr)188 rsksisetLogFunc(rsksictx ctx, void (*func)(void*, uchar *), void *usrptr)
189 {
190 ctx->usrptr = usrptr;
191 ctx->logFunc = func;
192 }
193
194 static ksifile
rsksifileConstruct(rsksictx ctx)195 rsksifileConstruct(rsksictx ctx) {
196 ksifile ksi = NULL;
197 if ((ksi = calloc(1, sizeof (struct ksifile_s))) == NULL)
198 goto done;
199 ksi->ctx = ctx;
200 ksi->hashAlg = ctx->hashAlg;
201 ksi->blockTimeLimit = ctx->blockTimeLimit;
202 ksi->blockSizeLimit = 1 << (ctx->effectiveBlockLevelLimit - 1);
203 ksi->bKeepRecordHashes = ctx->bKeepRecordHashes;
204 ksi->bKeepTreeHashes = ctx->bKeepTreeHashes;
205 ksi->lastLeaf[0] = ctx->hashAlg;
206
207 done:
208 return ksi;
209 }
210
211 /* return the actual length in to-be-written octets of an integer */
212 static uint8_t
tlvGetIntSize(uint64_t val)213 tlvGetIntSize(uint64_t val) {
214 uint8_t n = 0;
215 while (val != 0) {
216 val >>= 8;
217 n++;
218 }
219 return n;
220 }
221
222 static int
tlvWriteOctetString(FILE * f,const uint8_t * data,uint16_t len)223 tlvWriteOctetString(FILE *f, const uint8_t *data, uint16_t len) {
224 if (fwrite(data, len, 1, f) != 1)
225 return RSGTE_IO;
226 return 0;
227 }
228
229 static int
tlvWriteHeader8(FILE * f,int flags,uint8_t tlvtype,int len)230 tlvWriteHeader8(FILE *f, int flags, uint8_t tlvtype, int len) {
231 unsigned char buf[2];
232 assert((flags & RSGT_TYPE_MASK) == 0);
233 assert((tlvtype & RSGT_TYPE_MASK) == tlvtype);
234 buf[0] = (flags & ~RSGT_FLAG_TLV16) | tlvtype;
235 buf[1] = len & 0xff;
236
237 return tlvWriteOctetString(f, buf, 2);
238 }
239
240 static int
tlvWriteHeader16(FILE * f,int flags,uint16_t tlvtype,uint16_t len)241 tlvWriteHeader16(FILE *f, int flags, uint16_t tlvtype, uint16_t len)
242 {
243 uint16_t typ;
244 unsigned char buf[4];
245 assert((flags & RSGT_TYPE_MASK) == 0);
246 assert((tlvtype >> 8 & RSGT_TYPE_MASK) == (tlvtype >> 8));
247 typ = ((flags | RSGT_FLAG_TLV16) << 8) | tlvtype;
248
249 buf[0] = typ >> 8;
250 buf[1] = typ & 0xff;
251 buf[2] = (len >> 8) & 0xff;
252 buf[3] = len & 0xff;
253
254 return tlvWriteOctetString(f, buf, 4);
255 }
256
257 static int
tlvGetHeaderSize(uint16_t tag,size_t size)258 tlvGetHeaderSize(uint16_t tag, size_t size) {
259 if (tag <= RSGT_TYPE_MASK && size <= 0xff)
260 return 2;
261 if ((tag >> 8) <= RSGT_TYPE_MASK && size <= 0xffff)
262 return 4;
263 return 0;
264 }
265
266 static int
tlvWriteHeader(FILE * f,int flags,uint16_t tlvtype,uint16_t len)267 tlvWriteHeader(FILE *f, int flags, uint16_t tlvtype, uint16_t len) {
268 int headersize = tlvGetHeaderSize(tlvtype, flags);
269 if (headersize == 2)
270 return tlvWriteHeader8(f, flags, tlvtype, len);
271 else if (headersize == 4)
272 return tlvWriteHeader16(f, flags, tlvtype, len);
273 else
274 return 0;
275 }
276
277 static int
tlvWriteOctetStringTLV(FILE * f,int flags,uint16_t tlvtype,const uint8_t * data,uint16_t len)278 tlvWriteOctetStringTLV(FILE *f, int flags, uint16_t tlvtype, const uint8_t *data, uint16_t len) {
279 if (tlvWriteHeader(f, flags, tlvtype, len) != 0)
280 return RSGTE_IO;
281
282 if (fwrite(data, len, 1, f) != 1)
283 return RSGTE_IO;
284
285 return 0;
286 }
287
288 static int
tlvWriteInt64TLV(FILE * f,int flags,uint16_t tlvtype,uint64_t val)289 tlvWriteInt64TLV(FILE *f, int flags, uint16_t tlvtype, uint64_t val) {
290 unsigned char buf[8];
291 uint8_t count = tlvGetIntSize(val);
292 uint64_t nTmp;
293
294 if (tlvWriteHeader(f, flags, tlvtype, count) != 0)
295 return RSGTE_IO;
296
297 nTmp = val;
298 for (int i = count - 1; i >= 0; i--) {
299 buf[i] = 0xFF & nTmp;
300 nTmp = nTmp >> 8;
301 }
302
303 if (fwrite(buf, count, 1, f) != 1)
304 return RSGTE_IO;
305
306 return 0;
307 }
308
309 static int
tlvWriteHashKSI(ksifile ksi,uint16_t tlvtype,KSI_DataHash * rec)310 tlvWriteHashKSI(ksifile ksi, uint16_t tlvtype, KSI_DataHash *rec) {
311 int r;
312 const unsigned char *imprint;
313 size_t imprint_len;
314 r = KSI_DataHash_getImprint(rec, &imprint, &imprint_len);
315 if (r != KSI_OK) {
316 reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_getImprint", r);
317 return r;
318 }
319
320 return tlvWriteOctetStringTLV(ksi->blockFile, 0, tlvtype, imprint, imprint_len);
321 }
322
323 static int
tlvWriteBlockHdrKSI(ksifile ksi)324 tlvWriteBlockHdrKSI(ksifile ksi) {
325 unsigned tlvlen;
326 uint8_t hash_algo = ksi->hashAlg;
327 int r;
328
329 tlvlen = 2 + 1 /* hash algo TLV */ +
330 2 + KSI_getHashLength(ksi->hashAlg) /* iv */ +
331 2 + KSI_getHashLength(ksi->lastLeaf[0]) + 1;
332 /* last hash */;
333
334 /* write top-level TLV object block-hdr */
335 CHKr(tlvWriteHeader(ksi->blockFile, 0x00, 0x0901, tlvlen));
336
337 /* hash-algo */
338 CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x01, &hash_algo, 1));
339
340 /* block-iv */
341 CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x02,
342 ksi->IV, KSI_getHashLength(ksi->hashAlg)));
343
344 /* last-hash */
345 CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x03,
346 ksi->lastLeaf, KSI_getHashLength(ksi->lastLeaf[0]) + 1));
347 done:
348 return r;
349 }
350
351 static int
tlvWriteKSISigLS12(FILE * outfile,size_t record_count,uchar * der,uint16_t lenDer)352 tlvWriteKSISigLS12(FILE *outfile, size_t record_count, uchar *der, uint16_t lenDer) {
353 int r = 0;
354 int totalSize = 2 + tlvGetIntSize(record_count) + 4 + lenDer;
355
356 CHKr(tlvWriteHeader(outfile, 0x00, 0x0904, totalSize));
357 CHKr(tlvWriteInt64TLV(outfile, 0x00, 0x01, record_count));
358 CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x0905, der, lenDer));
359 done:
360 return r;
361 }
362
363 static int
tlvWriteNoSigLS12(FILE * outfile,size_t record_count,const KSI_DataHash * hash,const char * errorText)364 tlvWriteNoSigLS12(FILE *outfile, size_t record_count, const KSI_DataHash *hash, const char *errorText) {
365 int r = 0;
366 int totalSize = 0;
367 int noSigSize = 0;
368 const unsigned char *imprint = NULL;
369 size_t imprintLen = 0;
370
371 KSI_DataHash_getImprint(hash, &imprint, &imprintLen);
372
373 noSigSize = 2 + imprintLen + (errorText ? (2 + strlen(errorText) + 1) : 0);
374 totalSize = 2 + tlvGetIntSize(record_count) + 2 + noSigSize;
375
376 CHKr(tlvWriteHeader(outfile, 0x00, 0x0904, totalSize));
377 CHKr(tlvWriteInt64TLV(outfile, 0x00, 0x01, record_count));
378 CHKr(tlvWriteHeader(outfile, 0x00, 0x02, noSigSize));
379 CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x01, imprint, imprintLen));
380 if (errorText)
381 CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x02, (uint8_t*) errorText, strlen(errorText) + 1));
382 done:
383 return r;
384 }
385
386 static int
tlvCreateMetadata(ksifile ksi,uint64_t record_index,const char * key,const char * value,unsigned char * buffer,size_t * len)387 tlvCreateMetadata(ksifile ksi, uint64_t record_index, const char *key,
388 const char *value, unsigned char *buffer, size_t *len) {
389 int r = 0;
390 KSI_TlvElement *metadata = NULL, *attrib_tlv = NULL;
391 KSI_Utf8String *key_tlv = NULL, *value_tlv = NULL;
392 KSI_Integer *index_tlv = NULL;
393
394 CHKr(KSI_TlvElement_new(&metadata));
395 metadata->ftlv.tag = 0x0911;
396
397 CHKr(KSI_Integer_new(ksi->ctx->ksi_ctx, record_index, &index_tlv));
398 CHKr(KSI_TlvElement_setInteger(metadata, 0x01, index_tlv));
399
400 CHKr(KSI_TlvElement_new(&attrib_tlv));
401 attrib_tlv->ftlv.tag = 0x02;
402
403 CHKr(KSI_Utf8String_new(ksi->ctx->ksi_ctx, key, strlen(key) + 1, &key_tlv));
404 CHKr(KSI_TlvElement_setUtf8String(attrib_tlv, 0x01, key_tlv));
405
406 CHKr(KSI_Utf8String_new(ksi->ctx->ksi_ctx, value, strlen(value) + 1, &value_tlv));
407 CHKr(KSI_TlvElement_setUtf8String(attrib_tlv, 0x02, value_tlv));
408
409 CHKr(KSI_TlvElement_setElement(metadata, attrib_tlv));
410
411 CHKr(KSI_TlvElement_serialize(metadata, buffer, 0xFFFF, len, 0));
412
413 done:
414 if (metadata) KSI_TlvElement_free(metadata);
415 if (attrib_tlv) KSI_TlvElement_free(attrib_tlv);
416 if (key_tlv) KSI_Utf8String_free(key_tlv);
417 if (value_tlv) KSI_Utf8String_free(value_tlv);
418 if (index_tlv) KSI_Integer_free(index_tlv);
419
420 return r;
421 }
422
423 #define KSI_FILE_AMOUNT_INC 32
424
425 static int
rsksiExpandRegisterIfNeeded(rsksictx ctx,size_t inc)426 rsksiExpandRegisterIfNeeded(rsksictx ctx, size_t inc) {
427 int ret = RSGTE_INTERNAL;
428 ksifile *tmp = NULL;
429
430 if (ctx == NULL || inc == 0) {
431 return RSGTE_INTERNAL;
432 }
433
434 if (ctx->ksiCount < ctx->ksiCapacity) {
435 return RSGTE_SUCCESS;
436 }
437
438 /* If needed allocate memory for the buffer. */
439 tmp = (ksifile*)realloc(ctx->ksi, sizeof(ksifile) * (ctx->ksiCapacity + inc));
440 if (tmp == NULL) {
441 ret = RSGTE_OOM;
442 goto done;
443 }
444
445 /* Make sure that allocated pointers are all set to NULL. */
446 memset(tmp + ctx->ksiCapacity, 0, sizeof(ksifile) * inc);
447
448 /* Update buffer capacity. */
449 ctx->ksiCapacity += inc;
450 ctx->ksi = tmp;
451 tmp = NULL;
452 ret = RSGTE_SUCCESS;
453
454 done:
455 free(tmp);
456 return ret;
457 }
458
459 static int
rsksiRegisterKsiFile(rsksictx ctx,ksifile ksi)460 rsksiRegisterKsiFile(rsksictx ctx, ksifile ksi) {
461 int ret = RSGTE_INTERNAL;
462
463 if (ctx == NULL || ksi == NULL) {
464 return RSGTE_INTERNAL;
465 }
466
467 /* To be extra sure that ksifile buffer is initialized correctly, clear variables. */
468 if (ctx->ksi == NULL) {
469 ctx->ksiCount = 0;
470 ctx->ksiCapacity = 0;
471 }
472
473 ret = rsksiExpandRegisterIfNeeded(ctx, KSI_FILE_AMOUNT_INC);
474 if (ret != RSGTE_SUCCESS) goto done;
475
476 ctx->ksi[ctx->ksiCount] = ksi;
477 ctx->ksiCount++;
478 ret = RSGTE_SUCCESS;
479
480 done:
481 return ret;
482 }
483
484 static int
rsksiDeregisterKsiFile(rsksictx ctx,ksifile ksi)485 rsksiDeregisterKsiFile(rsksictx ctx, ksifile ksi) {
486 int ret = RSGTE_INTERNAL;
487 size_t i = 0;
488
489 if (ctx == NULL || ksi == NULL) {
490 return RSGTE_INTERNAL;
491 }
492
493
494 for (i = 0; i < ctx->ksiCount; i++) {
495 if (ctx->ksi[i] != NULL && ctx->ksi[i] == ksi) {
496 size_t lastElement = ctx->ksiCount - 1;
497
498 if (i != lastElement) {
499 ctx->ksi[i] = ctx->ksi[lastElement];
500 }
501
502 ctx->ksi[lastElement] = NULL;
503
504 ctx->ksiCount--;
505 ret = RSGTE_SUCCESS;
506 goto done;
507 }
508 }
509
510 done:
511 return ret;
512 }
513
514 /* support for old platforms - graceful degrade */
515 #ifndef O_CLOEXEC
516 #define O_CLOEXEC 0
517 #endif
518 /* read rsyslog log state file; if we cannot access it or the
519 * contents looks invalid, we flag it as non-present (and thus
520 * begin a new hash chain).
521 * The context is initialized accordingly.
522 */
523 static bool
ksiReadStateFile(ksifile ksi)524 ksiReadStateFile(ksifile ksi) {
525 int fd = -1;
526 struct rsksistatefile sf;
527 bool ret = false;
528
529 fd = open((char*)ksi->statefilename, O_RDONLY|O_NOCTTY|O_CLOEXEC, 0600);
530 if (fd == -1)
531 goto done;
532
533 if (read(fd, &sf, sizeof (sf)) != sizeof (sf)) goto done;
534 if (strncmp(sf.hdr, "KSISTAT10", 9)) goto done;
535
536 if (KSI_getHashLength(sf.hashID) != sf.lenHash ||
537 KSI_getHashLength(sf.hashID) > KSI_MAX_IMPRINT_LEN - 1)
538 goto done;
539
540 if (read(fd, ksi->lastLeaf + 1, sf.lenHash) != sf.lenHash)
541 goto done;
542
543 ksi->lastLeaf[0] = sf.hashID;
544 ret = true;
545
546 done:
547 if (!ret) {
548 memset(ksi->lastLeaf, 0, sizeof (ksi->lastLeaf));
549 ksi->lastLeaf[0] = ksi->hashAlg;
550 }
551
552 if (fd != -1)
553 close(fd);
554 return ret;
555 }
556
557 /* persist all information that we need to re-open and append
558 * to a log signature file.
559 */
560 static void
ksiWwriteStateFile(ksifile ksi)561 ksiWwriteStateFile(ksifile ksi)
562 {
563 int fd;
564 struct rsksistatefile sf;
565
566 fd = open((char*)ksi->statefilename,
567 O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, ksi->ctx->fCreateMode);
568 if(fd == -1)
569 goto done;
570 if (ksi->ctx->fileUID != (uid_t) - 1 || ksi->ctx->fileGID != (gid_t) - 1) {
571 /* we need to set owner/group */
572 if (fchown(fd, ksi->ctx->fileUID, ksi->ctx->fileGID) != 0) {
573 report(ksi->ctx, "lmsig_ksi: chown for file '%s' failed: %s",
574 ksi->statefilename, strerror(errno));
575 }
576 }
577
578 memcpy(sf.hdr, "KSISTAT10", 9);
579 sf.hashID = ksi->hashAlg;
580 sf.lenHash = KSI_getHashLength(ksi->lastLeaf[0]);
581 /* if the write fails, we cannot do anything against that. We check
582 * the condition just to keep the compiler happy.
583 */
584 if(write(fd, &sf, sizeof(sf))){};
585 if (write(fd, ksi->lastLeaf + 1, sf.lenHash)) {
586 };
587 close(fd);
588 done:
589 return;
590 }
591
592
593 static int
ksiCloseSigFile(ksifile ksi)594 ksiCloseSigFile(ksifile ksi) {
595 fclose(ksi->blockFile);
596 ksi->blockFile = NULL;
597 if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS)
598 queueAddCloseFile(ksi->ctx, ksi);
599
600 ksiWwriteStateFile(ksi);
601 return 0;
602 }
603
mkpath(char * path,mode_t mode,uid_t uid,gid_t gid)604 static int mkpath(char* path, mode_t mode, uid_t uid, gid_t gid) {
605
606 if(path == NULL)
607 return 1;
608
609 for (char *p = strchr(path + 1, '/'); p; p = strchr(p + 1, '/')) {
610 *p = '\0';
611 if (mkdir(path, mode) == 0) {
612 if (uid != (uid_t) -1 || gid != (uid_t) -1) {
613 if (chown(path, uid, gid)) {
614 LogError(errno, RS_RET_IO_ERROR,
615 "ksils12 signatures: could not change to "
616 "configured owner - files may be unaccessible");
617 }
618 }
619 }
620 else if (errno != EEXIST) {
621 *p = '/';
622 return -1;
623 }
624
625 *p = '/';
626 }
627 return 0;
628 }
629
630 static FILE*
ksiCreateFile(rsksictx ctx,const char * path,uid_t uid,gid_t gid,int mode,bool lockit,const char * header)631 ksiCreateFile(rsksictx ctx, const char *path, uid_t uid, gid_t gid, int mode, bool lockit, const char* header) {
632 int fd = -1;
633 struct stat stat_st;
634 FILE *f = NULL;
635 struct flock lock = {F_WRLCK, SEEK_SET, 0, 0, 0};
636
637 if(path ==NULL)
638 return NULL;
639
640 if (mkpath((char*) path, ctx->fDirCreateMode, ctx->dirUID, ctx->dirGID) != 0) {
641 report(ctx, "ksiCreateFile: mkpath failed for %s", path);
642 goto done;
643 }
644
645 fd = open(path, O_RDWR | O_APPEND | O_NOCTTY | O_CLOEXEC, 0600);
646 if (fd == -1) {
647 fd = open(path, O_RDWR | O_CREAT | O_NOCTTY | O_CLOEXEC, mode);
648 if (fd == -1) {
649 report(ctx, "creating file '%s' failed: %s", path, strerror(errno));
650 goto done;
651 }
652
653 if (uid != (uid_t) - 1 || gid != (gid_t) - 1) {
654 if (fchown(fd, uid, gid) != 0) {
655 report(ctx, "lmsig_ksi: chown for file '%s' failed: %s",
656 path, strerror(errno));
657 }
658 }
659 }
660
661 if (lockit && fcntl(fd, F_SETLK, &lock) != 0)
662 report(ctx, "fcntl error: %s", strerror(errno));
663
664 f = fdopen(fd, "a");
665 if (f == NULL) {
666 report(ctx, "fdopen for '%s' failed: %s", path, strerror(errno));
667 goto done;
668 }
669
670 setvbuf(f, NULL, _IOFBF, KSI_BUF_SIZE);
671
672 if (fstat(fd, &stat_st) == -1) {
673 reportErr(ctx, "ksiOpenSigFile: can not stat file");
674 goto done;
675 }
676
677 if (stat_st.st_size == 0 && header != NULL) {
678 if(fwrite(header, strlen(header), 1, f) != 1) {
679 report(ctx, "ksiOpenSigFile: fwrite for file %s failed: %s",
680 path, strerror(errno));
681 goto done;
682 }
683 }
684 /* Write header immediately as when using dynafile it is possible that the same
685 * file is opened 2x in sequence (caused by small dynafile cache where files are
686 * frequently closed and reopened). If the header already exists double header is
687 * not written. The content of the file is ordered by signer thread.
688 */
689 fflush(f);
690 done:
691 return f;
692 }
693
handle_ksi_config(rsksictx ctx,KSI_AsyncService * as,KSI_Config * config)694 static void handle_ksi_config(rsksictx ctx, KSI_AsyncService *as, KSI_Config *config) {
695 KSI_Integer *ksi_int = NULL;
696 uint64_t tmpInt, newLevel, res;
697
698 if (KSI_Config_getMaxRequests(config, &ksi_int) == KSI_OK && ksi_int != NULL) {
699 tmpInt = KSI_Integer_getUInt64(ksi_int);
700 ctx->max_requests=tmpInt;
701 report(ctx, "KSI gateway has reported a max requests value of %llu",
702 (long long unsigned) tmpInt);
703
704 if(as) {
705 res = KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_MAX_REQUEST_COUNT,
706 (void*) (ctx->max_requests));
707 if(res != KSI_OK)
708 reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_setOption(max_request)", res);
709
710 KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_REQUEST_CACHE_SIZE,
711 (void*) (5*ctx->max_requests));
712 }
713 }
714
715 ksi_int = NULL;
716 if(KSI_Config_getMaxLevel(config, &ksi_int) == KSI_OK && ksi_int != NULL) {
717 tmpInt = KSI_Integer_getUInt64(ksi_int);
718 report(ctx, "KSI gateway has reported a max level value of %llu",
719 (long long unsigned) tmpInt);
720 newLevel=MIN(tmpInt, ctx->blockLevelLimit);
721 if(ctx->effectiveBlockLevelLimit != newLevel) {
722 report(ctx, "Changing the configured block level limit from %llu to %llu",
723 (long long unsigned) ctx->effectiveBlockLevelLimit,
724 (long long unsigned) newLevel);
725 ctx->effectiveBlockLevelLimit = newLevel;
726 }
727 else if(tmpInt < 2) {
728 report(ctx, "KSI gateway has reported an invalid level limit value (%llu), "
729 "plugin disabled", (long long unsigned) tmpInt);
730 ctx->disabled = true;
731 }
732 }
733 }
734
735
736 /* note: if file exists, the last hash for chaining must
737 * be read from file.
738 */
739 static int
ksiOpenSigFile(ksifile ksi)740 ksiOpenSigFile(ksifile ksi) {
741 int r = 0, tmpRes = 0;
742 const char *header;
743 FILE* signatureFile = NULL;
744 KSI_Config *config = NULL;
745
746 if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS)
747 header = LS12_BLOCKFILE_HEADER;
748 else
749 header = LS12_FILE_HEADER;
750
751 ksi->blockFile = ksiCreateFile(ksi->ctx, (char*) ksi->blockfilename, ksi->ctx->fileUID,
752 ksi->ctx->fileGID, ksi->ctx->fCreateMode, true, header);
753
754 if (ksi->blockFile == NULL) {
755 r = RSGTE_IO;
756 goto done;
757 }
758
759 /* create the file for ksi signatures if needed */
760 if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
761 signatureFile = ksiCreateFile(ksi->ctx, (char*) ksi->ksifilename, ksi->ctx->fileUID,
762 ksi->ctx->fileGID, ksi->ctx->fCreateMode, true, LS12_SIGFILE_HEADER);
763
764 if (signatureFile == NULL) {
765 r = RSGTE_IO;
766 goto done;
767 }
768
769 ksi->sigFile = signatureFile;
770 queueAddNewFile(ksi->ctx, ksi);
771 }
772
773 /* we now need to obtain the last previous hash, so that
774 * we can continue the hash chain. We do not check for error
775 * as a state file error can be recovered by graceful degredation.
776 */
777 ksiReadStateFile(ksi);
778
779 if (ksi->ctx->syncMode == LOGSIG_SYNCHRONOUS) {
780 tmpRes = KSI_receiveAggregatorConfig(ksi->ctx->ksi_ctx, &config);
781 if(tmpRes == KSI_OK) {
782 handle_ksi_config(ksi->ctx, NULL, config);
783 }
784 else {
785 reportKSIAPIErr(ksi->ctx, NULL, "KSI_receiveAggregatorConfig", tmpRes);
786 }
787 KSI_Config_free(config);
788 }
789
790 done: return r;
791 }
792
793 /*
794 * As of some Linux and security expert I spoke to, /dev/urandom
795 * provides very strong random numbers, even if it runs out of
796 * entropy. As far as he knew, this is save for all applications
797 * (and he had good proof that I currently am not permitted to
798 * reproduce). -- rgerhards, 2013-03-04
799 */
800 static void
seedIVKSI(ksifile ksi)801 seedIVKSI(ksifile ksi)
802 {
803 int hashlen;
804 int fd;
805 const char *rnd_device = ksi->ctx->random_source ? ksi->ctx->random_source : "/dev/urandom";
806
807 hashlen = KSI_getHashLength(ksi->hashAlg);
808 ksi->IV = malloc(hashlen); /* do NOT zero-out! */
809 /* if we cannot obtain data from /dev/urandom, we use whatever
810 * is present at the current memory location as random data. Of
811 * course, this is very weak and we should consider a different
812 * option, especially when not running under Linux (for Linux,
813 * unavailability of /dev/urandom is just a theoretic thing, it
814 * will always work...). -- TODO -- rgerhards, 2013-03-06
815 */
816 if ((fd = open(rnd_device, O_RDONLY)) >= 0) {
817 if(read(fd, ksi->IV, hashlen) == hashlen) {}; /* keep compiler happy */
818 close(fd);
819 }
820 }
821
822 static int
create_signer_thread(rsksictx ctx)823 create_signer_thread(rsksictx ctx) {
824 if (ctx->signer_state != SIGNER_STARTED) {
825 if (pthread_mutex_init(&ctx->module_lock, 0))
826 report(ctx, "pthread_mutex_init: %s", strerror(errno));
827 ctx->signer_queue = ProtectedQueue_new(10);
828
829 ctx->signer_state = SIGNER_INIT;
830 if (pthread_create(&ctx->signer_thread, NULL, signer_thread, ctx)) {
831 report(ctx, "pthread_mutex_init: %s", strerror(errno));
832 ctx->signer_state = SIGNER_IDLE;
833 return RSGTE_INTERNAL;
834 }
835
836 /* Lock until init. */
837 while(*((volatile int*)&ctx->signer_state) & SIGNER_INIT);
838
839 if (ctx->signer_state != SIGNER_STARTED) {
840 return RSGTE_INTERNAL;
841 }
842 }
843
844 return RSGTE_SUCCESS;
845 }
846
847 rsksictx
rsksiCtxNew(void)848 rsksiCtxNew(void) {
849 rsksictx ctx;
850 ctx = calloc(1, sizeof (struct rsksictx_s));
851 KSI_CTX_new(&ctx->ksi_ctx); // TODO: error check (probably via a generic macro?)
852 ctx->hasher = NULL;
853 ctx->hashAlg = KSI_getHashAlgorithmByName("default");
854 ctx->blockTimeLimit = 0;
855 ctx->bKeepTreeHashes = false;
856 ctx->bKeepRecordHashes = true;
857 ctx->max_requests = (1 << 8);
858 ctx->errFunc = NULL;
859 ctx->usrptr = NULL;
860 ctx->fileUID = -1;
861 ctx->fileGID = -1;
862 ctx->dirUID = -1;
863 ctx->dirGID = -1;
864 ctx->fCreateMode = 0644;
865 ctx->fDirCreateMode = 0700;
866 ctx->syncMode = LOGSIG_SYNCHRONOUS;
867 ctx->signer_state = SIGNER_IDLE;
868 ctx->disabled = false;
869 ctx->ksi = NULL;
870
871 /*if (pthread_mutex_init(&ctx->module_lock, 0))
872 report(ctx, "pthread_mutex_init: %s", strerror(errno));
873 ctx->signer_queue = ProtectedQueue_new(10);*/
874
875 /* Creating a thread this way works only in daemon mode but not when being run
876 interactively when not forked */
877 /*ret = pthread_atfork(NULL, NULL, create_signer_thread);
878 if (ret != 0)
879 report(ctx, "pthread_atfork error: %s", strerror(ret));*/
880
881 return ctx;
882 }
883
884 static
rsksiStreamLogger(void * logCtx,int logLevel,const char * message)885 int rsksiStreamLogger(void *logCtx, int logLevel, const char *message)
886 {
887 char time_buf[32];
888 struct tm *tm_info;
889 time_t timer;
890 FILE *f = (FILE *)logCtx;
891
892 timer = time(NULL);
893
894 tm_info = localtime(&timer);
895 if (tm_info == NULL) {
896 return KSI_UNKNOWN_ERROR;
897 }
898
899 if (f != NULL) {
900 flockfile(f); /* for thread safety */
901 if (strftime(time_buf, sizeof(time_buf), "%d.%m.%Y %H:%M:%S", tm_info)) {
902 if (fprintf(f, "%s [%s] %lu - %s\n", level2str(logLevel),
903 time_buf, pthread_self(), message) > 0) { }
904 }
905 funlockfile(f);
906 }
907
908 return KSI_OK;
909 }
910
911 int
rsksiInitModule(rsksictx ctx)912 rsksiInitModule(rsksictx ctx) {
913 int res = 0;
914
915 if(ctx->debugFileName != NULL) {
916 ctx->debugFile = fopen(ctx->debugFileName, "w");
917 if(ctx->debugFile) {
918 res = KSI_CTX_setLoggerCallback(ctx->ksi_ctx, rsksiStreamLogger, ctx->debugFile);
919 if (res != KSI_OK)
920 reportKSIAPIErr(ctx, NULL, "Unable to set logger callback", res);
921 res = KSI_CTX_setLogLevel(ctx->ksi_ctx, ctx->debugLevel);
922 if (res != KSI_OK)
923 reportKSIAPIErr(ctx, NULL, "Unable to set log level", res);
924 }
925 else {
926 report(ctx, "Could not open logfile %s: %s", ctx->debugFileName, strerror(errno));
927 }
928 }
929
930 KSI_CTX_setOption(ctx->ksi_ctx, KSI_OPT_AGGR_HMAC_ALGORITHM, (void*)((size_t)ctx->hmacAlg));
931
932 return create_signer_thread(ctx);
933 }
934
935 /* either returns ksifile object or NULL if something went wrong */
936 ksifile
rsksiCtxOpenFile(rsksictx ctx,unsigned char * logfn)937 rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn)
938 {
939 int ret = RSGTE_INTERNAL;
940 ksifile ksi;
941 char fn[MAXFNAME+1];
942
943 if (ctx->disabled)
944 return NULL;
945
946 pthread_mutex_lock(&ctx->module_lock);
947
948 /* The thread cannot be be created in rsksiCtxNew because in daemon mode the
949 process forks after rsksiCtxNew and the thread disappears */
950 if (ctx->signer_state != SIGNER_STARTED) {
951 ret = rsksiInitModule(ctx);
952 if (ret != RSGTE_SUCCESS) {
953 report(ctx, "Unable to init. KSI module, signing service disabled");
954 ctx->disabled = true;
955 pthread_mutex_unlock(&ctx->module_lock);
956 return NULL;
957 }
958 }
959
960 if ((ksi = rsksifileConstruct(ctx)) == NULL)
961 goto done;
962
963 snprintf(fn, sizeof (fn), "%s.ksistate", logfn);
964 fn[MAXFNAME] = '\0'; /* be on safe side */
965 ksi->statefilename = (uchar*) strdup(fn);
966
967 if (ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
968 /* filename for blocks of hashes*/
969 snprintf(fn, sizeof (fn), "%s%s", logfn, blockFileSuffix);
970 fn[MAXFNAME] = '\0'; /* be on safe side */
971 ksi->blockfilename = (uchar*) strdup(fn);
972
973 /* filename for KSI signatures*/
974 snprintf(fn, sizeof (fn), "%s%s", logfn, sigFileSuffix);
975 fn[MAXFNAME] = '\0'; /* be on safe side */
976 ksi->ksifilename = (uchar*) strdup(fn);
977 } else if (ctx->syncMode == LOGSIG_SYNCHRONOUS) {
978 snprintf(fn, sizeof (fn), "%s%s", logfn, ls12FileSuffix);
979 fn[MAXFNAME] = '\0'; /* be on safe side */
980 ksi->blockfilename = (uchar*) strdup(fn);
981 }
982
983 if (ksiOpenSigFile(ksi) != 0) {
984 reportErr(ctx, "signature file open failed");
985 /* Free memory */
986 free(ksi);
987 ksi = NULL;
988 }
989
990 done:
991 /* Register ksi file in rsksictx for keeping track of block timeouts. */
992 rsksiRegisterKsiFile(ctx, ksi);
993 pthread_mutex_unlock(&ctx->module_lock);
994 return ksi;
995 }
996
997
998 /* Returns RSGTE_SUCCESS on success, error code otherwise. If algo is unknown or
999 * is not trusted, default hash function is used.
1000 */
1001 int
rsksiSetHashFunction(rsksictx ctx,char * algName)1002 rsksiSetHashFunction(rsksictx ctx, char *algName) {
1003 if (ctx == NULL || algName == NULL) {
1004 return RSGTE_INTERNAL;
1005 }
1006
1007 int r, id = KSI_getHashAlgorithmByName(algName);
1008 if (!KSI_isHashAlgorithmSupported(id)) {
1009 report(ctx, "Hash function '%s' is not supported - using default", algName);
1010 ctx->hashAlg = KSI_getHashAlgorithmByName("default");
1011 } else {
1012 if(!KSI_isHashAlgorithmTrusted(id)) {
1013 report(ctx, "Hash function '%s' is not trusted - using default", algName);
1014 ctx->hashAlg = KSI_getHashAlgorithmByName("default");
1015 }
1016 else
1017 ctx->hashAlg = id;
1018 }
1019
1020 if ((r = KSI_DataHasher_open(ctx->ksi_ctx, ctx->hashAlg, &ctx->hasher)) != KSI_OK) {
1021 reportKSIAPIErr(ctx, NULL, "KSI_DataHasher_open", r);
1022 ctx->disabled = true;
1023 return r;
1024 }
1025
1026 return RSGTE_SUCCESS;
1027 }
1028
1029 int
rsksiSetHmacFunction(rsksictx ctx,char * algName)1030 rsksiSetHmacFunction(rsksictx ctx, char *algName) {
1031 int id = KSI_getHashAlgorithmByName(algName);
1032 if (!KSI_isHashAlgorithmSupported(id)) {
1033 report(ctx, "HMAC function '%s' is not supported - using default", algName);
1034 ctx->hmacAlg = KSI_getHashAlgorithmByName("default");
1035 } else {
1036 if(!KSI_isHashAlgorithmTrusted(id)) {
1037 report(ctx, "HMAC function '%s' is not trusted - using default", algName);
1038 ctx->hmacAlg = KSI_getHashAlgorithmByName("default");
1039 }
1040 else
1041 ctx->hmacAlg = id;
1042 }
1043 return 0;
1044 }
1045
1046 int
rsksifileDestruct(ksifile ksi)1047 rsksifileDestruct(ksifile ksi) {
1048 int r = 0;
1049 rsksictx ctx = NULL;
1050 if (ksi == NULL)
1051 return RSGTE_INTERNAL;
1052
1053 pthread_mutex_lock(&ksi->ctx->module_lock);
1054
1055 ctx = ksi->ctx;
1056
1057 /* Deregister ksifile so it is not used by signer thread anymore. Note that files are not closed yet! */
1058 rsksiDeregisterKsiFile(ctx, ksi);
1059
1060 if (!ksi->disabled && ksi->bInBlk) {
1061 sigblkAddMetadata(ksi, blockCloseReason, "Block closed due to file closure.");
1062 r = sigblkFinishKSI(ksi);
1063 }
1064 /* Note that block file is closed immediately but signature file will be closed
1065 * by the signer thread scheduled by signer thread work queue.
1066 */
1067 if(!ksi->disabled)
1068 r = ksiCloseSigFile(ksi);
1069 free(ksi->blockfilename);
1070 free(ksi->statefilename);
1071 free(ksi->ksifilename);
1072
1073 free(ksi);
1074
1075 pthread_mutex_unlock(&ctx->module_lock);
1076 return r;
1077 }
1078
1079 /* This can only be used when signer thread has terminated or within the thread. */
1080 static void
rsksifileForceFree(ksifile ksi)1081 rsksifileForceFree(ksifile ksi) {
1082 if (ksi == NULL) return;
1083
1084 if (ksi->sigFile != NULL) fclose(ksi->sigFile);
1085 if (ksi->blockFile != NULL) fclose(ksi->blockFile);
1086 free(ksi->blockfilename);
1087 free(ksi->statefilename);
1088 free(ksi->ksifilename);
1089 free(ksi);
1090 return;
1091 }
1092
1093 /* This can only be used when signer thread has terminated or within the thread. */
1094 static void
rsksictxForceFreeSignatures(rsksictx ctx)1095 rsksictxForceFreeSignatures(rsksictx ctx) {
1096 size_t i = 0;
1097
1098 if (ctx == NULL || ctx->ksi == NULL) return;
1099
1100 for (i = 0; i < ctx->ksiCount; i++) {
1101 if (ctx->ksi[i] != NULL) {
1102 rsksifileForceFree(ctx->ksi[i]);
1103 ctx->ksi[i] = NULL;
1104 }
1105 }
1106
1107 ctx->ksiCount = 0;
1108 return;
1109 }
1110
1111 /* This can only be used when signer thread has terminated or within the thread. */
1112 static int
rsksictxForceCloseWithoutSig(rsksictx ctx,const char * reason)1113 rsksictxForceCloseWithoutSig(rsksictx ctx, const char *reason) {
1114 size_t i = 0;
1115 if (ctx == NULL || ctx->ksi == NULL) return RSGTE_INTERNAL;
1116 for (i = 0; i < ctx->ksiCount; i++) {
1117 if (ctx->ksi[i] != NULL) {
1118 int ret = RSGTE_INTERNAL;
1119
1120 /* Only if block contains records, create metadata, close the block and add
1121 * no signature marker. Closing block without record will produce redundant
1122 * blocks that needs to be signed afterward.
1123 */
1124 if (ctx->ksi[i]->nRecords > 0) {
1125 ret = sigblkFinishKSINoSignature(ctx->ksi[i], reason);
1126 if (ret != RSGTE_SUCCESS) return ret;
1127 }
1128
1129 /* Free files and remove object from the list. */
1130 rsksifileForceFree(ctx->ksi[i]);
1131 ctx->ksi[i] = NULL;
1132 }
1133 }
1134
1135 ctx->ksiCount = 0;
1136 return RSGTE_SUCCESS;
1137 }
1138
1139 void
rsksiCtxDel(rsksictx ctx)1140 rsksiCtxDel(rsksictx ctx) {
1141 if (ctx == NULL)
1142 return;
1143
1144 /* Note that even in sync. mode signer thread is created and needs to be closed
1145 * correctly.
1146 */
1147 if (ctx->signer_state == SIGNER_STARTED) {
1148 queueAddQuit(ctx);
1149 /* Wait until thread closes to be able to safely free the resources. */
1150 pthread_join(ctx->signer_thread, NULL);
1151 ProtectedQueue_free(ctx->signer_queue);
1152 pthread_mutex_destroy(&ctx->module_lock);
1153 }
1154
1155 free(ctx->aggregatorUri);
1156 free(ctx->aggregatorId);
1157 free(ctx->aggregatorKey);
1158 free(ctx->debugFileName);
1159
1160 if (ctx->random_source)
1161 free(ctx->random_source);
1162
1163 KSI_DataHasher_free(ctx->hasher);
1164 KSI_CTX_free(ctx->ksi_ctx);
1165
1166 if(ctx->debugFile!=NULL)
1167 fclose(ctx->debugFile);
1168
1169 /* After signer thread is terminated there should be no open signature files,
1170 * but to be extra sure that all files are closed, recheck the list of opened
1171 * signature files.
1172 */
1173 rsksictxForceFreeSignatures(ctx);
1174 free(ctx->ksi);
1175
1176 free(ctx);
1177 }
1178
1179 /* new sigblk is initialized, but maybe in existing ctx */
1180 void
sigblkInitKSI(ksifile ksi)1181 sigblkInitKSI(ksifile ksi)
1182 {
1183 if(ksi == NULL) goto done;
1184 seedIVKSI(ksi);
1185 memset(ksi->roots, 0, sizeof (ksi->roots));
1186 ksi->nRoots = 0;
1187 ksi->nRecords = 0;
1188 ksi->bInBlk = 1;
1189 ksi->blockStarted = time(NULL); //TODO: maybe milli/nanoseconds should be used
1190 ksi->blockSizeLimit = 1 << (ksi->ctx->effectiveBlockLevelLimit - 1);
1191
1192 /* flush the optional debug file when starting a new block */
1193 if(ksi->ctx->debugFile != NULL)
1194 fflush(ksi->ctx->debugFile);
1195
1196 done:
1197 return;
1198 }
1199
1200 int
sigblkCreateMask(ksifile ksi,KSI_DataHash ** m)1201 sigblkCreateMask(ksifile ksi, KSI_DataHash **m) {
1202 int r = 0;
1203
1204 CHKr(KSI_DataHasher_reset(ksi->ctx->hasher));
1205 CHKr(KSI_DataHasher_add(ksi->ctx->hasher, ksi->lastLeaf, KSI_getHashLength(ksi->lastLeaf[0]) + 1));
1206 CHKr(KSI_DataHasher_add(ksi->ctx->hasher, ksi->IV, KSI_getHashLength(ksi->hashAlg)));
1207 CHKr(KSI_DataHasher_close(ksi->ctx->hasher, m));
1208
1209 done:
1210 if (r != KSI_OK) {
1211 reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHasher", r);
1212 r = RSGTE_HASH_CREATE;
1213 }
1214 return r;
1215 }
1216 int
sigblkCreateHash(ksifile ksi,KSI_DataHash ** out,const uchar * rec,const size_t len)1217 sigblkCreateHash(ksifile ksi, KSI_DataHash **out, const uchar *rec, const size_t len) {
1218 int r = 0;
1219
1220 CHKr(KSI_DataHasher_reset(ksi->ctx->hasher));
1221 CHKr(KSI_DataHasher_add(ksi->ctx->hasher, rec, len));
1222 CHKr(KSI_DataHasher_close(ksi->ctx->hasher, out));
1223
1224 done:
1225 if (r != KSI_OK) {
1226 reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHasher", r);
1227 r = RSGTE_HASH_CREATE;
1228 }
1229
1230 return r;
1231 }
1232
1233
1234 int
sigblkHashTwoNodes(ksifile ksi,KSI_DataHash ** out,KSI_DataHash * left,KSI_DataHash * right,uint8_t level)1235 sigblkHashTwoNodes(ksifile ksi, KSI_DataHash **out, KSI_DataHash *left, KSI_DataHash *right,
1236 uint8_t level) {
1237 int r = 0;
1238
1239 CHKr(KSI_DataHasher_reset(ksi->ctx->hasher));
1240 CHKr(KSI_DataHasher_addImprint(ksi->ctx->hasher, left));
1241 CHKr(KSI_DataHasher_addImprint(ksi->ctx->hasher, right));
1242 CHKr(KSI_DataHasher_add(ksi->ctx->hasher, &level, 1));
1243 CHKr(KSI_DataHasher_close(ksi->ctx->hasher, out));
1244
1245 done:
1246 if (r != KSI_OK) {
1247 reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_create", r);
1248 r = RSGTE_HASH_CREATE;
1249 }
1250
1251 return r;
1252 }
1253 int
sigblkAddMetadata(ksifile ksi,const char * key,const char * value)1254 sigblkAddMetadata(ksifile ksi, const char *key, const char *value) {
1255 unsigned char buffer[0xFFFF];
1256 size_t encoded_size = 0;
1257 int ret = 0;
1258
1259 tlvCreateMetadata(ksi, ksi->nRecords, key, value, buffer, &encoded_size);
1260 sigblkAddLeaf(ksi, buffer, encoded_size, true);
1261
1262 return ret;
1263 }
1264
1265 int
sigblkAddRecordKSI(ksifile ksi,const uchar * rec,const size_t len)1266 sigblkAddRecordKSI(ksifile ksi, const uchar *rec, const size_t len) {
1267 int ret = 0;
1268 if (ksi == NULL || ksi->disabled)
1269 return 0;
1270
1271 pthread_mutex_lock(&ksi->ctx->module_lock);
1272
1273 if ((ret = sigblkAddLeaf(ksi, rec, len, false)) != 0)
1274 goto done;
1275
1276 if (ksi->nRecords == ksi->blockSizeLimit) {
1277 sigblkFinishKSI(ksi);
1278 sigblkInitKSI(ksi);
1279 }
1280
1281 done:
1282 pthread_mutex_unlock(&ksi->ctx->module_lock);
1283 return ret;
1284 }
1285
1286
1287 int
sigblkAddLeaf(ksifile ksi,const uchar * leafData,const size_t leafLength,bool metadata)1288 sigblkAddLeaf(ksifile ksi, const uchar *leafData, const size_t leafLength, bool metadata) {
1289
1290 KSI_DataHash *mask, *leafHash, *treeNode, *tmpTreeNode;
1291 uint8_t j;
1292 const unsigned char *pTmp;
1293 size_t len;
1294
1295 int r = 0;
1296
1297 if (ksi == NULL || ksi->disabled) goto done;
1298 CHKr(sigblkCreateMask(ksi, &mask));
1299 CHKr(sigblkCreateHash(ksi, &leafHash, leafData, leafLength));
1300
1301 if(ksi->nRecords == 0)
1302 tlvWriteBlockHdrKSI(ksi);
1303
1304 /* metadata record has to be written into the block file too*/
1305 if (metadata)
1306 tlvWriteOctetString(ksi->blockFile, leafData, leafLength);
1307
1308 if (ksi->bKeepRecordHashes)
1309 tlvWriteHashKSI(ksi, 0x0902, leafHash);
1310
1311 /* normal leaf and metadata record are hashed in different order */
1312 if (!metadata) { /* hash leaf */
1313 if ((r = sigblkHashTwoNodes(ksi, &treeNode, mask, leafHash, 1)) != 0) goto done;
1314 } else {
1315 if ((r = sigblkHashTwoNodes(ksi, &treeNode, leafHash, mask, 1)) != 0) goto done;
1316 }
1317
1318 /* persists x here if Merkle tree needs to be persisted! */
1319 if(ksi->bKeepTreeHashes)
1320 tlvWriteHashKSI(ksi, 0x0903, treeNode);
1321
1322 KSI_DataHash_getImprint(treeNode, &pTmp, &len);
1323 memcpy(ksi->lastLeaf, pTmp, len);
1324
1325 for(j = 0 ; j < ksi->nRoots ; ++j) {
1326 if (ksi->roots[j] == NULL) {
1327 ksi->roots[j] = treeNode;
1328 treeNode = NULL;
1329 break;
1330 } else if (treeNode != NULL) {
1331 /* hash interim node */
1332 tmpTreeNode = treeNode;
1333 r = sigblkHashTwoNodes(ksi, &treeNode, ksi->roots[j], tmpTreeNode, j + 2);
1334 KSI_DataHash_free(ksi->roots[j]);
1335 ksi->roots[j] = NULL;
1336 KSI_DataHash_free(tmpTreeNode);
1337 if (r != 0) goto done;
1338 if(ksi->bKeepTreeHashes)
1339 tlvWriteHashKSI(ksi, 0x0903, treeNode);
1340 }
1341 }
1342 if (treeNode != NULL) {
1343 /* new level, append "at the top" */
1344 ksi->roots[ksi->nRoots] = treeNode;
1345 ++ksi->nRoots;
1346 assert(ksi->nRoots < MAX_ROOTS);
1347 treeNode = NULL;
1348 }
1349 ++ksi->nRecords;
1350
1351 /* cleanup (x is cleared as part of the roots array) */
1352 KSI_DataHash_free(mask);
1353 KSI_DataHash_free(leafHash);
1354
1355 done:
1356 return r;
1357 }
1358
1359 static int
sigblkCheckTimeOut(rsksictx ctx)1360 sigblkCheckTimeOut(rsksictx ctx) {
1361 int ret = RSGTE_INTERNAL;
1362 time_t now;
1363 char buf[KSI_BUF_SIZE];
1364 size_t i = 0;
1365
1366 if (ctx == NULL) {
1367 return RSGTE_INTERNAL;
1368 }
1369
1370 pthread_mutex_lock(&ctx->module_lock);
1371
1372 if (ctx->ksi == NULL || ctx->disabled || !ctx->blockTimeLimit) {
1373 ret = RSGTE_SUCCESS;
1374 goto done;
1375 }
1376
1377 now = time(NULL);
1378
1379 for (i = 0; i < ctx->ksiCount; i++) {
1380 ksifile ksi = ctx->ksi[i];
1381
1382 if (ksi == NULL) continue; /* To avoide unexpected crash. */
1383 if (!ksi->bInBlk) continue; /* Not inside a block, nothing to close nor sign. */
1384 if ((time_t) (ksi->blockStarted + ctx->blockTimeLimit) > now) continue;
1385
1386 snprintf(buf, KSI_BUF_SIZE, "Block closed due to reaching time limit %d", ctx->blockTimeLimit);
1387 sigblkAddMetadata(ksi, blockCloseReason, buf);
1388 sigblkFinishKSI(ksi);
1389 sigblkInitKSI(ksi);
1390 }
1391
1392 done:
1393 pthread_mutex_unlock(&ctx->module_lock);
1394 return ret;
1395 }
1396
1397
1398 static int
sigblkSign(ksifile ksi,KSI_DataHash * hash,int level)1399 sigblkSign(ksifile ksi, KSI_DataHash *hash, int level)
1400 {
1401 unsigned char *der = NULL;
1402 size_t lenDer = 0;
1403 int r = KSI_OK;
1404 int ret = 0;
1405 KSI_Signature *sig = NULL;
1406
1407 /* Sign the root hash. */
1408 r = KSI_Signature_signAggregated(ksi->ctx->ksi_ctx, hash, level, &sig);
1409 if (r != KSI_OK) {
1410 reportKSIAPIErr(ksi->ctx, ksi, "KSI_Signature_createAggregated", r);
1411 ret = 1;
1412 goto signing_done;
1413 }
1414
1415 /* Serialize Signature. */
1416 r = KSI_Signature_serialize(sig, &der, &lenDer);
1417 if (r != KSI_OK) {
1418 reportKSIAPIErr(ksi->ctx, ksi, "KSI_Signature_serialize", r);
1419 ret = 1;
1420 lenDer = 0;
1421 goto signing_done;
1422 }
1423
1424 signing_done:
1425 /* if signing failed the signature will be written as zero size */
1426 if (r == KSI_OK) {
1427 r = tlvWriteKSISigLS12(ksi->blockFile, ksi->nRecords, der, lenDer);
1428 if (r != KSI_OK) {
1429 reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteKSISigLS12", r);
1430 ret = 1;
1431 }
1432 } else
1433 r = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, hash, KSI_getErrorString(r));
1434
1435 if (r != KSI_OK) {
1436 reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteBlockSigKSI", r);
1437 ret = 1;
1438 }
1439
1440 if (sig != NULL)
1441 KSI_Signature_free(sig);
1442 if (der != NULL)
1443 KSI_free(der);
1444 return ret;
1445 }
1446
1447 unsigned
sigblkCalcLevel(unsigned leaves)1448 sigblkCalcLevel(unsigned leaves) {
1449 unsigned level = 0;
1450 unsigned c = leaves;
1451 while (c > 1) {
1452 level++;
1453 c >>= 1;
1454 }
1455
1456 if (1 << level < (int)leaves)
1457 level++;
1458
1459 return level;
1460 }
1461
1462 static int
sigblkFinishTree(ksifile ksi,KSI_DataHash ** hsh)1463 sigblkFinishTree(ksifile ksi, KSI_DataHash **hsh) {
1464 int ret = RSGTE_INTERNAL;
1465 KSI_DataHash *root = NULL;
1466 KSI_DataHash *rootDel = NULL;
1467 int8_t j = 0;
1468
1469 if (ksi == NULL || hsh == NULL) {
1470 goto done;
1471 }
1472
1473 if (ksi->nRecords == 0) {
1474 ret = RSGTE_SUCCESS;
1475 goto done;
1476 }
1477
1478 root = NULL;
1479 for(j = 0 ; j < ksi->nRoots ; ++j) {
1480 if(root == NULL) {
1481 root = ksi->roots[j];
1482 ksi->roots[j] = NULL;
1483 } else if (ksi->roots[j] != NULL) {
1484 rootDel = root;
1485 root = NULL;
1486 ret = sigblkHashTwoNodes(ksi, &root, ksi->roots[j], rootDel, j + 2);
1487 KSI_DataHash_free(ksi->roots[j]);
1488 ksi->roots[j] = NULL;
1489 KSI_DataHash_free(rootDel);
1490 rootDel = NULL;
1491 if(ksi->bKeepTreeHashes) {
1492 tlvWriteHashKSI(ksi, 0x0903, root);
1493 }
1494 if(ret != KSI_OK) goto done; /* checks sigblkHashTwoNodes() result! */
1495 }
1496 }
1497
1498 *hsh = root;
1499 root = NULL;
1500 ret = RSGTE_SUCCESS;
1501
1502 done:
1503 KSI_DataHash_free(root);
1504 KSI_DataHash_free(rootDel);
1505 return ret;
1506 }
1507
1508
1509 int
sigblkFinishKSI(ksifile ksi)1510 sigblkFinishKSI(ksifile ksi)
1511 {
1512 KSI_DataHash *root = NULL;
1513 int ret = RSGTE_INTERNAL;
1514 unsigned level = 0;
1515
1516 if (ksi == NULL) {
1517 goto done;
1518 }
1519
1520 if (ksi->nRecords == 0) {
1521 ret = RSGTE_SUCCESS;
1522 goto done;
1523 }
1524
1525 ret = sigblkFinishTree(ksi, &root);
1526 if (ret != RSGTE_SUCCESS) goto done;
1527
1528 //Multiplying leaves count by 2 to account for blinding masks
1529 level=sigblkCalcLevel(2 * ksi->nRecords);
1530
1531 //in case of async mode we append the root hash to signer queue
1532 if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
1533 ret = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, root, NULL);
1534 if (ret != KSI_OK) {
1535 reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret);
1536 goto done;
1537 }
1538
1539 queueAddSignRequest(ksi->ctx, ksi, root, level);
1540 root = NULL;
1541 } else {
1542 sigblkSign(ksi, root, level);
1543 }
1544
1545 ret = RSGTE_SUCCESS;
1546
1547 done:
1548 KSI_DataHash_free(root);
1549 free(ksi->IV);
1550 ksi->IV = NULL;
1551 ksi->bInBlk = 0;
1552 return ret;
1553 }
1554
1555 static int
sigblkFinishKSINoSignature(ksifile ksi,const char * reason)1556 sigblkFinishKSINoSignature(ksifile ksi, const char *reason)
1557 {
1558 KSI_DataHash *root = NULL;
1559 int ret = RSGTE_INTERNAL;
1560
1561 if (ksi == NULL || ksi->ctx == NULL ||
1562 (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS && ksi->sigFile == NULL) ||
1563 ksi->blockFile == NULL || reason == NULL) {
1564 goto done;
1565 }
1566
1567 ret = sigblkAddMetadata(ksi, blockCloseReason, reason);
1568 if (ret != RSGTE_SUCCESS) goto done;
1569
1570 ret = sigblkFinishTree(ksi, &root);
1571 if (ret != RSGTE_SUCCESS) goto done;
1572
1573 ret = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, root, reason);
1574 if (ret != KSI_OK) {
1575 reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret);
1576 goto done;
1577 }
1578
1579 if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) {
1580 ret = tlvWriteNoSigLS12(ksi->sigFile, ksi->nRecords, root, reason);
1581 if (ret != KSI_OK) {
1582 reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret);
1583 goto done;
1584 }
1585 }
1586
1587 ret = RSGTE_SUCCESS;
1588
1589 done:
1590 KSI_DataHash_free(root);
1591 free(ksi->IV);
1592 ksi->IV=NULL;
1593 ksi->bInBlk = 0;
1594 return ret;
1595 }
1596
1597 int
rsksiSetAggregator(rsksictx ctx,char * uri,char * loginid,char * key)1598 rsksiSetAggregator(rsksictx ctx, char *uri, char *loginid, char *key) {
1599 int r;
1600 char *strTmp, *strTmpUri;
1601
1602 /* only use the strings if they are not empty */
1603 ctx->aggregatorUri = (uri != NULL && strlen(uri) != 0) ? strdup(uri) : NULL;
1604 ctx->aggregatorId = (loginid != NULL && strlen(loginid) != 0) ? strdup(loginid) : NULL;
1605 ctx->aggregatorKey = (key != NULL && strlen(key) != 0) ? strdup(key) : NULL;
1606
1607 /* split the URI string up for possible HA endpoints */
1608 strTmp = ctx->aggregatorUri;
1609 while((strTmpUri = strsep(&strTmp, "|") ) != NULL) {
1610 if(ctx->aggregatorEndpointCount >= KSI_CTX_HA_MAX_SUBSERVICES) {
1611 report(ctx, "Maximum number (%d) of service endoints reached, ignoring endpoint: %s",
1612 KSI_CTX_HA_MAX_SUBSERVICES, strTmpUri);
1613 }
1614 else {
1615 ctx->aggregatorEndpoints[ctx->aggregatorEndpointCount] = strTmpUri;
1616 ctx->aggregatorEndpointCount++;
1617 }
1618 }
1619
1620 r = KSI_CTX_setAggregator(ctx->ksi_ctx, ctx->aggregatorUri, ctx->aggregatorId, ctx->aggregatorKey);
1621 if(r != KSI_OK) {
1622 ctx->disabled = true;
1623 reportKSIAPIErr(ctx, NULL, "KSI_CTX_setAggregator", r);
1624 return KSI_INVALID_ARGUMENT;
1625 }
1626
1627 return r;
1628 }
1629
1630
1631 int
rsksiSetDebugFile(rsksictx ctx,char * val)1632 rsksiSetDebugFile(rsksictx ctx, char *val) {
1633 if(!val)
1634 return KSI_INVALID_ARGUMENT;
1635
1636 ctx->debugFileName=strdup(val);
1637 return KSI_OK;
1638 }
1639
1640 static bool
add_queue_item(rsksictx ctx,QITEM_type type,KSI_DataHash * root,FILE * sigFile,uint64_t intarg1,uint64_t intarg2)1641 add_queue_item(rsksictx ctx, QITEM_type type, KSI_DataHash *root, FILE *sigFile, uint64_t intarg1, uint64_t intarg2) {
1642 QueueItem *qi = (QueueItem*) malloc(sizeof (QueueItem));
1643 if (!qi) {
1644 ctx->disabled = true;
1645 return false;
1646 }
1647
1648 qi->root = root;
1649 qi->file = sigFile;
1650
1651 qi->type = type;
1652 qi->status = QITEM_WAITING;
1653 qi->intarg1 = intarg1;
1654 qi->intarg2 = intarg2;
1655 qi->respHandle = NULL;
1656 qi->ksi_status = KSI_UNKNOWN_ERROR;
1657 qi->request_time = time(NULL);
1658 if (ProtectedQueue_addItem(ctx->signer_queue, qi) == false) {
1659 ctx->disabled = true;
1660 free(qi);
1661 return false;
1662 }
1663 return true;
1664 }
1665
1666 static bool
queueAddCloseFile(rsksictx ctx,ksifile ksi)1667 queueAddCloseFile(rsksictx ctx, ksifile ksi) {
1668 return add_queue_item(ctx, QITEM_CLOSE_FILE, NULL, ksi->sigFile, 0, 0);
1669 }
1670
1671 static bool
queueAddNewFile(rsksictx ctx,ksifile ksi)1672 queueAddNewFile(rsksictx ctx, ksifile ksi) {
1673 return add_queue_item(ctx, QITEM_NEW_FILE, NULL, ksi->sigFile, time(NULL) + ctx->blockTimeLimit, 0);
1674 }
1675
1676 static bool
queueAddQuit(rsksictx ctx)1677 queueAddQuit(rsksictx ctx) {
1678 return add_queue_item(ctx, QITEM_QUIT, NULL, NULL, 0, 0);
1679 }
1680
1681 static bool
queueAddSignRequest(rsksictx ctx,ksifile ksi,KSI_DataHash * root,unsigned level)1682 queueAddSignRequest(rsksictx ctx, ksifile ksi, KSI_DataHash *root, unsigned level) {
1683 return add_queue_item(ctx, QITEM_SIGNATURE_REQUEST, root, ksi->sigFile, ksi->nRecords, level);
1684 }
1685
1686 static bool
save_response(rsksictx ctx,FILE * outfile,QueueItem * item)1687 save_response(rsksictx ctx, FILE* outfile, QueueItem *item) {
1688 bool ret = false;
1689 KSI_Signature *sig = NULL;
1690 unsigned char *raw = NULL;
1691 size_t raw_len;
1692 int res = KSI_OK;
1693
1694 if(item->respHandle != NULL && item->ksi_status == KSI_OK) {
1695 CHECK_KSI_API(KSI_AsyncHandle_getSignature(item->respHandle, &sig), ctx,
1696 "KSI_AsyncHandle_getSignature");
1697 CHECK_KSI_API(KSI_Signature_serialize(sig, &raw, &raw_len), ctx,
1698 "KSI_Signature_serialize");
1699 tlvWriteKSISigLS12(outfile, item->intarg1, raw, raw_len);
1700 KSI_free(raw);
1701 }
1702 else {
1703 tlvWriteNoSigLS12(outfile, item->intarg1, item->root, KSI_getErrorString(item->ksi_status));
1704 }
1705 ret = true;
1706
1707 cleanup:
1708 if(res != KSI_OK)
1709 tlvWriteNoSigLS12(outfile, item->intarg1, item->root, KSI_getErrorString(res));
1710
1711 KSI_Signature_free(sig);
1712
1713 return ret;
1714 }
1715
1716 static bool
process_requests_async(rsksictx ctx,KSI_CTX * ksi_ctx,KSI_AsyncService * as)1717 process_requests_async(rsksictx ctx, KSI_CTX *ksi_ctx, KSI_AsyncService *as) {
1718 bool ret = false;
1719 QueueItem *item = NULL;
1720 int res = KSI_OK, tmpRes;
1721 KSI_AsyncHandle *reqHandle = NULL;
1722 KSI_AsyncHandle *respHandle = NULL;
1723 KSI_AggregationReq *req = NULL;
1724 KSI_Config *config = NULL;
1725 KSI_Integer *level;
1726 long extError;
1727 KSI_Utf8String *errorMsg;
1728 int state, ksi_status;
1729 unsigned i;
1730 size_t p;
1731
1732 KSI_AsyncService_getPendingCount(as, &p);
1733
1734 /* Check if there are pending/available responses and associate them with the request items */
1735 while(true) {
1736 respHandle = NULL;
1737 item = NULL;
1738 tmpRes=KSI_AsyncService_run(as, &respHandle, &p);
1739 if(tmpRes!=KSI_OK)
1740 reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_run", tmpRes);
1741
1742 if (respHandle == NULL) { /* nothing received */
1743 break;
1744 }
1745
1746 state = KSI_ASYNC_STATE_UNDEFINED;
1747
1748 CHECK_KSI_API(KSI_AsyncHandle_getState(respHandle, &state), ctx, "KSI_AsyncHandle_getState");
1749
1750 if(state == KSI_ASYNC_STATE_PUSH_CONFIG_RECEIVED) {
1751 res = KSI_AsyncHandle_getConfig(respHandle, &config);
1752 if(res == KSI_OK) {
1753 handle_ksi_config(ctx, as, config);
1754 KSI_AsyncHandle_free(respHandle);
1755 } else
1756 reportKSIAPIErr(ctx, NULL, "KSI_AsyncHandle_getConfig", res);
1757 }
1758 else if(state == KSI_ASYNC_STATE_RESPONSE_RECEIVED) {
1759 CHECK_KSI_API(KSI_AsyncHandle_getRequestCtx(respHandle, (const void**)&item), ctx,
1760 "KSI_AsyncHandle_getRequestCtx");
1761 item->respHandle = respHandle;
1762 item->ksi_status = KSI_OK;
1763 }
1764 else if(state == KSI_ASYNC_STATE_ERROR) {
1765 CHECK_KSI_API(KSI_AsyncHandle_getRequestCtx(respHandle, (const void**)&item), ctx,
1766 "KSI_AsyncHandle_getRequestCtx");
1767 errorMsg = NULL;
1768 KSI_AsyncHandle_getError(respHandle, &ksi_status);
1769 KSI_AsyncHandle_getExtError(respHandle, &extError);
1770 KSI_AsyncHandle_getErrorMessage(respHandle, &errorMsg);
1771 report(ctx, "Asynchronous request returned error %s (%d), %lu %s",
1772 KSI_getErrorString(ksi_status), ksi_status, extError,
1773 errorMsg ? KSI_Utf8String_cstr(errorMsg) : "");
1774 KSI_AsyncHandle_free(respHandle);
1775
1776 if(item)
1777 item->ksi_status = ksi_status;
1778 }
1779
1780 if(item)
1781 item->status = QITEM_DONE;
1782 }
1783
1784 KSI_AsyncService_getPendingCount(as, &p);
1785
1786 /* Send all the new requests in the back of the queue to the server */
1787 for(i = 0; i < ProtectedQueue_count(ctx->signer_queue); i++) {
1788 item = NULL;
1789 if(!ProtectedQueue_getItem(ctx->signer_queue, i, (void**)&item) || !item)
1790 continue;
1791 /* ingore non request queue items */
1792 if(item->type != QITEM_SIGNATURE_REQUEST)
1793 continue;
1794
1795 /* stop at first processed item */
1796 if(item->status != QITEM_WAITING)
1797 continue;
1798
1799 CHECK_KSI_API(KSI_AggregationReq_new(ksi_ctx, &req), ctx, "KSI_AggregationReq_new");
1800 CHECK_KSI_API(KSI_AggregationReq_setRequestHash((KSI_AggregationReq*)req,
1801 KSI_DataHash_ref(item->root)), ctx,
1802 "KSI_AggregationReq_setRequestHash");
1803 CHECK_KSI_API(KSI_Integer_new(ksi_ctx, item->intarg2, &level), ctx,
1804 "KSI_Integer_new");
1805 CHECK_KSI_API(KSI_AggregationReq_setRequestLevel(req, level), ctx,
1806 "KSI_AggregationReq_setRequestLevel");
1807 CHECK_KSI_API(KSI_AsyncAggregationHandle_new(ksi_ctx, req, &reqHandle), ctx,
1808 "KSI_AsyncAggregationHandle_new");
1809 CHECK_KSI_API(KSI_AsyncHandle_setRequestCtx(reqHandle, (void*)item, NULL), ctx,
1810 "KSI_AsyncRequest_setRequestContext");
1811 res = KSI_AsyncService_addRequest(as, reqHandle); /* this can fail because of throttling */
1812
1813 if (res == KSI_OK) {
1814 item->status = QITEM_SENT;
1815
1816 tmpRes=KSI_AsyncService_run(as, NULL, NULL);
1817 if(tmpRes!=KSI_OK)
1818 reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_run", tmpRes);
1819
1820 } else {
1821 reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_addRequest", res);
1822 KSI_AsyncHandle_free(reqHandle);
1823 item->status = QITEM_DONE;
1824 item->ksi_status = res;
1825 break;
1826 }
1827 }
1828
1829
1830 /* Save all consequent fulfilled responses in the front of the queue to the signature file */
1831 while(ProtectedQueue_count(ctx->signer_queue)) {
1832 item = NULL;
1833 if(!ProtectedQueue_getItem(ctx->signer_queue, 0, (void**)&item))
1834 break;
1835
1836 if(!item) {
1837 ProtectedQueue_popFront(ctx->signer_queue, (void**) &item);
1838 continue;
1839 }
1840
1841 /* stop at first non request queue item (maybe file close/open, quit) */
1842 if(item->type!=QITEM_SIGNATURE_REQUEST)
1843 break;
1844
1845 /* stop at first unfinished queue item because the signatures need to be ordered */
1846 if(item->status != QITEM_DONE)
1847 break;
1848
1849 ProtectedQueue_popFront(ctx->signer_queue, (void**) &item);
1850 save_response(ctx, item->file, item);
1851 fflush(item->file);
1852 /* the main thread has to be locked when the hash is freed to avoid a race condition */
1853 /* TODO: this need more elegant solution, hash should be detached from creation context*/
1854 pthread_mutex_lock(&ctx->module_lock);
1855 KSI_DataHash_free(item->root);
1856 KSI_AsyncHandle_free(item->respHandle);
1857 free(item);
1858 pthread_mutex_unlock(&ctx->module_lock);
1859 }
1860
1861 ret = true;
1862
1863 cleanup:
1864 KSI_AsyncService_getPendingCount(as, &p);
1865 return ret;
1866 }
1867
1868 /* This can only be used when signer thread has terminated or within the thread. */
1869 static bool
rsksictxCloseAllPendingBlocksWithoutSignature(rsksictx ctx,const char * reason)1870 rsksictxCloseAllPendingBlocksWithoutSignature(rsksictx ctx, const char *reason) {
1871 bool ret = false;
1872 QueueItem *item = NULL;
1873 int res = KSI_OK;
1874
1875 /* Save all consequent fulfilled responses in the front of the queue to the signature file */
1876 while(ProtectedQueue_count(ctx->signer_queue)) {
1877 item = NULL;
1878 ProtectedQueue_popFront(ctx->signer_queue, (void**) &item);
1879
1880 if(item == NULL) {
1881 continue;
1882 }
1883
1884 /* Skip non request queue item. */
1885 if(item->type == QITEM_SIGNATURE_REQUEST) {
1886 res = tlvWriteNoSigLS12(item->file, item->intarg1, item->root, reason);
1887 if (res != KSI_OK) {
1888 reportKSIAPIErr(ctx, NULL, "tlvWriteNoSigLS12", res);
1889 ret = false;
1890 goto cleanup;
1891 }
1892 fflush(item->file);
1893 }
1894
1895 KSI_DataHash_free(item->root);
1896 KSI_AsyncHandle_free(item->respHandle);
1897 free(item);
1898 }
1899
1900 ret = true;
1901
1902 cleanup:
1903 return ret;
1904 }
1905
1906
1907 static void
request_async_config(rsksictx ctx,KSI_CTX * ksi_ctx,KSI_AsyncService * as)1908 request_async_config(rsksictx ctx, KSI_CTX *ksi_ctx, KSI_AsyncService *as) {
1909 KSI_Config *cfg = NULL;
1910 KSI_AsyncHandle *cfgHandle = NULL;
1911 KSI_AggregationReq *cfgReq = NULL;
1912 int res;
1913 bool bSuccess = false;
1914
1915 CHECK_KSI_API(KSI_AggregationReq_new(ksi_ctx, &cfgReq), ctx, "KSI_AggregationReq_new");
1916 CHECK_KSI_API(KSI_Config_new(ksi_ctx, &cfg), ctx, "KSI_Config_new");
1917 CHECK_KSI_API(KSI_AggregationReq_setConfig(cfgReq, cfg), ctx, "KSI_AggregationReq_setConfig");
1918 CHECK_KSI_API(KSI_AsyncAggregationHandle_new(ksi_ctx, cfgReq, &cfgHandle), ctx,
1919 "KSI_AsyncAggregationHandle_new");
1920 CHECK_KSI_API(KSI_AsyncService_addRequest(as, cfgHandle), ctx, "KSI_AsyncService_addRequest");
1921
1922 bSuccess = true;
1923
1924 cleanup:
1925 if(!bSuccess) {
1926 if(cfgHandle)
1927 KSI_AsyncHandle_free(cfgHandle);
1928 else if(cfgReq)
1929 KSI_AggregationReq_free(cfgReq);
1930 else if(cfg)
1931 KSI_Config_free(cfg);
1932 }
1933 }
1934
1935 #pragma GCC diagnostic push
1936 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
signer_thread(void * arg)1937 void *signer_thread(void *arg) {
1938
1939 rsksictx ctx = (rsksictx) arg;
1940 QueueItem *item = NULL;
1941 size_t ksiFileCount = 0;
1942 time_t timeout;
1943 KSI_CTX *ksi_ctx;
1944 KSI_AsyncService *as = NULL;
1945 int res = 0;
1946 bool ret = false;
1947 int i = 0, endpoints = 0;
1948
1949 CHECK_KSI_API(KSI_CTX_new(&ksi_ctx), ctx, "KSI_CTX_new");
1950 CHECK_KSI_API(KSI_CTX_setAggregator(ksi_ctx,
1951 ctx->aggregatorUri, ctx->aggregatorId, ctx->aggregatorKey),
1952 ctx, "KSI_CTX_setAggregator");
1953
1954
1955 if(ctx->debugFile) {
1956 res = KSI_CTX_setLoggerCallback(ksi_ctx, rsksiStreamLogger, ctx->debugFile);
1957 if (res != KSI_OK)
1958 reportKSIAPIErr(ctx, NULL, "Unable to set logger callback", res);
1959 res = KSI_CTX_setLogLevel(ksi_ctx, ctx->debugLevel);
1960 if (res != KSI_OK)
1961 reportKSIAPIErr(ctx, NULL, "Unable to set log level", res);
1962 }
1963
1964 CHECK_KSI_API(KSI_CTX_setOption(ksi_ctx, KSI_OPT_AGGR_HMAC_ALGORITHM, (void*)((size_t)ctx->hmacAlg)),
1965 ctx, "KSI_CTX_setOption");
1966
1967 res = KSI_SigningHighAvailabilityService_new(ksi_ctx, &as);
1968 if (res != KSI_OK) {
1969 reportKSIAPIErr(ctx, NULL, "KSI_SigningAsyncService_new", res);
1970 }
1971 else {
1972 for (i = 0; i < ctx->aggregatorEndpointCount; i++) {
1973 res = KSI_AsyncService_addEndpoint(as,
1974 ctx->aggregatorEndpoints[i], ctx->aggregatorId, ctx->aggregatorKey);
1975 if (res != KSI_OK) {
1976 //This can fail if the protocol is not supported by async api.
1977 reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_addEndpoint", res);
1978 continue;
1979 }
1980
1981 endpoints++;
1982 }
1983 }
1984
1985 if(endpoints == 0) { /* no endpoint accepted, deleting the service */
1986 report(ctx, "No endpoints added, signing service disabled");
1987 ctx->disabled = true;
1988 KSI_AsyncService_free(as);
1989 as=NULL;
1990 goto cleanup;
1991 }
1992
1993 KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_REQUEST_CACHE_SIZE,
1994 (void*) (ctx->max_requests));
1995
1996 ctx->signer_state = SIGNER_STARTED;
1997 while (true) {
1998 timeout = 1;
1999
2000 /* Wait for a work item or timeout*/
2001 ProtectedQueue_waitForItem(ctx->signer_queue, NULL, timeout * 1000);
2002 /* Check for block time limit*/
2003 sigblkCheckTimeOut(ctx);
2004
2005 /* in case there are no items go around*/
2006 if (ProtectedQueue_count(ctx->signer_queue) == 0) {
2007 process_requests_async(ctx, ksi_ctx, as);
2008 continue;
2009 }
2010
2011 /* process signing requests only if there is an open signature file */
2012 if(ksiFileCount > 0) {
2013 /* check for pending/unsent requests in asynchronous service */
2014 ret = process_requests_async(ctx, ksi_ctx, as);
2015 if(!ret) {
2016 // probably fatal error, disable signing, error should be already reported
2017 ctx->disabled = true;
2018 goto cleanup;
2019 }
2020 }
2021 /* if there are sig. requests still in the front, then we have to start over*/
2022 if (ProtectedQueue_peekFront(ctx->signer_queue, (void**) &item)
2023 && item->type == QITEM_SIGNATURE_REQUEST)
2024 continue;
2025
2026 /* Handle other types of work items */
2027 if (ProtectedQueue_popFront(ctx->signer_queue, (void**) &item) != 0) {
2028 if (item->type == QITEM_CLOSE_FILE) {
2029 if (item->file) {
2030 fclose(item->file);
2031 item->file = NULL;
2032 }
2033
2034 if (ksiFileCount > 0) ksiFileCount--;
2035 } else if (item->type == QITEM_NEW_FILE) {
2036 ksiFileCount++;
2037 request_async_config(ctx, ksi_ctx, as);
2038 /* renew the config when opening a new file */
2039 } else if (item->type == QITEM_QUIT) {
2040 free(item);
2041
2042 /* Will look into work queue for pending KSI signatures and will output
2043 * unsigned block marker instead of actual KSI signature to finalize this
2044 * thread quickly.
2045 */
2046 rsksictxCloseAllPendingBlocksWithoutSignature(ctx,
2047 "Signing not finished due to sudden closure of lmsig_ksi-ls12 module.");
2048 rsksictxForceCloseWithoutSig(ctx,
2049 "Block closed due to sudden closure of lmsig_ksi-ls12 module.");
2050
2051 goto cleanup;
2052 }
2053 free(item);
2054 }
2055 }
2056
2057 cleanup:
2058
2059 KSI_AsyncService_free(as);
2060 KSI_CTX_free(ksi_ctx);
2061 ctx->signer_state = SIGNER_STOPPED;
2062
2063 return NULL;
2064 }
2065 #pragma GCC diagnostic push
2066