Esempio n. 1
0
int KSI_PublicationsFile_getPublicationDataByTime(const KSI_PublicationsFile *trust, const KSI_Integer *pubTime, KSI_PublicationRecord **pubRec) {
	int res;
	size_t i;
	KSI_PublicationRecord *result = NULL;

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

	KSI_ERR_clearErrors(trust->ctx);

	if (pubTime == NULL || pubRec == NULL) {
		KSI_pushError(trust->ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	for (i = 0; i < KSI_PublicationRecordList_length(trust->publications); i++) {
		KSI_PublicationRecord *pr = NULL;
		KSI_PublicationData *pd = NULL;
		KSI_Integer *tm = NULL;

		res = KSI_PublicationRecordList_elementAt(trust->publications, i, &pr);
		if (res != KSI_OK) {
			KSI_pushError(trust->ctx, res, NULL);
			goto cleanup;
		}

		res = KSI_PublicationRecord_getPublishedData(pr, &pd);
		if (res != KSI_OK) {
			KSI_pushError(trust->ctx, res, NULL);
			goto cleanup;
		}

		res = KSI_PublicationData_getTime(pd, &tm);
		if (res != KSI_OK) {
			KSI_pushError(trust->ctx, res, NULL);
			goto cleanup;
		}

		if (KSI_Integer_equals(pubTime, tm)) {
			result = pr;
			break;
		}

		KSI_nofree(tm);
		KSI_nofree(pd);
	}

	*pubRec = result;

	res = KSI_OK;

cleanup:

	KSI_nofree(result);

	return res;
}
Esempio n. 2
0
int KSI_PublicationsFile_verify(KSI_PublicationsFile *pubFile, KSI_CTX *ctx) {
	int res;
	KSI_CTX *useCtx = ctx;
	KSI_PKITruststore *pki = NULL;

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

	if (useCtx == NULL) {
		useCtx = pubFile->ctx;
	}

	KSI_ERR_clearErrors(useCtx);

	/* Make sure the signature exists. */
	if (pubFile->signature == NULL) {
		KSI_pushError(useCtx, res = KSI_PUBLICATIONS_FILE_NOT_SIGNED_WITH_PKI, NULL);
		goto cleanup;
	}

	/* Do we need to serialize the publications file? */
	if (pubFile->raw == NULL) {
		/* FIXME! At the moment the creation of publications file is not supported,
		 * thus this error can not occur under normal conditions. */
		KSI_pushError(useCtx, res = KSI_UNKNOWN_ERROR, "Not implemented");
		goto cleanup;
	}

	res = KSI_CTX_getPKITruststore(useCtx, &pki);
	if (res != KSI_OK) {
		KSI_pushError(useCtx, res, NULL);
		goto cleanup;
	}

	res = KSI_PKITruststore_verifyPKISignature(pki, pubFile->raw, pubFile->signedDataLength, pubFile->signature, pubFile->certConstraints);
	if (res != KSI_OK) {
		KSI_pushError(useCtx, res, "Signature not verified.");
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	KSI_nofree(useCtx);
	KSI_nofree(pki);

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

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

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

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

	*o = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_nofree(ctx);
	KSI_Utf8String_free(tmp);

	return res;
}
Esempio n. 4
0
static int verifyAggregationRootWithCalendarChain(KSI_Signature *sig) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_DataHash *inputHash = NULL;
	KSI_VerificationStep step = KSI_VERIFY_AGGRCHAIN_WITH_CALENDAR_CHAIN;
	KSI_VerificationResult *info = &sig->verificationResult;
	KSI_AggregationHashChain *aggregationChain = NULL;
	KSI_Integer *calAggrTime = NULL;

	KSI_LOG_info(sig->ctx, "Verifying aggregation hash chain root.");

	res = KSI_CalendarHashChain_getInputHash(sig->calendarChain, &inputHash);
	if (res != KSI_OK) goto cleanup;

	/* Take the first aggregation hash chain, as all of the chain should have
	 * the same value for "aggregation time". */
	res = KSI_AggregationHashChainList_elementAt(sig->aggregationChainList, 0, &aggregationChain);
	if (res != KSI_OK || aggregationChain == NULL) {
		if (res == KSI_OK) res = KSI_INVALID_STATE;
		goto cleanup;
	}

	if (!KSI_DataHash_equals(sig->verificationResult.aggregationHash, inputHash)) {
		res = KSI_VerificationResult_addFailure(info, step, "Aggregation root hash mismatch.");
		if (res != KSI_OK) goto cleanup;
	}

	res = KSI_CalendarHashChain_getAggregationTime(sig->calendarChain, &calAggrTime);
	if (res != KSI_OK) goto cleanup;

	if (!KSI_Integer_equals(calAggrTime, aggregationChain->aggregationTime)) {
		res = KSI_VerificationResult_addFailure(info, step, "Aggregation time in calendar chain and aggregation chain differ.");
		if (res != KSI_OK) goto cleanup;
	}

	res = KSI_VerificationResult_addSuccess(info, step, "Aggregation root matches with calendar chain.");
	if (res != KSI_OK) goto cleanup;

cleanup:

	KSI_nofree(calAggrTime);
	KSI_nofree(aggregationChain);

	return res;
}
Esempio n. 5
0
int KSI_Integer_fromTlv(KSI_TLV *tlv, KSI_Integer **o) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	KSI_Integer *tmp = NULL;
	const unsigned char *raw = NULL;
	size_t len;
	size_t i;
	KSI_uint64_t val = 0;

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

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

	if (len > 8) {
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Integer larger than 64bit");
		goto cleanup;
	}

	/* Encode the up-to 64bit unsigned integer. */
	for (i = 0; i < len; i++) {
		val = val << 8 | raw[i];
	}

	/* Make sure the integer was coded properly. */
	if (len != KSI_UINT64_MINSIZE(val)) {
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Integer not properly formated.");
		goto cleanup;
	}

	res = KSI_Integer_new(ctx, val, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*o = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_nofree(ctx);
	KSI_Integer_free(tmp);

	return res;
}
Esempio n. 6
0
static int verifyDocument(KSI_Signature *sig) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_DataHash *hsh = NULL;
	KSI_VerificationStep step = KSI_VERIFY_DOCUMENT;
	KSI_VerificationResult *info = &sig->verificationResult;

	if (!sig->verificationResult.verifyDocumentHash) {
		res = KSI_OK;
		goto cleanup;
	}

	KSI_LOG_info(sig->ctx, "Verifying document hash.");
	KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Verifying document hash", sig->verificationResult.documentHash);

	if (sig->rfc3161 != NULL) {
		KSI_LOG_info(sig->ctx, "Document hash is compared with RFC 3161 input hash.");
		res = KSI_RFC3161_getInputHash(sig->rfc3161, &hsh);
		if (res != KSI_OK) goto cleanup;
	} else {
		res = KSI_Signature_getDocumentHash(sig, &hsh);
		if (res != KSI_OK) goto cleanup;
	}


	if (!KSI_DataHash_equals(hsh, sig->verificationResult.documentHash)) {
		KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Document hash", sig->verificationResult.documentHash);
		KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Signed   hash", hsh);

		res = KSI_VerificationResult_addFailure(info, step, "Wrong document.");
		goto cleanup;
	}

	res = KSI_VerificationResult_addSuccess(info, step, "Document correct.");

cleanup:

	KSI_nofree(hsh);
	KSI_nofree(info);

	return res;
}
Esempio n. 7
0
int KSI_Utf8String_fromTlv(KSI_TLV *tlv, KSI_Utf8String **o) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	const char *cstr = NULL;
	KSI_Utf8String *tmp = NULL;
	size_t len;

	ctx = KSI_TLV_getCtx(tlv);

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

	res = KSI_TLV_getRawValue(tlv, (const unsigned char **)&cstr, &len);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_Utf8String_new(ctx, cstr, len, &tmp);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	*o = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_nofree(ctx);
	KSI_nofree(cstr);
	KSI_Utf8String_free(tmp);

	return res;
}
Esempio n. 8
0
int KSI_PublicationsFile_getPKICertificateById(const KSI_PublicationsFile *pubFile, const KSI_OctetString *id, KSI_PKICertificate **cert) {
	int res;
	size_t i;
	KSI_CertificateRecord *certRec = NULL;

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

	KSI_ERR_clearErrors(pubFile->ctx);

	if (id == NULL || cert == NULL) {
		KSI_pushError(pubFile->ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}


	for (i = 0; i < KSI_CertificateRecordList_length(pubFile->certificates); i++) {
		KSI_OctetString *cId = NULL;

		res = KSI_CertificateRecordList_elementAt(pubFile->certificates, i, &certRec);
		if (res != KSI_OK) {
			KSI_pushError(pubFile->ctx, res, NULL);
			goto cleanup;
		}

		res = KSI_CertificateRecord_getCertId(certRec, &cId);
		if (res != KSI_OK) {
			KSI_pushError(pubFile->ctx, res, NULL);
			goto cleanup;
		}

		if (KSI_OctetString_equals(cId, id)) {
			res = KSI_CertificateRecord_getCert(certRec, cert);
			if (res != KSI_OK) {
				KSI_pushError(pubFile->ctx, res, NULL);
				goto cleanup;
			}

			break;
		}
	}

	res = KSI_OK;

cleanup:

	KSI_nofree(certRec);

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

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

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

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

	*hsh = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_nofree(ctx);
	KSI_nofree(raw);
	KSI_DataHash_free(tmp);

	return res;
}
Esempio n. 10
0
KSI_HashAlgorithm KSI_getHashAlgorithmByName(const char *name) {
	size_t i;
	KSI_HashAlgorithm algo_id = KSI_HASHALG_INVALID;
	int alias_id;

	char *alias = NULL;
	char *upperName = NULL;

	if (name == NULL || !*name || strchr(name, ',') != NULL) goto cleanup;

	upperName = KSI_calloc(strlen(name) + 1, 1);
	if (upperName == NULL) goto cleanup;

	/* Create upper-case name */
	for (i = 0; i < (int) strlen(name); i++) {
		if (name[i] == '_') {
			upperName[i] = '-';
		} else {
			upperName[i] = (char) toupper(name[i]);
		}
	}
	upperName[i] = '\0';

	for (i = 0; i < KSI_NUMBER_OF_KNOWN_HASHALGS; i++) {
		/* Skip all records without a name. */
		if (KSI_hashAlgorithmInfo[i].name == NULL) continue;

		/* Do we have a bingo? */
		if (!strcmp(upperName, KSI_hashAlgorithmInfo[i].name)) {
			algo_id = i;
			goto cleanup;
		}

		alias_id = 0;
		/* Loop until a null pointer or empty string. */
		while ((alias = KSI_hashAlgorithmInfo[i].aliases[alias_id++]) && *alias) {
			if (!strcmp(upperName, alias)) {
				algo_id = i;
				goto cleanup;
			}
		}
	}

cleanup:

	KSI_free(upperName);
	KSI_nofree(alias);

	return algo_id;
}
Esempio n. 11
0
int KSI_PublicationsFile_findPublication(const KSI_PublicationsFile *trust, KSI_PublicationRecord *inRec, KSI_PublicationRecord **outRec) {
	int res;
	size_t i;

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

	KSI_ERR_clearErrors(trust->ctx);

	if (inRec == NULL || outRec == NULL) {
		KSI_pushError(trust->ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}


	for (i = 0; i < KSI_PublicationRecordList_length(trust->publications); i++) {
		KSI_PublicationRecord *pr = NULL;

		res = KSI_PublicationRecordList_elementAt(trust->publications, i, &pr);
		if (res != KSI_OK || pr == NULL) {
			KSI_pushError(trust->ctx, res != KSI_OK ? res : (res = KSI_INVALID_STATE), NULL);
			goto cleanup;
		}

		if (pr->publishedData == NULL || inRec->publishedData == NULL) {
			KSI_pushError(trust->ctx, res = KSI_INVALID_STATE, NULL);
			goto cleanup;
		}

		if (KSI_DataHash_equals(pr->publishedData->imprint, inRec->publishedData->imprint) && KSI_Integer_equals(pr->publishedData->time, inRec->publishedData->time) ) {
			*outRec = KSI_PublicationRecord_ref(pr);
			break;
		}

		KSI_nofree(pr);
	}

	res = KSI_OK;

cleanup:

	return res;
}
Esempio n. 12
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. 13
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. 14
0
int KSI_PKISignature_fromTlv(KSI_TLV *tlv, KSI_PKISignature **sig) {
	KSI_CTX *ctx = NULL;
	int res = KSI_UNKNOWN_ERROR;

	KSI_PKISignature *tmp = NULL;
	const unsigned char *raw = NULL;
	unsigned int raw_len = 0;

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


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

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

	*sig = tmp;
	tmp = NULL;

	res = KSI_OK;


cleanup:

	KSI_nofree(raw);

	KSI_PKISignature_free(tmp);

	return res;
}
Esempio n. 15
0
int KSI_PublicationsFile_getLatestPublication(const KSI_PublicationsFile *trust, const KSI_Integer *pubTime, KSI_PublicationRecord **pubRec) {
	int res;
	size_t i;
	KSI_PublicationRecord *result = NULL;
	KSI_Integer *result_tm = NULL;

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

	KSI_ERR_clearErrors(trust->ctx);

	if (pubRec == NULL) {
		KSI_pushError(trust->ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}


	for (i = 0; i < KSI_PublicationRecordList_length(trust->publications); i++) {
		KSI_PublicationRecord *pr = NULL;
		KSI_PublicationData *pd = NULL;
		KSI_Integer *tm = NULL;

		res = KSI_PublicationRecordList_elementAt(trust->publications, i, &pr);
		if (res != KSI_OK) {
			KSI_pushError(trust->ctx, res, NULL);
			goto cleanup;
		}

		res = KSI_PublicationRecord_getPublishedData(pr, &pd);
		if (res != KSI_OK) {
			KSI_pushError(trust->ctx, res, NULL);
			goto cleanup;
		}

		res = KSI_PublicationData_getTime(pd, &tm);
		if (res != KSI_OK) {
			KSI_pushError(trust->ctx, res, NULL);
			goto cleanup;
		}

		/* Check if current publication time is after given time. */
		if (pubTime == NULL || KSI_Integer_compare(pubTime, tm) <= 0) {
			/* Check if current publication time is after the latest so far. */
			if (result_tm == NULL || KSI_Integer_compare(result_tm, tm) <= 0) {
				result = pr;
				result_tm = tm;
			}
		}

		KSI_nofree(tm);
		KSI_nofree(pd);
	}

	*pubRec = result;

	res = KSI_OK;

cleanup:

	KSI_nofree(result);
	KSI_nofree(result_tm);

	return res;
}
Esempio n. 16
0
int KSI_PublicationsFile_getPublicationDataByPublicationString(const KSI_PublicationsFile *pubFile, const char *pubString, KSI_PublicationRecord **pubRec) {
	int res;
	KSI_PublicationData *findPubData = NULL;
	KSI_DataHash *findImprint = NULL;
	KSI_Integer *findTime = NULL;

	KSI_PublicationRecord *tmpPubRec = NULL;
	KSI_PublicationData *tmpPubData = NULL;
	KSI_DataHash *tmpImprint = NULL;

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

	KSI_ERR_clearErrors(pubFile->ctx);

	if (pubString == NULL || pubRec == NULL) {
		KSI_pushError(pubFile->ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}


	/* Decode the publication string. */
	res = KSI_PublicationData_fromBase32(pubFile->ctx, pubString, &findPubData);
	if (res != KSI_OK) {
		KSI_pushError(pubFile->ctx, res, NULL);
		goto cleanup;
	}

	/* Extract the expected imprint. */
	res = KSI_PublicationData_getImprint(findPubData, &findImprint);
	if (res != KSI_OK) {
		KSI_pushError(pubFile->ctx, res, NULL);
		goto cleanup;
	}

	/* Extract the expected publication time. */
	res = KSI_PublicationData_getTime(findPubData, &findTime);
	if (res != KSI_OK) {
		KSI_pushError(pubFile->ctx, res, NULL);
		goto cleanup;
	}

	/* Find the publication using the publication time. */
	res = KSI_PublicationsFile_getPublicationDataByTime(pubFile, findTime, &tmpPubRec);
	if (res != KSI_OK) {
		KSI_pushError(pubFile->ctx, res, NULL);
		goto cleanup;
	}

	if (tmpPubRec != NULL) {
		/* Extract published data. */
		res = KSI_PublicationRecord_getPublishedData(tmpPubRec, &tmpPubData);
		if (res != KSI_OK) {
			KSI_pushError(pubFile->ctx, res, NULL);
			goto cleanup;
		}

		/* Extract the time. */
		res = KSI_PublicationData_getImprint(tmpPubData, &tmpImprint);
		if (res != KSI_OK) {
			KSI_pushError(pubFile->ctx, res, NULL);
			goto cleanup;
		}

		if (!KSI_DataHash_equals(findImprint, tmpImprint))  {
			KSI_pushError(pubFile->ctx, res = KSI_INVALID_PUBLICATION, NULL);
			goto cleanup;
		}
	}

	*pubRec = tmpPubRec;

	res = KSI_OK;

cleanup:

	KSI_PublicationData_free(findPubData);
	KSI_nofree(findImprint);
	KSI_nofree(findTime);

	KSI_nofree(tmpPubRec);
	KSI_nofree(tmpPubData);
	KSI_nofree(tmpImprint);

	return res;
}
Esempio n. 17
0
static int storeObjectValue(KSI_CTX *ctx, const KSI_TlvTemplate *tmpl, void *payload, void *val) {
	int res = KSI_UNKNOWN_ERROR;
	void *list = NULL;
	void *listp = NULL;

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

	/* Verify the correctness of the template. */
	if (tmpl->setValue == NULL) {
		KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Invalid template - missing setValue function.");
		goto cleanup;
	}

	if (tmpl->listAppend != NULL) {
		if (tmpl->getValue == NULL) {
			KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Invalid template - missing getValue function.");
			goto cleanup;
		}
		res = tmpl->getValue(payload, &listp);
		if (res != KSI_OK) goto cleanup;

		if (listp == NULL) {
			/* Make sure we have required function pointers. */
			if (tmpl->listNew == NULL || tmpl->listFree == NULL) {
				KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Template does not have list constructor or destructor, but list itself does not exist.");
				goto cleanup;
			}
			res = tmpl->listNew(&list);
			if (res != KSI_OK) {
				KSI_pushError(ctx, res, NULL);
				goto cleanup;
			}

			listp = list;
		}

		res = tmpl->listAppend(listp, (void *) val);
		if (res != KSI_OK) {
			KSI_pushError(ctx, res, NULL);
			goto cleanup;
		}

		res = tmpl->setValue(payload, listp);
		if (res != KSI_OK) {
			KSI_pushError(ctx, res, NULL);
			goto cleanup;
		}

		list = NULL;

	} else {
		/* Regular value - store with the setter. */
		res = tmpl->setValue(payload, (void *) val);
		if (res != KSI_OK) {
			KSI_pushError(ctx, res, NULL);
			goto cleanup;
		}
	}

	res = KSI_OK;

cleanup:

	KSI_nofree(listp);
	if (tmpl != NULL && tmpl->listFree != NULL) tmpl->listFree(list);

	return res;
}
Esempio n. 18
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;
}
Esempio n. 19
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;
}