static int parseStructure(KSI_TLV *tlv, int indent) { int res; KSI_TLV *nested = NULL; KSI_LIST(KSI_TLV) *list = NULL; size_t i; KSI_Utf8String *utf = NULL; KSI_Integer *integer = NULL; KSI_OctetString *octet = NULL; switch (KSI_TLV_getTag(tlv)) { case 0x01: /* Cast as numeric TLV */ /* Parse number */ res = KSI_Integer_fromTlv(tlv, &integer); if (res != KSI_OK) goto cleanup; break; case 0x02: /* Cast as string TLV */ res = KSI_Utf8String_fromTlv(tlv, &utf); if (res != KSI_OK) goto cleanup; break; case 0x03: case 0x1003: res = KSI_TLV_getNestedList(tlv, &list); if (res != KSI_OK) goto cleanup; /* Parse nested */ for (i = 0; i < KSI_TLVList_length(list); i++) { res = KSI_TLVList_elementAt(list, i, &nested); if (res != KSI_OK) goto cleanup; if (nested == NULL) break; res = parseStructure(nested, indent); if (res != KSI_OK) goto cleanup; } break; case 0x04: /* Cast as octet string*/ res = KSI_OctetString_fromTlv(tlv, &octet); if (res != KSI_OK) goto cleanup; break; default: res = KSI_INVALID_FORMAT; goto cleanup; } cleanup: KSI_OctetString_free(octet); KSI_Utf8String_free(utf); KSI_Integer_free(integer); return res; }
static int publicationsFileTLV_getSignatureTLVLength(KSI_TLV *pubFileTlv, size_t *len) { int res; KSI_TLVList *list = NULL; KSI_TLV *tlvSig = NULL; const unsigned char *raw = NULL; size_t raw_len; size_t sig_len; KSI_CTX *ctx = NULL; if (pubFileTlv == NULL && len == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } ctx = KSI_TLV_getCtx(pubFileTlv); KSI_ERR_clearErrors(ctx); res = KSI_TLV_getNestedList(pubFileTlv, &list); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_TLVList_elementAt(list, KSI_TLVList_length(list) - 1, &tlvSig); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (KSI_TLV_getTag(tlvSig) != 0x704) { KSI_pushError(ctx, res, "Last TLV in publications file must be signature (0x704)"); goto cleanup; } res = KSI_TLV_getRawValue(tlvSig, &raw, &raw_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } sig_len = raw_len; sig_len += 4; *len = sig_len; cleanup: return res; }
static int TLVListIterator_next(TLVListIterator *iter, KSI_TLV **tlv) { int res = KSI_UNKNOWN_ERROR; KSI_TLV *next = NULL; if (iter == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } if (iter->idx < KSI_TLVList_length(iter->list)) { res = KSI_TLVList_elementAt(iter->list, iter->idx, &next); if (res != KSI_OK) goto cleanup; iter->idx++; } *tlv = next; res = KSI_OK; cleanup: return res; }
KSI_END_TLV_TEMPLATE static int replaceCalendarChain(KSI_Signature *sig, KSI_CalendarHashChain *calendarHashChain) { int res; KSI_DataHash *aggrOutputHash = NULL; KSI_TLV *oldCalChainTlv = NULL; KSI_TLV *newCalChainTlv = NULL; KSI_LIST(KSI_TLV) *nestedList = NULL; size_t i; if (sig == NULL || calendarHashChain == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(sig->ctx); res = KSI_TLV_getNestedList(sig->baseTlv, &nestedList); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } if (sig->calendarChain != NULL) { for (i = 0; i < KSI_TLVList_length(nestedList); i++) { res = KSI_TLVList_elementAt(nestedList,i, &oldCalChainTlv); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } if (oldCalChainTlv == NULL) { KSI_pushError(sig->ctx, res = KSI_INVALID_SIGNATURE, "Signature TLV element missing."); goto cleanup; } if (KSI_TLV_getTag(oldCalChainTlv) == 0x0802) break; } } res = KSI_TLV_new(sig->ctx, 0x0802, 0, 0, &newCalChainTlv); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } res = KSI_TlvTemplate_construct(sig->ctx, newCalChainTlv, calendarHashChain, KSI_TLV_TEMPLATE(KSI_CalendarHashChain)); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } res = (sig->calendarChain == NULL) ? /* In case there is no calendar hash chain attached, append a new one. */ KSI_TLV_appendNestedTlv(sig->baseTlv, newCalChainTlv) : /* Otherwise replace the calendar hash chain. */ KSI_TLV_replaceNestedTlv(sig->baseTlv, oldCalChainTlv, newCalChainTlv); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } newCalChainTlv = NULL; /* The memory was freed within KSI_TLV_replaceNestedTlv. */ oldCalChainTlv = NULL; KSI_CalendarHashChain_free(sig->calendarChain); sig->calendarChain = calendarHashChain; res = KSI_OK; cleanup: KSI_nofree(nestedList); KSI_DataHash_free(aggrOutputHash); KSI_TLV_free(newCalChainTlv); return res; }