Esempio n. 1
0
static void TestClone(CuTest *tc) {
	int res;
	KSI_TLV *tlv = NULL;
	KSI_TLV *clone = NULL;

	unsigned char in[0xffff + 4];
	unsigned char out1[0xffff + 4];
	char errstr[1024];

	size_t out_len;
	size_t in_len;

	FILE *f = NULL;
	int i = 0;

	KSI_ERR_clearErrors(ctx);

	while (ok_sample[i] != NULL) {
		f = fopen(getFullResourcePath(ok_sample[i]), "rb");
		CuAssert(tc, "Unable to open test file.", f != NULL);

		in_len = (unsigned) fread(in, 1, sizeof(in), f);

		fclose(f);
		f = NULL;

		res = KSI_TLV_parseBlob2(ctx, in, in_len, 0, &tlv);
		CuAssert(tc, "Unable to parse TLV.", res == KSI_OK);

		res = parseStructure(tlv, 0);
		CuAssert(tc, "Unable to parse TLV structure.", res == KSI_OK);

		res = KSI_TLV_clone(tlv, &clone);
		CuAssert(tc, "Unsable to clone TLV.", res == KSI_OK && clone != NULL);

		/* Re assemble TLV */
		res = KSI_TLV_serialize_ex(clone, out1, sizeof(out1), &out_len);
		CuAssert(tc, "Unable to serialize TLV.", res == KSI_OK);

		CuAssert(tc, "Serialized TLV size mismatch.", in_len == out_len);
		sprintf(errstr, "Serialised TLV content does not match original: '%s'.", ok_sample[i]);
		CuAssert(tc, errstr, !memcmp(in, out1, in_len));

		KSI_TLV_free(clone);
		clone = NULL;

		KSI_TLV_free(tlv);
		tlv = NULL;
		i++;
	}
}
Esempio n. 2
0
int KSI_TlvTemplate_parse(KSI_CTX *ctx, const unsigned char *raw, unsigned raw_len, const KSI_TlvTemplate *tmpl, void *payload) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tlv = NULL;
	struct tlv_track_s tr[0xf];

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || raw == NULL || tmpl == NULL || payload == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	res = KSI_TLV_parseBlob2(ctx, (unsigned char *)raw, raw_len, 0, &tlv);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = extract(ctx, payload, tlv, tmpl, tr, 0, sizeof(tr));
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	KSI_LOG_logTlv(ctx, KSI_LOG_DEBUG, "Parsed TLV", tlv);

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tlv);

	return res;
}
Esempio n. 3
0
int KSI_Utf8StringNZ_toTlv(KSI_CTX *ctx, KSI_Utf8String *o, unsigned tag, int isNonCritical, int isForward, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || o == NULL || tlv == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	if (o->len == 0 || (o->len == 1 && o->value[0] == 0)) {
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Empty string value not allowed.");
		goto cleanup;
	}

	res = KSI_Utf8String_toTlv(ctx, o, tag, isNonCritical, isForward, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*tlv = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tmp);

	return res;
}
Esempio n. 4
0
int KSI_OctetString_toTlv(KSI_CTX *ctx, KSI_OctetString *o, unsigned tag, int isNonCritical, int isForward, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || o == NULL || tlv == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	res = KSI_TLV_new(ctx, tag, isNonCritical, isForward, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_TLV_setRawValue(tmp, o->data, o->data_len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*tlv = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tmp);

	return res;
}
Esempio n. 5
0
/**
 * KSI_PublicationData
 */
void KSI_PublicationData_free(KSI_PublicationData *t) {
	if (t != NULL && --t->ref == 0) {
		KSI_Integer_free(t->time);
		KSI_DataHash_free(t->imprint);
		KSI_TLV_free(t->baseTlv);
		KSI_free(t);
	}
}
Esempio n. 6
0
int KSI_TlvTemplate_serializeObject(KSI_CTX *ctx, const void *obj, unsigned tag, int isNc, int isFwd, const KSI_TlvTemplate *tmpl, unsigned char **raw, unsigned *raw_len) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tlv = NULL;
	unsigned char *tmp = NULL;
	unsigned tmp_len = 0;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || obj == NULL || tmpl == NULL || raw == NULL || raw_len == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	/* Create TLV for the PDU object. */
	res = KSI_TLV_new(ctx, KSI_TLV_PAYLOAD_TLV, tag, isFwd, isNc, &tlv);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	/* Evaluate the TLV. */
	res = KSI_TlvTemplate_construct(ctx, tlv, obj, tmpl);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	KSI_LOG_logTlv(ctx, KSI_LOG_DEBUG, "Serializing object", tlv);

	/* Serialize the TLV. */
	res = KSI_TLV_serialize(tlv, &tmp, &tmp_len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*raw = tmp;
	tmp = NULL;
	*raw_len = tmp_len;

	res = KSI_OK;

cleanup:

	KSI_free(tmp);
	KSI_TLV_free(tlv);

	return res;
}
Esempio n. 7
0
int KSI_Integer_toTlv(KSI_CTX *ctx, KSI_Integer *o, unsigned tag, int isNonCritical, int isForward, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;
	unsigned char raw[8];
	unsigned len = 0;
	KSI_uint64_t val;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || o == NULL || tlv == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	val = o->value;

	res = KSI_TLV_new(ctx, tag, isNonCritical, isForward, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	/* Encode the integer value. */
	while (val != 0) {
		raw[7 - len++] = val & 0xff;
		val >>= 8;
	}

	/* If the length is greater than 0 (val > 0), add the raw value. */
	if (len > 0) {
		res = KSI_TLV_setRawValue(tmp, raw + 8 - len, len);
		if (res != KSI_OK) {
			KSI_pushError(ctx, res, NULL);
			goto cleanup;
		}
	}

	*tlv = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tmp);

	return res;
}
Esempio n. 8
0
int KSI_PKISignature_toTlv(KSI_CTX *ctx, KSI_PKISignature *sig, unsigned tag, int isNonCritical, int isForward, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;
	unsigned char *raw = NULL;
	unsigned raw_len = 0;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || sig == NULL || tlv == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}


	res = KSI_TLV_new(ctx, KSI_TLV_PAYLOAD_RAW, tag, isNonCritical, isForward, &tmp);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_PKISignature_serialize(sig, &raw, &raw_len);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_TLV_setRawValue(tmp, raw, raw_len);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}


	*tlv = tmp;
	tmp = NULL;

	res = KSI_OK;


cleanup:

	KSI_nofree(raw);
	KSI_TLV_free(tmp);

	return res;
}
Esempio n. 9
0
int KSI_DataHash_toTlv(KSI_CTX *ctx, KSI_DataHash *hsh, unsigned tag, int isNonCritical, int isForward, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;
	const unsigned char *raw = NULL;
	size_t raw_len = 0;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || hsh == NULL || tlv == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	res = KSI_TLV_new(ctx, tag, isNonCritical, isForward, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_DataHash_getImprint(hsh, &raw, &raw_len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_TLV_setRawValue(tmp, raw, raw_len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*tlv = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_nofree(raw);
	KSI_TLV_free(tmp);

	return res;
}
Esempio n. 10
0
static void TestNokFiles(CuTest* tc) {
	int res;
	int i = 0;

	KSI_TLV *tlv = NULL;

	KSI_ERR_clearErrors(ctx);

	while (nok_sample[i] != NULL) {
		res = KSITest_tlvFromFile(getFullResourcePath(nok_sample[i++]), &tlv);

		if (res == KSI_OK) {
			res = parseStructure(tlv, 0);
		}

		CuAssert(tc, "Parser did not fail with invalid TLV.", res != KSI_OK);

		KSI_TLV_free(tlv);
		tlv = NULL;
	}
}
Esempio n. 11
0
static void TestOkFiles(CuTest* tc) {
	int res;
	int i = 0;

	KSI_TLV *tlv = NULL;

	KSI_ERR_clearErrors(ctx);

	while (ok_sample[i] != NULL) {
		CuAssert(tc, "Unable to read valid TLV.", KSITest_tlvFromFile(getFullResourcePath(ok_sample[i++]), &tlv) == KSI_OK);

		res = parseStructure(tlv, 0);

		CuAssert(tc, "Unable to parse valid TLV.", res == KSI_OK);

		KSI_TLV_free(tlv);
		tlv = NULL;

		break;
	}
}
Esempio n. 12
0
int KSI_TlvTemplate_deepCopy(KSI_CTX *ctx, const void *from, const KSI_TlvTemplate *baseTemplate, void *to) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmpTlv = NULL;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || from == NULL || baseTemplate == NULL || to == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	/* Create a dummy TLV */
	res = KSI_TLV_new(ctx, KSI_TLV_PAYLOAD_TLV, 0x0, 0, 0, &tmpTlv);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	/* Create a TLV object */
	res = KSI_TlvTemplate_construct(ctx, tmpTlv, from, baseTemplate);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	/* Evaluate the cloned object */
	res = KSI_TlvTemplate_extract(ctx, to, tmpTlv, baseTemplate);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tmpTlv);

	return res;
}
Esempio n. 13
0
int KSI_Utf8String_toTlv(KSI_CTX *ctx, KSI_Utf8String *o, unsigned tag, int isNonCritical, int isForward, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || o == NULL || tlv == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	res = KSI_TLV_new(ctx, tag, isNonCritical, isForward, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	if (o->len > 0xffff){
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "UTF8 string too long for TLV conversion.");
		goto cleanup;
	}

	res = KSI_TLV_setRawValue(tmp, o->value, (unsigned)o->len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*tlv = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tmp);

	return res;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
int KSI_PublicationsFile_serialize(KSI_CTX *ctx, KSI_PublicationsFile *pubFile, char **raw, size_t *raw_len) {
	int res;
	const unsigned char *buf = NULL;
	size_t buf_len = 0;
	KSI_TLV *tlv = NULL;
	unsigned char *tmp = NULL;
	size_t tmp_len = 0;
	size_t sig_len = 0;

	KSI_ERR_clearErrors(ctx);

	if (ctx == NULL || pubFile == 0 || raw == NULL || raw_len == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	/**
	 * Create TLV 0x700 that contains nested list of publication file TLVs.
	 * Calculate signed data length assuming that signature TLV is always the last.
	 */
	res = KSI_TLV_new(ctx, 0x700, 0, 0, &tlv);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_TlvTemplate_construct(ctx, tlv, pubFile, KSI_TLV_TEMPLATE(KSI_PublicationsFile));
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = publicationsFileTLV_getSignatureTLVLength(tlv, &sig_len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_TLV_getRawValue(tlv, &buf, &buf_len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}


	/**
	 * Append raw value to publication file header. Copy raw publication file into
	 * internal and external buffer.
	 */
	tmp_len = buf_len + sizeof(PUB_FILE_HEADER_ID) - 1;
	tmp = (unsigned char *) KSI_malloc(tmp_len);
	if (tmp == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	if (KSI_strncpy((char *)tmp, PUB_FILE_HEADER_ID, tmp_len) == NULL) {
		KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, NULL);
		goto cleanup;
	}

	memcpy(tmp + sizeof(PUB_FILE_HEADER_ID) - 1, buf, buf_len);

	if (pubFile->raw != NULL) KSI_free(pubFile->raw);
	pubFile->raw = tmp;
	pubFile->raw_len = tmp_len;
	pubFile->signedDataLength = tmp_len - sig_len;
	tmp = NULL;

	tmp = (unsigned char *) KSI_malloc(pubFile->raw_len);
	if (tmp == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	memcpy(tmp, pubFile->raw, pubFile->raw_len);
	*raw = (char *)tmp;
	*raw_len = pubFile->raw_len;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tlv);
	KSI_free(tmp);
	return res;
}
Esempio n. 16
0
int KSI_PublicationsFile_parse(KSI_CTX *ctx, const void *raw, size_t raw_len, KSI_PublicationsFile **pubFile) {
	int res;
	KSI_PublicationsFile *tmp = NULL;
	struct generator_st gen = {ctx, raw, raw_len, NULL, 0, 0, false};
	unsigned char *tmpRaw = NULL;
	const size_t hdrLen = strlen(PUB_FILE_HEADER_ID);

	KSI_ERR_clearErrors(ctx);

	if (ctx == NULL || raw == NULL || raw_len == 0 || pubFile == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	/* Check the header. */
	if (gen.len < hdrLen || memcmp(gen.ptr, PUB_FILE_HEADER_ID, hdrLen)) {
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unrecognized header.");
		goto cleanup;
	}

	/* Header verification ok - create the store object. */
	res = KSI_PublicationsFile_new(ctx, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	tmp->signedDataLength = hdrLen;

	/* Initialize generator. */
	gen.ptr += hdrLen;
	gen.len -= hdrLen;

	/* Read the payload of the file, and make no assumptions with the ordering. */
	res = KSI_TlvTemplate_extractGenerator(ctx, tmp, (void *)&gen, KSI_TLV_TEMPLATE(KSI_PublicationsFile), (int (*)(void *, KSI_TLV **))generateNextTlv);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	tmp->signedDataLength += gen.sig_offset;

	/* Copy the raw value */
	tmpRaw = KSI_malloc(raw_len);
	if (tmpRaw == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}
	memcpy(tmpRaw, raw, raw_len);

	tmp->raw = tmpRaw;
	tmp->raw_len = raw_len;
	tmpRaw = NULL;

	*pubFile = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:


	KSI_free(tmpRaw);
	KSI_TLV_free(gen.tlv);
	KSI_PublicationsFile_free(tmp);

	return res;
}
Esempio n. 17
0
static int extractGenerator(KSI_CTX *ctx, void *payload, void *generatorCtx, const KSI_TlvTemplate *tmpl, int (*generator)(void *, KSI_TLV **), struct tlv_track_s *tr, size_t tr_len, size_t tr_size) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tlv = NULL;
	char buf[1024];

	void *voidVal = NULL;
	void *compositeVal = NULL;
	void *valuep = NULL;
	KSI_TLV *tlvVal = NULL;

	size_t template_len = 0;
	bool templateHit[MAX_TEMPLATE_SIZE];
	bool groupHit[2] = {false, false};
	bool oneOf[2] = {false, false};
	size_t i;
	size_t tmplStart = 0;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || payload == NULL || generatorCtx == NULL || tmpl == NULL || generator == NULL || tr == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	/* Analyze the template. */
	template_len = getTemplateLength(tmpl);

	if (template_len == 0) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Empty template suggests invalid state.");
		goto cleanup;
	}

	/* Make sure there will be no buffer overflow. */
	if (template_len > MAX_TEMPLATE_SIZE) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Template too big");
		goto cleanup;
	}
	memset(templateHit, 0, sizeof(templateHit));

	while (1) {
		int matchCount = 0;
		res = generator(generatorCtx, &tlv);
		if (res != KSI_OK) {
			KSI_pushError(ctx, res, NULL);
			goto cleanup;
		}

		if (tlv == NULL) break;

		KSI_LOG_trace(ctx, "Starting to parse TLV[0x%02x]", KSI_TLV_getTag(tlv));

		if (tr_len < tr_size) {
			tr[tr_len].tag = KSI_TLV_getTag(tlv);
			tr[tr_len].desc = NULL;
		}

		for (i = tmplStart; i < template_len; i++) {
			if (tmpl[i].tag != KSI_TLV_getTag(tlv)) continue;
			if (i == tmplStart && !tmpl[i].multiple) tmplStart++;

			tr[tr_len].desc = tmpl[i].descr;

			matchCount++;
			templateHit[i] = true;
			if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G0) != 0) groupHit[0] = true;
			if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G1) != 0) groupHit[1] = true;

			if (FLAGSET(tmpl[i], KSI_TLV_TMPL_FLG_MOST_ONE_G0)) {
				if (oneOf[0]) {
					KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Mutually exclusive elements present within group 0.");
					goto cleanup;
				}
				oneOf[0] = true;
			}

			if (FLAGSET(tmpl[i], KSI_TLV_TMPL_FLG_MOST_ONE_G1)) {
				if (oneOf[1]) {
					KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Mutually exclusive elements present within group 0.");
					goto cleanup;
				}
				oneOf[1] = true;
			}

			valuep = NULL;
			if (tmpl[i].getValue != NULL) {
				/* Validate the value has not been set */
				res = tmpl[i].getValue(payload, (void **)&valuep);
				if (res != KSI_OK) {
					KSI_pushError(ctx, res, NULL);
					goto cleanup;
				}
			}

			if (valuep != NULL && !tmpl[i].multiple) {
				compositeVal = NULL;
				KSI_LOG_error(ctx, "Multiple occurrences of a unique tag 0x%02x", tmpl[i].tag);
				KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "To avoid memory leaks, a value may not be set more than once while parsing.");
				goto cleanup;
			}
			/* Parse the current TLV */
			switch (tmpl[i].type) {
				case KSI_TLV_TEMPLATE_OBJECT:
					KSI_LOG_trace(ctx, "Detected object template for TLV value extraction.");
					if (tmpl[i].fromTlv == NULL) {
						KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Invalid template: fromTlv not set.");
						goto cleanup;
					}

					res = tmpl[i].fromTlv(tlv, &voidVal);
					if (res != KSI_OK) {
						KSI_pushError(ctx, res, NULL);
						goto cleanup;
					}

					res = storeObjectValue(ctx, &tmpl[i], payload, voidVal);
					if (res != KSI_OK) {
						tmpl[i].destruct(voidVal); // FIXME: Make sure, it is a valid pointer.
						goto cleanup;
					}

					break;
				case KSI_TLV_TEMPLATE_COMPOSITE:
				{
					KSI_LOG_trace(ctx, "Detected composite template for TLV value extraction.");

					res = tmpl[i].construct(ctx, &compositeVal);
					if (res != KSI_OK) {
						KSI_pushError(ctx, res, NULL);
						goto cleanup;
					}

					res = extract(ctx, compositeVal, tlv, tmpl[i].subTemplate, tr, tr_len + 1, tr_size);
					if (res != KSI_OK) {
						KSI_LOG_error(ctx, "Unable to parse composite TLV: %s", track_str(tr, tr_len, tr_size, buf, sizeof(buf)));
						tmpl[i].destruct(compositeVal); // FIXME: Make sure is is a valid pointer.
						goto cleanup;
					}

					res = storeObjectValue(ctx, &tmpl[i], payload, (void *)compositeVal);
					if (res != KSI_OK) {
						KSI_pushError(ctx, res, NULL);
						goto cleanup;
					}

					/* Reset the buffer. */
					break;
				}
				default:
					KSI_LOG_error(ctx, "No template found.");
					/* Should not happen, but just in case. */
					KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Undefined template type");
					goto cleanup;
			}

			if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_MORE_DEFS) == 0) break;
		}

		/* Check if a match was found, an raise an error if the TLV is marked as critical. */
		if (matchCount == 0 && !KSI_TLV_isNonCritical(tlv)) {
			char errm[1024];
			KSI_snprintf(errm, sizeof(errm), "Unknown critical tag: %s", track_str(tr, tr_len + 1, tr_size, buf, sizeof(buf)));
			KSI_LOG_error(ctx, errm);
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
			goto cleanup;
		}
	}

	/* Check that every mandatory component was present. */
	for (i = 0; i < template_len; i++) {
		char errm[100];
		if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_MANDATORY) != 0 && !templateHit[i]) {
			KSI_snprintf(errm, sizeof(errm), "Mandatory element missing: %s->[0x%x]%s", track_str(tr, tr_len, tr_size, buf, sizeof(buf)), tmpl[i].tag, tmpl[i].descr != NULL ? tmpl[i].descr : "");
			KSI_LOG_debug(ctx, "%s", errm);
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
			goto cleanup;
		}
		if (((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G0) != 0 && !groupHit[0]) ||
				((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G1) != 0 && !groupHit[1])) {
			KSI_snprintf(errm, sizeof(errm), "Mandatory group missing: %s->[0x%x]%s", track_str(tr, tr_len, tr_size, buf, sizeof(buf)), tmpl[i].tag, tmpl[i].descr != NULL ? tmpl[i].descr : "");
			KSI_LOG_debug(ctx, "%s", errm);
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
			goto cleanup;
		}
	}

	res = KSI_OK;

cleanup:

	KSI_TLV_free(tlvVal);

	return res;
}
Esempio n. 18
0
static int generateNextTlv(struct generator_st *gen, KSI_TLV **tlv) {
	int res = KSI_UNKNOWN_ERROR;
	unsigned char *buf = NULL;
	size_t consumed = 0;
	KSI_FTLV ftlv;

	if (gen == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}


	if (gen->tlv != NULL) {
		KSI_TLV_free(gen->tlv);
		gen->tlv = NULL;
	}

	/* Try to parse only when there is something left to parse. */
	if (gen->len > 0) {
		memset(&ftlv, 0, sizeof(ftlv));
		res = KSI_FTLV_memRead(gen->ptr, gen->len, &ftlv);
		if (res != KSI_OK) {
			KSI_pushError(gen->ctx, res, NULL);
			goto cleanup;
		}

		consumed = ftlv.hdr_len + ftlv.dat_len;

		buf = KSI_malloc(consumed);
		if (buf == NULL) {
			KSI_pushError(gen->ctx, res = KSI_OUT_OF_MEMORY, NULL);
			goto cleanup;
		}

		memcpy(buf, gen->ptr, consumed);

		gen->ptr += consumed;
		gen->len -= consumed;

		/* Make sure the buffer is not overflowing. */
		if (consumed > UINT_MAX){
			KSI_pushError(gen->ctx, res = KSI_INVALID_FORMAT, "Input too large.");
			goto cleanup;
		}

		if (consumed > 0) {
			if (gen->hasSignature) {
				/* The signature must be the last element. */
				KSI_pushError(gen->ctx, res = KSI_INVALID_FORMAT, "The signature must be the last element.");
				goto cleanup;
			}

			res = KSI_TLV_parseBlob2(gen->ctx, buf, (unsigned)consumed, 1, &gen->tlv);
			if (res != KSI_OK) {
				KSI_pushError(gen->ctx, res, NULL);
				goto cleanup;
			}

			buf = NULL;

			if (KSI_TLV_getTag(gen->tlv) == 0x0704) {
				gen->sig_offset = gen->offset;
				gen->hasSignature = true;
			}
		}

	}

	gen->offset += consumed;
	*tlv = gen->tlv;

	res = KSI_OK;

cleanup:

	KSI_free(buf);

	return res;
}
Esempio n. 19
0
static int construct(KSI_CTX *ctx, KSI_TLV *tlv, const void *payload, const KSI_TlvTemplate *tmpl, struct tlv_track_s *tr, size_t tr_len, const size_t tr_size) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_TLV *tmp = NULL;
	void *payloadp = NULL;
	int isNonCritical = 0;
	int isForward = 0;

	size_t template_len = 0;
	bool templateHit[MAX_TEMPLATE_SIZE];
	bool groupHit[2] = {false, false};
	bool oneOf[2] = {false, false};

	size_t i;
	char buf[1000];

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || tlv == NULL || payload == NULL || tmpl == NULL || tr == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	/* Calculate the template length. */
	template_len = getTemplateLength(tmpl);

	if (template_len == 0) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "A template may not be empty.");
		goto cleanup;
	}

	if (template_len > MAX_TEMPLATE_SIZE) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Template too big.");
		goto cleanup;
	}

	memset(templateHit, 0, sizeof(templateHit));


	for (i = 0; i < template_len; i++) {
		if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_NO_SERIALIZE) != 0) continue;
		payloadp = NULL;

		res = tmpl[i].getValue(payload, &payloadp);
		if (res != KSI_OK) {
			KSI_pushError(ctx, res, NULL);
			goto cleanup;
		}

		if (payloadp != NULL) {
			/* Register for tracking. */
			if (tr_len < tr_size) {
				tr[tr_len].tag = tmpl[i].tag;
				tr[tr_len].desc = tmpl[i].descr;
			}

			templateHit[i] = true;

			if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G0) != 0) groupHit[0] = true;
			if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G1) != 0) groupHit[1] = true;
			if (FLAGSET(tmpl[i], KSI_TLV_TMPL_FLG_MOST_ONE_G0)) {
				if (oneOf[0]) {
					char errm[1000];
					KSI_snprintf(errm, sizeof(errm), "Mutually exclusive elements present within group 0 (%s).", track_str(tr, tr_len, tr_size, buf, sizeof(buf)));
					KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
				}
				oneOf[0] = true;
			}
			if (FLAGSET(tmpl[i], KSI_TLV_TMPL_FLG_MOST_ONE_G1)) {
				if (oneOf[1]) {
					char errm[1000];
					KSI_snprintf(errm, sizeof(errm), "Mutually exclusive elements present within group 1 (%s).", track_str(tr, tr_len, tr_size, buf, sizeof(buf)));
					KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
				}
				oneOf[1] = true;
			}

			isNonCritical = (tmpl[i].flags & KSI_TLV_TMPL_FLG_NONCRITICAL) != 0;
			isForward = (tmpl[i].flags & KSI_TLV_TMPL_FLG_FORWARD) != 0;

			switch (tmpl[i].type) {
				case KSI_TLV_TEMPLATE_OBJECT:
					if (tmpl[i].toTlv == NULL) {
						KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Invalid template: toTlv not set.");
						goto cleanup;
					}

					if (tmpl[i].listLength != NULL) {
						int j;
						for (j = 0; j < tmpl[i].listLength(payloadp); j++) {
							void *listElement = NULL;
							res = tmpl[i].listElementAt(payloadp, j, &listElement);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}

							res = tmpl[i].toTlv(ctx, listElement, tmpl[i].tag, isNonCritical, isForward != 0, &tmp);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}

							res = KSI_TLV_appendNestedTlv(tlv, tmp);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}

							tmp = NULL;
						}


					} else {
						res = tmpl[i].toTlv(ctx, payloadp, tmpl[i].tag, isNonCritical, isForward, &tmp);
						if (res != KSI_OK) {
							KSI_pushError(ctx, res, NULL);
							goto cleanup;
						}

						res = KSI_TLV_appendNestedTlv(tlv, tmp);
						if (res != KSI_OK) {
							KSI_pushError(ctx, res, NULL);
							goto cleanup;
						}
						tmp = NULL;
					}

					break;
				case KSI_TLV_TEMPLATE_COMPOSITE:
					if (tmpl[i].listLength != NULL) {
						int j;

						for (j = 0; j < tmpl[i].listLength(payloadp); j++) {
							void *listElement = NULL;

							res = KSI_TLV_new(ctx, KSI_TLV_PAYLOAD_TLV, tmpl[i].tag, isNonCritical, isForward, &tmp);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}

							res = tmpl[i].listElementAt(payloadp, j, &listElement);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}

							res = construct(ctx, tmp, listElement, tmpl[i].subTemplate, tr, tr_len + 1, tr_size);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}

							res = KSI_TLV_appendNestedTlv(tlv, tmp);
							if (res != KSI_OK) {
								KSI_pushError(ctx, res, NULL);
								goto cleanup;
							}
							tmp = NULL;
						}
					} else {
						res = KSI_TLV_new(ctx, KSI_TLV_PAYLOAD_TLV, tmpl[i].tag, isNonCritical, isForward, &tmp);
						if (res != KSI_OK) {
							KSI_pushError(ctx, res, NULL);
							goto cleanup;
						}

						res = construct(ctx, tmp, payloadp, tmpl[i].subTemplate, tr, tr_len + 1, tr_size);
						if (res != KSI_OK) {
							KSI_pushError(ctx, res, NULL);
							goto cleanup;
						}

						res = KSI_TLV_appendNestedTlv(tlv, tmp);
						if (res != KSI_OK) {
							KSI_pushError(ctx, res, NULL);
							goto cleanup;
						}
						tmp = NULL;
					}
					break;
				default:
					KSI_LOG_error(ctx, "Unimplemented template type: %d", tmpl[i].type);
					KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Unimplemented template type.");
					goto cleanup;
			}
		}
	}

	/* Check that every mandatory component was present. */
	for (i = 0; i < template_len; i++) {
		char errm[1000];
		if ((tmpl[i].flags & KSI_TLV_TMPL_FLG_MANDATORY) != 0 && !templateHit[i]) {
			KSI_snprintf(errm, sizeof(errm), "Mandatory element missing: %s->[0x%02x]%s", track_str(tr, tr_len, tr_size, buf, sizeof(buf)), tmpl[i].tag, tmpl[i].descr == NULL ? "" : tmpl[i].descr);
			KSI_LOG_debug(ctx, "%s", errm);
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
			goto cleanup;
		}
		if (((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G0) != 0 && !groupHit[0]) ||
				((tmpl[i].flags & KSI_TLV_TMPL_FLG_LEAST_ONE_G1) != 0 && !groupHit[1])) {
			KSI_snprintf(errm, sizeof(errm), "Mandatory group missing: %s->[0x%02x]%s", track_str(tr, tr_len, tr_size, buf, sizeof(buf)), tmpl[i].tag, tmpl[i].descr == NULL ? "" : tmpl[i].descr);
			KSI_LOG_debug(ctx, "%s", errm);
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errm);
			goto cleanup;
		}
	}

	res = KSI_OK;

cleanup:

	KSI_nofree(payloadp);

	KSI_TLV_free(tmp);

	return res;
}