/*TODO: Not supported*/
int KSI_PKITruststore_addLookupFile(KSI_PKITruststore *trust, const char *path) {
	int res = KSI_UNKNOWN_ERROR;
	HCERTSTORE tmp_FileTrustStore = NULL;
	char buf[1024];

	if (trust == NULL || path == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	KSI_ERR_clearErrors(trust->ctx);

	/*Open new store */
	tmp_FileTrustStore = CertOpenStore(CERT_STORE_PROV_FILENAME_A, 0, 0, 0, path);
	if (tmp_FileTrustStore == NULL) {
		KSI_LOG_debug(trust->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(trust->ctx, res = KSI_INVALID_FORMAT, NULL);
		goto cleanup;
	}

	/*Update with priority 0 store*/
	if (!CertAddStoreToCollection(trust->collectionStore, tmp_FileTrustStore, 0, 0)) {
		KSI_LOG_debug(trust->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(trust->ctx, res = KSI_INVALID_FORMAT, NULL);
		goto cleanup;
	}

	tmp_FileTrustStore = NULL;

	res = KSI_OK;

cleanup:

	if (tmp_FileTrustStore) CertCloseStore(tmp_FileTrustStore, CERT_CLOSE_STORE_CHECK_FLAG);
	return res;
}
Beispiel #2
0
static int verifyCalendarChainWithPublication(KSI_Signature *sig){
	int res = KSI_UNKNOWN_ERROR;
	KSI_CalendarHashChain *calChain = NULL;
	KSI_Integer *pubTime = NULL;
	KSI_DataHash *rootHash = NULL;
	KSI_PublicationRecord *sigPubRec = NULL;
	KSI_PublicationData *sigPubData = NULL;
	KSI_DataHash *publishedHash = NULL;
	KSI_Integer *publishedTime = NULL;
	KSI_VerificationStep step = KSI_VERIFY_CALCHAIN_WITH_PUBLICATION;
	KSI_VerificationResult *info = &sig->verificationResult;

	if (sig->publication == NULL) {
		res = KSI_OK;
		goto cleanup;
	}

	KSI_LOG_debug(sig->ctx, "Verifying calendar chain with publication.");

	calChain = sig->calendarChain;
	res = KSI_CalendarHashChain_getPublicationTime(calChain, &pubTime);
	if (res != KSI_OK) goto cleanup;

	res = KSI_CalendarHashChain_aggregate(calChain, &rootHash);
	if (res != KSI_OK) goto cleanup;

	sigPubRec = sig->publication;
	res = KSI_PublicationRecord_getPublishedData(sigPubRec, &sigPubData);
	if (res != KSI_OK) goto cleanup;

	res = KSI_PublicationData_getImprint(sigPubData, &publishedHash);
	if (res != KSI_OK) goto cleanup;

	res = KSI_PublicationData_getTime(sigPubData, &publishedTime);
	if (res != KSI_OK) goto cleanup;


	if (!KSI_DataHash_equals(rootHash, publishedHash)){
		KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Calendar root hash", rootHash);
		KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Published hash", publishedHash);
		res = KSI_VerificationResult_addFailure(info, step, "Published hash and calendar hash chain root hash mismatch.");
		goto cleanup;
	}

	if (!KSI_Integer_equals(pubTime, publishedTime)){
		KSI_LOG_debug(sig->ctx, "Calendar hash chain publication time: %i.", KSI_Integer_getUInt64(pubTime));
		KSI_LOG_debug(sig->ctx, "Published publication time: %i.", KSI_Integer_getUInt64(publishedTime));
		res = KSI_VerificationResult_addFailure(info, step, "Calendar hash chain publication time mismatch.");
		goto cleanup;
	}

	res = KSI_VerificationResult_addSuccess(info, step, "Calendar chain verified with publication.");

cleanup:

	KSI_DataHash_free(rootHash);

	return res;
}
Beispiel #3
0
int KSI_receivePublicationsFile(KSI_CTX *ctx, KSI_PublicationsFile **pubFile) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_RequestHandle *handle = NULL;
	const unsigned char *raw = NULL;
	size_t raw_len = 0;
	KSI_PublicationsFile *tmp = NULL;

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

	/* TODO! Implement mechanism for reloading (e.g cache timeout) */
	if (ctx->publicationsFile == NULL) {
		KSI_LOG_debug(ctx, "Receiving publications file.");

		res = KSI_sendPublicationRequest(ctx, NULL, 0, &handle);
		if (res != KSI_OK) {
			KSI_pushError(ctx,res, NULL);
			goto cleanup;
		}

		res = KSI_RequestHandle_perform(handle);
		if (res != KSI_OK) {
			KSI_pushError(ctx,res, NULL);
			goto cleanup;
		}

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

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

		ctx->publicationsFile = tmp;
		tmp = NULL;

		KSI_LOG_debug(ctx, "Publications file received.");
	}

	*pubFile = KSI_PublicationsFile_ref(ctx->publicationsFile);

	res = KSI_OK;

cleanup:

	KSI_RequestHandle_free(handle);
	KSI_PublicationsFile_free(tmp);

	return res;

}
Beispiel #4
0
static size_t receiveDataFromLibCurl(void *ptr, size_t size, size_t nmemb, void *stream) {
	size_t bytesCount = 0;
	unsigned char *tmp_buffer = NULL;
	CurlNetHandleCtx *nc = (CurlNetHandleCtx *) stream;

	bytesCount = nc->len + size * nmemb;
	if (bytesCount > UINT_MAX) {
		goto cleanup;
	}
	tmp_buffer = KSI_calloc(bytesCount, 1);
	if (tmp_buffer == NULL) goto cleanup;

	memcpy(tmp_buffer, nc->raw, nc->len);
	memcpy(tmp_buffer + nc->len, ptr, size * nmemb);

	KSI_free(nc->raw);
	nc->raw = tmp_buffer;
	nc->len = bytesCount;
	tmp_buffer = NULL;

	KSI_LOG_debug(nc->ctx, "0x%x: Received %llu bytes (%llu so far)", nc, (unsigned long long) bytesCount, nc->len);

	bytesCount = size * nmemb;

cleanup:

	KSI_free(tmp_buffer);
	return bytesCount;
}
Beispiel #5
0
static int curlReceive(KSI_RequestHandle *handle) {
	int res = KSI_UNKNOWN_ERROR;
	CurlNetHandleCtx *implCtx = NULL;
	long httpCode;

	if (handle == NULL || handle->client == NULL || handle->implCtx == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	KSI_ERR_clearErrors(handle->ctx);

	implCtx = handle->implCtx;

	KSI_LOG_debug(handle->ctx, "Sending request.");

	res = curl_easy_perform(implCtx->curl);
	KSI_LOG_debug(handle->ctx, "Received %llu bytes.", (unsigned long long)implCtx->len);

	if (curl_easy_getinfo(implCtx->curl, CURLINFO_HTTP_CODE, &httpCode) == CURLE_OK) {
		updateStatus(handle);
		KSI_LOG_debug(handle->ctx, "Received HTTP error code %d. Curl error '%s'.", httpCode, implCtx->curlErr);
	}

	if (res != CURLE_OK) {
		KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, implCtx->curlErr);
		goto cleanup;
	}

	res = KSI_RequestHandle_setResponse(handle, implCtx->raw, implCtx->len);
	if (res != KSI_OK) {
		KSI_pushError(handle->ctx, res, NULL);
		goto cleanup;
	}

	/* Cleanup on success.*/
	KSI_free(implCtx->raw);
	implCtx->raw = NULL;
	implCtx->len = 0;
	handle->completed = true;

	res = KSI_OK;

cleanup:

	return res;
}
int KSI_PKICertificate_new(KSI_CTX *ctx, const void *der, size_t der_len, KSI_PKICertificate **cert) {
	int res = KSI_UNKNOWN_ERROR;
	PCCERT_CONTEXT x509 = NULL;
	KSI_PKICertificate *tmp = NULL;
	char buf[1024];

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || der == NULL || der_len == 0 || cert == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	if (der_len > UINT_MAX) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Length is more than MAX_INT.");
		goto cleanup;
	}

	x509 = CertCreateCertificateContext(X509_ASN_ENCODING, der, (unsigned)der_len);
	if (x509 == NULL) {
		DWORD error = GetLastError();
		const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf));
		KSI_LOG_debug(ctx, "%s", errmsg);

		if (error == CRYPT_E_ASN1_EOD)
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Invalid PKI certificate. ASN.1 unexpected end of data.");
		else if (error == CRYPT_E_ASN1_MEMORY	)
			KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		else
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg);

		goto cleanup;
	}

	tmp = KSI_new(KSI_PKICertificate);
	if (tmp == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	tmp->ctx = ctx;
	tmp->x509 = x509;
	x509 = NULL;

	*cert = tmp;
	tmp = NULL;

	res = KSI_OK;


cleanup:

	if (x509 != NULL) CertFreeCertificateContext(x509);
	KSI_PKICertificate_free(tmp);

	return res;
}
static int KSI_PKITruststore_verifySignatureCertificate(const KSI_PKITruststore *pki, const KSI_PKISignature *signature) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	PCCERT_CONTEXT subjectCert = NULL;
	char tmp[256];
	char *magicEmail = NULL;

	if (pki == NULL || signature == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = pki->ctx;
	KSI_ERR_clearErrors(ctx);

	res = extractSigningCertificate(signature, &subjectCert);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	//printCertInfo(subjectCert);

	res=KSI_CTX_getPublicationCertEmail(ctx, &magicEmail);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	if (magicEmail != NULL){
		if (CertGetNameString(subjectCert, CERT_NAME_EMAIL_TYPE, 0, NULL, tmp, sizeof(tmp))==1){
			KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get subjects name from PKI certificate.");
			goto cleanup;
		}

		KSI_LOG_debug(ctx, "CryptoAPI: Subjects E-mail: %s.", tmp);

		if (strcmp(tmp, magicEmail) != 0) {
			KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Wrong subject name.");
			goto cleanup;
		}
	}

	res = KSI_PKITruststore_verifyCertificate(pki, subjectCert);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	if (subjectCert) CertFreeCertificateContext(subjectCert);

	return res;
}
int KSI_PKICertificate_serialize(KSI_PKICertificate *cert, unsigned char **raw, unsigned *raw_len) {
	int res = KSI_UNKNOWN_ERROR;
	unsigned char *tmp_serialized = NULL;
	DWORD len = 0;
	char buf[1024];

	if (cert == NULL || raw == NULL || raw_len == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	KSI_ERR_clearErrors(cert->ctx);

	if (!CertSerializeCertificateStoreElement(cert->x509, 0, NULL, &len)) {
		KSI_LOG_debug(cert->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(cert->ctx, res = KSI_CRYPTO_FAILURE, "Unable to serialize PKI certificate.");
		goto cleanup;
	}

	tmp_serialized = KSI_malloc(len);
	if (tmp_serialized == NULL) {
		KSI_pushError(cert->ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	if (!CertSerializeCertificateStoreElement(cert->x509, 0, (BYTE*)tmp_serialized, &len)){
		KSI_LOG_debug(cert->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(cert->ctx, res = KSI_CRYPTO_FAILURE, "Unable to serialize PKI certificate.");
		goto cleanup;
	}

	*raw = tmp_serialized;
	*raw_len = (unsigned)len;
	tmp_serialized = NULL;

	res = KSI_OK;

cleanup:

	KSI_free(tmp_serialized);

	return res;
}
void KSI_PKITruststore_free(KSI_PKITruststore *trust) {
	char buf[1024];

	if (trust != NULL) {
		if (trust->collectionStore != NULL){
			if (!CertCloseStore(trust->collectionStore, CERT_CLOSE_STORE_CHECK_FLAG)){
				KSI_LOG_debug(trust->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
				}
		}
		KSI_free(trust);
	}
}
Beispiel #10
0
static int sendRequest(KSI_NetworkClient *client, KSI_RequestHandle *handle, char *host, unsigned port) {
	int res;
	TcpClientCtx *tc = NULL;

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

	KSI_ERR_clearErrors(handle->ctx);

	if (client == NULL || host == NULL) {
		KSI_pushError(handle->ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

	tc = KSI_new(TcpClientCtx);
	if (tc == NULL) {
		KSI_pushError(handle->ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}
	tc->host = NULL;
	tc->port = 0;

	KSI_LOG_debug(handle->ctx, "Tcp: Sending request to: %s:%u", host, port);

	res = KSI_strdup(host, &tc->host);
	if (res != KSI_OK) {
		KSI_pushError(handle->ctx, res, NULL);
		goto cleanup;
	}
	tc->port = port;


	handle->readResponse = readResponse;
	handle->client = client;

	res = KSI_RequestHandle_setImplContext(handle, tc, (void (*)(void *))TcpClientCtx_free);
	if (res != KSI_OK) {
		KSI_pushError(handle->ctx, res, NULL);
		goto cleanup;
	}

	tc = NULL;

	res = KSI_OK;

cleanup:

	TcpClientCtx_free(tc);

	return res;
}
static int KSI_PKITruststore_verifySignatureCertificate(const KSI_PKITruststore *pki, const KSI_PKISignature *signature) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	PCCERT_CONTEXT subjectCert = NULL;
	char tmp[256];
	size_t i;

	if (pki == NULL || signature == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = pki->ctx;
	KSI_ERR_clearErrors(ctx);

	res = extractSigningCertificate(signature, &subjectCert);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	for (i = 0; pki->ctx->certConstraints[i].oid != NULL; i++) {
		KSI_CertConstraint *ptr = &pki->ctx->certConstraints[i];

		KSI_LOG_info(pki->ctx, "Verifying PKI signature certificate with oid = '%s' expected value '%s'.", ptr->oid, ptr->val);

		if (CertGetNameString(subjectCert, CERT_NAME_ATTR_TYPE, 0, ptr->oid, tmp, sizeof(tmp)) == 1){
			KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get OID value.");
			goto cleanup;
		}

		if (strcmp(tmp, ptr->val) != 0) {
			KSI_LOG_debug(pki->ctx, "Unexpected value for OID='%s': '%s'", ptr->oid, tmp);
			KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Unexpected OID value.");
			goto cleanup;
		}
	}

	res = KSI_PKITruststore_verifyCertificate(pki, subjectCert);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	if (subjectCert) CertFreeCertificateContext(subjectCert);

	return res;
}
Beispiel #12
0
int KSI_DataHasher_reset(KSI_DataHasher *hasher) {
	int res = KSI_UNKNOWN_ERROR;
	ALG_ID msHashAlg = 0;
	CRYPTO_HASH_CTX * pCryptoCTX = NULL;	//Crypto helper struct
	HCRYPTPROV pCSP = 0;					//Crypto service provider
	HCRYPTHASH pTmp_hash = 0;			//Hash object

	if (hasher == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	KSI_ERR_clearErrors(hasher->ctx);

	/*Shortcuts for pointers*/
	pCryptoCTX = (CRYPTO_HASH_CTX*)hasher->hashContext;
	pCSP = pCryptoCTX->pt_CSP;

	/*Convert hash algorithm into crypto api style*/
	msHashAlg = hashAlgorithmToALG_ID(hasher->algorithm);
	if (msHashAlg == 0) {
		KSI_pushError(hasher->ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL);
		goto cleanup;
	}

	/*If hasher object already exists, destroy one*/
	if (pTmp_hash != 0){
		CryptDestroyHash(pTmp_hash);
		}

	/*Create new hasher object*/
	if (!CryptCreateHash(pCSP, msHashAlg, 0,0,&pTmp_hash)) {
		DWORD error = GetLastError();
		KSI_LOG_debug(hasher->ctx, "Cryptoapi: Create hash error %i\n", error);
		KSI_pushError(hasher->ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
		}

	pCryptoCTX->pt_hHash = pTmp_hash;

	pTmp_hash = 0;

	res = KSI_OK;

cleanup:

	if (pTmp_hash) CryptDestroyHash(pTmp_hash);

	return res;
}
int KSI_PKITruststore_new(KSI_CTX *ctx, int setDefaults, KSI_PKITruststore **trust) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_PKITruststore *tmp = NULL;
	HCERTSTORE collectionStore = NULL;
	char buf[1024];

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


	res = KSI_CTX_registerGlobals(ctx, cryptopapiGlobal_init, cryptopapiGlobal_cleanup);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	//TODO: Will be removed
	/*Open certificate store as collection of other stores*/
	collectionStore = CertOpenStore(CERT_STORE_PROV_COLLECTION, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, NULL);
	if (collectionStore == NULL) {
		KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, NULL);
		goto cleanup;
	}

	tmp = KSI_new(KSI_PKITruststore);
	if (tmp == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	tmp->ctx = ctx;
	tmp->collectionStore = collectionStore;

	*trust = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_PKITruststore_free(tmp);

	return res;
}
Beispiel #14
0
static int extract(KSI_CTX *ctx, void *payload, KSI_TLV *tlv, const KSI_TlvTemplate *tmpl, struct tlv_track_s *tr, size_t tr_len, size_t tr_size) {
	int res = KSI_UNKNOWN_ERROR;
	int tr_inc = 0;
	TLVListIterator iter;

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

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

	res = KSI_TLV_getNestedList(tlv, &iter.list);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	iter.idx = 0;

	/*When extracting second tlv there is no need to register it twice because it is mention in lower level.*/
	if (tr_len == 0) {
		tr[tr_len].tag = KSI_TLV_getTag(tlv);
		tr[tr_len].desc = NULL;
		tr_inc = 1;
	}

	res = extractGenerator(ctx, payload, (void *)&iter, tmpl, (int (*)(void *, KSI_TLV **))TLVListIterator_next, tr, tr_len + tr_inc, tr_size);
	if (res != KSI_OK) {
		char buf[1024];
		KSI_LOG_debug(ctx, "Unable to parse TLV: %s", track_str(tr, tr_len, tr_size, buf, sizeof(buf)));
		KSI_pushError(ctx, res, buf);
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	return res;

}
Beispiel #15
0
static void TestSerialize(CuTest* tc) {
	int res;
	KSI_TLV *tlv = NULL;

	unsigned char in[0xffff + 4];
	unsigned char out[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) {
		KSI_LOG_debug(ctx, "TestSerialize: opening file '%s'.", ok_sample[i]);
		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);

		/* Re assemble TLV */
		KSI_TLV_serialize_ex(tlv, out, sizeof(out), &out_len);

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

		KSI_TLV_free(tlv);
		tlv = NULL;
		i++;
	}
}
Beispiel #16
0
static int verifyPublicationsFile(KSI_CTX *ctx, KSI_Signature *sig) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_VerificationStep step = KSI_VERIFY_PUBFILE_SIGNATURE;
	KSI_VerificationResult *info = &sig->verificationResult;

	KSI_LOG_debug(sig->ctx, "Verifying publications file.");

	res = initPublicationsFile(&sig->verificationResult, ctx);
	if (res != KSI_OK) goto cleanup;

	res = KSI_PublicationsFile_verify(sig->verificationResult.publicationsFile, ctx);
	if (res == KSI_OK) {
		res = KSI_VerificationResult_addSuccess(info, step, "Publications file verified.");
	} else {
		res = KSI_VerificationResult_addFailure(info, step, "Publications file not verified.");
	}

cleanup:

	return res;
}
Beispiel #17
0
int KSI_DataHasher_add(KSI_DataHasher *hasher, const void *data, size_t data_length) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	CRYPTO_HASH_CTX * pCryptoCTX = NULL;	//Crypto helper struct
	HCRYPTHASH pHash = 0;			//Hash object


	if (hasher == NULL || data == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = hasher->ctx;
	KSI_ERR_clearErrors(ctx);


	pCryptoCTX = (CRYPTO_HASH_CTX*)hasher->hashContext;
	pHash = pCryptoCTX->pt_hHash;

	if(data_length > UINT_MAX){
		KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Cryptoapi: Unable to add mote than UINT_MAX data to the hasher.");
		goto cleanup;
	}

	if (!CryptHashData(pHash, data, (DWORD)data_length, 0)){
		DWORD error = GetLastError();
		KSI_LOG_debug(ctx, "Cryptoapi: HashData error %i\n", error);
		KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Cryptoapi: Unable to add data to the hash");
		goto cleanup;
		}

	res = KSI_OK;

cleanup:

	return res;
}
Beispiel #18
0
char *KSI_PublicationData_toString(KSI_PublicationData *t, char *buffer, size_t buffer_len) {
	int res = KSI_UNKNOWN_ERROR;
	char *ret = NULL;
	size_t len = 0;
	char *pubStr = NULL;
	char tmp[256];

	res = KSI_PublicationData_toBase32(t, &pubStr);
	if (res != KSI_OK) {
		KSI_LOG_debug(t->ctx, "Unable to convert publication data to base 32: %s (%d)", KSI_getErrorString(res), res);
		goto cleanup;
	}

	len += KSI_snprintf(buffer + len, buffer_len - len, "Publication string: %s\nPublication date: %s", pubStr, KSI_Integer_toDateString(t->time, tmp, sizeof(tmp)));
	KSI_snprintf(buffer + len, buffer_len - len, "\nPublished hash: %s", KSI_DataHash_toString(t->imprint, tmp, sizeof(tmp)));

	ret = buffer;

cleanup:

	KSI_free(pubStr);

	return ret;
}
Beispiel #19
0
/*TODO: check chain index verification*/
static int rfc3161_verify(const KSI_Signature *sig) {
	int res;
	KSI_CTX *ctx = NULL;
	KSI_RFC3161 *rfc3161 = NULL;
	KSI_AggregationHashChainList *aggreChain = NULL;
	KSI_AggregationHashChain *firstChain = NULL;
	unsigned i;


	if (sig == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = sig->ctx;
	KSI_ERR_clearErrors(ctx);


	rfc3161 = sig->rfc3161;
	if (rfc3161 == NULL) {
		res = KSI_OK;
		goto cleanup;
	}

	aggreChain = sig->aggregationChainList;
	if (aggreChain == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_SIGNATURE, "Aggregation chain is missing.");
		goto cleanup;
	}

	res = KSI_AggregationHashChainList_elementAt(aggreChain, 0, &firstChain);
	if (res != KSI_OK || firstChain == NULL) {
		KSI_pushError(ctx, res != KSI_OK ? res : (res = KSI_INVALID_STATE), NULL);
		goto cleanup;
	}

	if (KSI_Integer_compare(firstChain->aggregationTime, rfc3161->aggregationTime) != 0) {
		KSI_LOG_debug(ctx, "Signatures aggregation time: %i.", KSI_Integer_getUInt64(firstChain->aggregationTime));
		KSI_LOG_debug(ctx, "RFC 3161 aggregation time:   %i.", KSI_Integer_getUInt64(rfc3161->aggregationTime));
		KSI_pushError(ctx, res = KSI_VERIFICATION_FAILURE, "Aggregation chain and RFC 3161 aggregation time mismatch.");
		goto cleanup;
	}

	if (KSI_IntegerList_length(firstChain->chainIndex) != KSI_IntegerList_length(rfc3161->chainIndex)) {
		KSI_LOG_debug(ctx, "Aggregation chain and RFC 3161 chain index mismatch.", KSI_IntegerList_length(firstChain->chainIndex));
		KSI_LOG_debug(ctx, "Signatures chain index length: %i.", KSI_IntegerList_length(firstChain->chainIndex));
		KSI_LOG_debug(ctx, "RFC 3161 chain index length:   %i.", KSI_IntegerList_length(rfc3161->chainIndex));
	}else {
		for (i = 0; i < KSI_IntegerList_length(firstChain->chainIndex); i++){
			KSI_Integer *ch1 = NULL;
			KSI_Integer *ch2 = NULL;

			res = KSI_IntegerList_elementAt(firstChain->chainIndex, i, &ch1);
			if (res != KSI_OK) {
				KSI_pushError(ctx, res, NULL);
				goto cleanup;
			}

			res = KSI_IntegerList_elementAt(rfc3161->chainIndex, i, &ch2);
			if (res != KSI_OK) {
				KSI_pushError(ctx, res, NULL);
				goto cleanup;
			}

			if (KSI_Integer_compare(ch1, ch2) != 0) {
				KSI_LOG_debug(ctx, "Aggregation chain and RFC 3161 chain index mismatch.", KSI_IntegerList_length(firstChain->chainIndex));
				break;
			}
		}
	}


	res = KSI_OK;

cleanup:

	return res;
}
static int KSI_PKITruststore_verifyCertificate(const KSI_PKITruststore *pki, const PCCERT_CONTEXT cert){
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	CERT_ENHKEY_USAGE enhkeyUsage;
	CERT_USAGE_MATCH certUsage;
	CERT_CHAIN_PARA chainPara;
	PCCERT_CHAIN_CONTEXT pChainContext = NULL;
	CERT_CHAIN_POLICY_PARA policyPara;
	CERT_CHAIN_POLICY_STATUS policyStatus;
	char buf[1024];

	if (pki == NULL || cert == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = pki->ctx;
	KSI_ERR_clearErrors(ctx);

	/* Get the certificate chain of certificate under verification. */
	/*OID List for certificate trust list extensions*/
	enhkeyUsage.cUsageIdentifier = 0;
	enhkeyUsage.rgpszUsageIdentifier = NULL;
	/*Criteria for identifying issuer certificate for chain building*/
	certUsage.dwType = USAGE_MATCH_TYPE_AND;
	certUsage.Usage = enhkeyUsage;
	/*Searching and matching criteria for chain building*/
	chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
	chainPara.RequestedUsage = certUsage;

	/*Use CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL for no automatic cert store update by windows.
	 It is useful when there is need to remove default cert from system store*/
	/*Build Certificate Chain from top to root certificate*/
	if (!CertGetCertificateChain(NULL, cert, NULL, pki->collectionStore, &chainPara, 0, NULL, &pChainContext)) {
		KSI_LOG_debug(pki->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get PKI certificate chain");
		goto cleanup;
	}
//TODO: debugging
//	printCertChain(pChainContext);

	/*TODO: REMOVE*/
	/*If chain is based on untrusted root, determine if it's in pki->collectionStore.
	 If it is, enable chain verification to trust untrusted roots*/
	if (pChainContext->TrustStatus.dwErrorStatus&CERT_TRUST_IS_UNTRUSTED_ROOT){
		KSI_LOG_debug(ctx, "CryptoAPI: Root certificate is not present under Windows 'Trusted Root Certification Authorities'.");
		KSI_LOG_debug(ctx, "CryptoAPI: Searching if it is present under PKI Trust Store from files.");
		if (isUntrustedRootCertInStore(pki, pChainContext)){
			policyPara.dwFlags =  CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
			KSI_LOG_debug(ctx, "CryptoAPI: Certificate is present. Allow untrusted root certificates");
		}
		else{
			policyPara.dwFlags = 0;
			KSI_LOG_debug(ctx, "CryptoAPI: Certificate is not present.");
		}
	}
	else if (pChainContext->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) {
		KSI_LOG_debug(ctx, "%s", getCertificateChainErrorStr(pChainContext));
		KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, getCertificateChainErrorStr(pChainContext));
		goto cleanup;
	}
	else{
		policyPara.dwFlags = 0;
	}

	/* Verify certificate chain. */
	policyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
	policyPara.pvExtraPolicyPara = 0;

	if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, pChainContext, &policyPara, &policyStatus)) {
		KSI_LOG_debug(pki->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, NULL);
		goto cleanup;
	}

	if (policyStatus.dwError) {
		KSI_LOG_debug(ctx, "CryptoAPI: PKI chain policy error %X.", policyStatus.dwError);
 		KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, NULL);
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	if (pChainContext) CertFreeCertificateChain(pChainContext);

	return res;
}
Beispiel #21
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;
}
Beispiel #22
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;
}
/*cert obj must be freed*/
static int extractSigningCertificate(const KSI_PKISignature *signature, PCCERT_CONTEXT *cert) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	HCERTSTORE certStore = NULL;
	DWORD signerCount = 0;
	PCERT_INFO pSignerCertInfo = NULL;
	HCRYPTMSG signaturMSG = NULL;
	PCCERT_CONTEXT signing_cert = NULL;
	BYTE *dataRecieved = NULL;
	char buf[1024];
	DWORD dataLen = 0;

	if (signature == NULL || cert == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = signature->ctx;
	KSI_ERR_clearErrors(ctx);


	/*Get Signature certificates as a certificate store*/
	certStore = CryptGetMessageCertificates(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, (HCRYPTPROV_LEGACY)NULL, 0, signature->pkcs7.pbData, signature->pkcs7.cbData);
	if (certStore == NULL){
		KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to get signatures PKI certificates.");
		goto cleanup;
	 }

	/*Counting signing certificates*/
	signerCount = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, signature->pkcs7.pbData, signature->pkcs7.cbData);
	if (signerCount == -1){
		KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to count PKI signatures certificates.");
		goto cleanup;
	}

	/*Is there exactly 1 signing cert?*/
	if (signerCount != 1){
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "PKI signature certificate count is not 1.");
		goto cleanup;
	}

	/*Open signature for decoding*/
	signaturMSG = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0,0, NULL, NULL);
	if (signaturMSG == NULL){
		DWORD error = GetLastError();
		const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf));
		KSI_LOG_debug(signature->ctx, "%s", errmsg);

		if (error == E_INVALIDARG)
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg);
		else if (error == E_OUTOFMEMORY)
			KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		else
			KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, errmsg);

		goto cleanup;
	}

	if (!CryptMsgUpdate(signaturMSG, signature->pkcs7.pbData, signature->pkcs7.cbData, TRUE)){
		DWORD error = GetLastError();
		const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf));
		KSI_LOG_debug(signature->ctx, "%s", errmsg);

		if (error == E_OUTOFMEMORY)
			KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		else if (error == CRYPT_E_UNEXPECTED_ENCODING)
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "The PKI signature is not encoded as PKCS7.");
		else if (error == CRYPT_E_MSG_ERROR)
			KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, errmsg);
		else
			KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, errmsg);

		goto cleanup;
	}

	/*Get signatures signing cert id*/
	if (!CryptMsgGetParam (signaturMSG, CMSG_SIGNER_CERT_INFO_PARAM, 0, NULL, &dataLen)){
		DWORD error = GetLastError();
		const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf));
		KSI_LOG_debug(signature->ctx, "%s", errmsg);

		if (error == CRYPT_E_ATTRIBUTES_MISSING)
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "The PKI signature does not contain signing certificate id.");
		else
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg);

		goto cleanup;
	}

	dataRecieved = KSI_malloc(dataLen);
	if (dataRecieved == NULL){
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	if (!CryptMsgGetParam (signaturMSG, CMSG_SIGNER_CERT_INFO_PARAM, 0, dataRecieved, &dataLen)){
		KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Unable to get PKI signatures signing certificate id.");
		goto cleanup;
	}

	pSignerCertInfo = (PCERT_INFO)dataRecieved;

	/*Get signing cert*/
	signing_cert = CertGetSubjectCertificateFromStore(certStore, X509_ASN_ENCODING, pSignerCertInfo);
	if (signing_cert == NULL){
		KSI_LOG_debug(signature->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get PKI signatures signer certificate.");
		goto cleanup;
	}

	/*The copy of the object is NOT created. Just its reference value is incremented*/
	signing_cert = CertDuplicateCertificateContext(signing_cert);

	*cert = signing_cert;
	signing_cert = NULL;


	res = KSI_OK;

cleanup:

	if (signing_cert) CertFreeCertificateContext(signing_cert);
	if (certStore) CertCloseStore(certStore, CERT_CLOSE_STORE_CHECK_FLAG);
	if (signaturMSG) CryptMsgClose(signaturMSG);
	KSI_free(dataRecieved);

	return res;
}
Beispiel #24
0
static int sendRequest(KSI_NetworkClient *client, KSI_RequestHandle *handle, char *url) {
	int res = KSI_UNKNOWN_ERROR;
	CurlNetHandleCtx *implCtx = NULL;
	KSI_HttpClient *http = client->impl;
	char mimeTypeHeader[1024];

	if (client == NULL || client->ctx == NULL || handle == NULL || url == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	KSI_ERR_clearErrors(client->ctx);

	res = CurlNetHandleCtx_new(client->ctx, &implCtx);
	if (res != KSI_OK) {
		KSI_pushError(client->ctx, res, NULL);
		goto cleanup;
	}

	KSI_LOG_debug(handle->ctx, "Curl: Preparing request to: %s", url);

	implCtx->curl = curl_easy_init();
	if (implCtx->curl == NULL) {
		KSI_pushError(client->ctx, res = KSI_OUT_OF_MEMORY, "Unable to init CURL.");
		goto cleanup;
	}

	curl_easy_setopt(implCtx->curl, CURLOPT_VERBOSE, 0);
	curl_easy_setopt(implCtx->curl, CURLOPT_WRITEFUNCTION, receiveDataFromLibCurl);
	curl_easy_setopt(implCtx->curl, CURLOPT_NOPROGRESS, 1);

	/* Make sure cURL won't use signals. */
	curl_easy_setopt(implCtx->curl, CURLOPT_NOSIGNAL, 1);

	curl_easy_setopt(implCtx->curl, CURLOPT_ERRORBUFFER, implCtx->curlErr);
	if (http->agentName != NULL) {
		curl_easy_setopt(implCtx->curl, CURLOPT_USERAGENT, http->agentName);
	}

	if (http->mimeType != NULL) {
		KSI_snprintf(mimeTypeHeader, sizeof(mimeTypeHeader) ,"Content-Type: %s", http->mimeType);
		implCtx->httpHeaders = curl_slist_append(implCtx->httpHeaders, mimeTypeHeader);
		curl_easy_setopt(implCtx->curl, CURLOPT_HTTPHEADER, implCtx->httpHeaders);
	}

	if (handle->request != NULL) {
		curl_easy_setopt(implCtx->curl, CURLOPT_POST, 1);
		curl_easy_setopt(implCtx->curl, CURLOPT_POSTFIELDS, (char *)handle->request);
		curl_easy_setopt(implCtx->curl, CURLOPT_POSTFIELDSIZE, (long)handle->request_length);
	} else {
		curl_easy_setopt(implCtx->curl, CURLOPT_POST, 0);
	}

	curl_easy_setopt(implCtx->curl, CURLOPT_WRITEDATA, implCtx);

	curl_easy_setopt(implCtx->curl, CURLOPT_CONNECTTIMEOUT, http->connectionTimeoutSeconds);
	curl_easy_setopt(implCtx->curl, CURLOPT_TIMEOUT, http->readTimeoutSeconds);

	curl_easy_setopt(implCtx->curl, CURLOPT_URL, url);

	handle->readResponse = curlReceive;
	handle->client = client;

	res = KSI_RequestHandle_setImplContext(handle, implCtx, (void (*)(void *))CurlNetHandleCtx_free);
	if (res != KSI_OK) {
		KSI_pushError(handle->ctx, res, NULL);
		goto cleanup;
	}

	implCtx = NULL;

	res = KSI_OK;

cleanup:

	CurlNetHandleCtx_free(implCtx);

	return res;
}
Beispiel #25
0
/**
 * Prepares request and opens a session handle.
 */
static int wininetSendRequest(KSI_NetworkClient *client, KSI_RequestHandle *handle, char *url) {
	int res;
	KSI_CTX *ctx = NULL;
	wininetNetHandleCtx *wininetHandle = NULL;
	KSI_HttpClient *http = (KSI_HttpClient *)client;
	HINTERNET internetHandle;
	char msg[1024];
	char *scheme = NULL;
	char *hostName = NULL;
	char *query = NULL;
	int port = 0;


	if (client == NULL || handle == NULL || url == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = handle->ctx;
	KSI_ERR_clearErrors(ctx);

	if (http->implCtx == NULL) {
		res = KSI_INVALID_ARGUMENT;
		KSI_pushError(ctx, res, "Network client http implementation context not set.");
		goto cleanup;
	}

	/*Initializing of wininet helper struct*/
	res = wininetNetHandleCtx_new(&wininetHandle);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	wininetHandle->ctx = ctx;
	internetHandle = http->implCtx;

	res = KSI_UriSplitBasic(url, &scheme, &hostName, &port, &query);
	if(res != KSI_OK){
		KSI_snprintf(msg, sizeof(msg), "WinINet: Unable to crack url '%s'.", url);
		KSI_pushError(ctx, res, msg);
		goto cleanup;
	}

	if(scheme == NULL || strcmp("http", scheme) != 0 && strcmp("https", scheme) != 0){
		KSI_snprintf(msg, sizeof(msg), "WinINet: unknown Internet scheme '%s'.", scheme);
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, msg);
		goto cleanup;
	}

	if(hostName == NULL || query == NULL){
		KSI_snprintf(msg, sizeof(msg), "WinINet: Invalid url '%s'.", url);
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, msg);
		goto cleanup;
	}

	if (handle->request_length > LONG_MAX) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "WinINet: Request too long.");
		goto cleanup;
	}

	KSI_LOG_debug(ctx, "WinINet: Sending request to: %s.", url);
	/*Preparing session handle*/
	//Opens an HTTP session for a given site
	wininetHandle->session_handle = InternetConnectA(internetHandle, hostName, port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
	if (wininetHandle->session_handle == NULL) {
		WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to initialize connection handle.");
	}

	wininetHandle->request_handle = HttpOpenRequestA(wininetHandle->session_handle,
		(handle->request == NULL ? "GET" : "POST"),
		query, NULL, NULL, NULL,
		(strcmp("https", scheme) == 0 ? INTERNET_FLAG_SECURE : 0),
		0);

	if (wininetHandle->request_handle == NULL){
		WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to initialize request handle.");
	}

	/*TODO Timeout is set, but seems to have no effect*/
	if (http->connectionTimeoutSeconds >= 0) {
		DWORD dw = (http->connectionTimeoutSeconds == 0 ? 0xFFFFFFFF : http->connectionTimeoutSeconds * 1000);
		if (!InternetSetOption(wininetHandle->request_handle, INTERNET_OPTION_CONNECT_TIMEOUT, &dw, sizeof(dw))){
			WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to set connection timeout.");
		}
	}

	if (http->readTimeoutSeconds >= 0) {
		DWORD dw = (http->readTimeoutSeconds == 0 ? 0xFFFFFFFF : http->readTimeoutSeconds * 1000);
		if (!InternetSetOption(wininetHandle->request_handle, INTERNET_OPTION_SEND_TIMEOUT, &dw, sizeof(dw))){
			WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to set send timeout.");
		}
		if (!InternetSetOption(wininetHandle->request_handle, INTERNET_OPTION_RECEIVE_TIMEOUT, &dw, sizeof(dw))){
			WININET_ERROR(ctx, GetLastError(), KSI_NETWORK_ERROR, "WinINet: Unable to set receive timeout.");
		}
	}

	handle->readResponse = wininetReceive;
	handle->client = client;

    res = KSI_RequestHandle_setImplContext(handle, wininetHandle, (void (*)(void *))wininetNetHandleCtx_free);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

    wininetHandle = NULL;
	res = KSI_OK;

cleanup:

	wininetNetHandleCtx_free(wininetHandle);

	KSI_free(query);
	KSI_free(hostName);
	KSI_free(scheme);

	return res;
}
Beispiel #26
0
static int performN(KSI_NetworkClient *client, KSI_RequestHandle **arr, size_t arr_len) {
	int res = KSI_UNKNOWN_ERROR;
	CURLM *cm = NULL;
	CURLMcode cres;
	size_t i;
	int count;
	char buf[1024];
	fd_set fdread;
	fd_set fdwrite;
	fd_set fdexcep;
	int maxfd = -1;
	struct timeval timeout;

	FD_ZERO(&fdread);
	FD_ZERO(&fdwrite);
	FD_ZERO(&fdexcep);

	if (client == NULL || (arr == NULL && arr_len != 0)) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	KSI_ERR_clearErrors(client->ctx);

	KSI_LOG_debug(client->ctx, "Starting cURL multi perform.");

	timeout.tv_sec = 0;
	timeout.tv_usec = 100;

	cm = curl_multi_init();
	if (cm == NULL) {
		KSI_pushError(client->ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	for (i = 0; i < arr_len; i++) {
		CurlNetHandleCtx *pctx = arr[i]->implCtx;
		cres = curl_multi_add_handle(cm, pctx->curl);
		if (cres != CURLM_OK) {
			KSI_snprintf(buf, sizeof(buf), "Curl error occurred: %s", curl_multi_strerror(cres));
			KSI_pushError(client->ctx, res = KSI_UNKNOWN_ERROR, buf);
			goto cleanup;
		}
	}

	curl_multi_setopt(cm, CURLMOPT_PIPELINING, 1);

	do {
		cres  = curl_multi_fdset(cm, &fdread, &fdwrite, &fdexcep, &maxfd);
		if (cres != CURLM_OK) {
			KSI_snprintf(buf, sizeof(buf), "Curl error occurred: %s", curl_multi_strerror(cres));
			KSI_pushError(client->ctx, res = KSI_UNKNOWN_ERROR, buf);
			goto cleanup;
		}

		select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);

		cres = curl_multi_perform(cm, &count);
		if (cres != CURLM_OK && cres != CURLM_CALL_MULTI_PERFORM) {
			KSI_snprintf(buf, sizeof(buf), "Curl error occurred: %s", curl_multi_strerror(cres));
			KSI_pushError(client->ctx, res = KSI_UNKNOWN_ERROR, buf);
			goto cleanup;
		}
	} while (count > 0 || cres == CURLM_CALL_MULTI_PERFORM);

	/* Remove the handles from the multi container. */
	for (i = 0; i < arr_len; i++) {
		CurlNetHandleCtx *pctx = arr[i]->implCtx;
		cres = curl_multi_remove_handle(cm, pctx->curl);
		if (cres != CURLM_OK) {
			KSI_snprintf(buf, sizeof(buf), "Curl error occurred: %s", curl_multi_strerror(cres));
			KSI_pushError(client->ctx, res = KSI_UNKNOWN_ERROR, buf);
			goto cleanup;
		}
		arr[i]->response = pctx->raw;
		pctx->raw = NULL;

		arr[i]->response_length = pctx->len;
		arr[i]->completed = true;

		res = updateStatus(arr[i]);
		if (res != KSI_OK) goto cleanup;
	}

	KSI_LOG_debug(client->ctx, "Finished cURL multi perform.");


	res = KSI_OK;

cleanup:

	if (cm != NULL) curl_multi_cleanup(cm);

	return res;

}
/*TODO: Not supported*/
int KSI_PKITruststore_addLookupDir(KSI_PKITruststore *trust, const char *path) {
	KSI_LOG_debug(trust->ctx, "CryptoAPI: Not implemented.");
	return KSI_OK;
}
int KSI_PKITruststore_verifyRawSignature(KSI_CTX *ctx, const unsigned char *data, unsigned data_len, const char *algoOid, const unsigned char *signature, unsigned signature_len, const KSI_PKICertificate *certificate) {
	int res = KSI_UNKNOWN_ERROR;
	ALG_ID algorithm=0;
	HCRYPTPROV hCryptProv = 0;
    PCCERT_CONTEXT subjectCert = NULL;
	HCRYPTKEY publicKey = 0;
	DWORD i=0;
	BYTE *little_endian_pkcs1= NULL;
	DWORD pkcs1_len = 0;
	HCRYPTHASH hash = 0;
	char buf[1024];

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || data == NULL || signature == NULL ||
		signature_len >= UINT_MAX || algoOid == NULL || certificate == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}


	algorithm = algIdFromOID(algoOid);
	if (algorithm == 0) {
		KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL);
		goto cleanup;
	}

	// Get the CSP context
	if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){
		KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get cryptographic provider.");
		goto cleanup;
	}

	// Get the public key from the issuer certificate
	subjectCert = certificate->x509;
	if (!CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING,&subjectCert->pCertInfo->SubjectPublicKeyInfo,&publicKey)){
		KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Failed to read PKI public key.");
		goto cleanup;
	}

	/*Convert big-endian to little-endian PKCS#1 signature*/
	pkcs1_len = signature_len;
	little_endian_pkcs1 = (BYTE*)KSI_malloc(pkcs1_len);

	if (little_endian_pkcs1 == NULL){
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	for (i=0; i<pkcs1_len; i++){
		little_endian_pkcs1[pkcs1_len-1-i] = signature[i];
	}

	// Create the hash object and hash input data.
	if (!CryptCreateHash(hCryptProv, algorithm, 0, 0, &hash)){
		KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to create hasher.");
		goto cleanup;
	}

	if (!CryptHashData(hash, (BYTE*)data, data_len,0)){
		KSI_LOG_debug(ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to hash data.");
		goto cleanup;
	}

	/*Verify the signature. The format MUST be PKCS#1*/
	if (!CryptVerifySignature(hash, (BYTE*)little_endian_pkcs1, pkcs1_len, publicKey, NULL, 0)){
		DWORD error = GetLastError();
		const char *errmsg = getMSError(GetLastError(), buf, sizeof(buf));
		KSI_LOG_debug(ctx, "%s", errmsg);

		if (error == NTE_BAD_SIGNATURE)
			KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, "Invalid PKI signature.");
		else if (error == NTE_NO_MEMORY)
			KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, "Unable to verify PKI signature. CSP out of memory.");
		else
			KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, errmsg);

		goto cleanup;
	}

	KSI_LOG_debug(certificate->ctx, "CryptoAPI: PKI signature verified successfully.");

	res = KSI_OK;

cleanup:

	KSI_free(little_endian_pkcs1);
	if (hCryptProv) CryptReleaseContext(hCryptProv, 0);
	if (hash) CryptDestroyHash(hash);

	return res;
}
Beispiel #29
0
static int verifyPublicationWithPubString(KSI_CTX *ctx, KSI_Signature *sig) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_VerificationStep step = KSI_VERIFY_PUBLICATION_WITH_PUBSTRING;
	KSI_VerificationResult *info = &sig->verificationResult;
	KSI_Integer *time1 = NULL;
	KSI_Integer *time2 = NULL;
	KSI_DataHash *hsh1 = NULL;
	KSI_DataHash *hsh2 = NULL;


	if (sig->publication == NULL || sig->verificationResult.useUserPublication == false) {
		res = KSI_OK;
		goto cleanup;
	}


	KSI_LOG_info(ctx, "Verifying publication with publication string");

	if (sig->verificationResult.userPublication == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	res = KSI_PublicationData_getTime(sig->verificationResult.userPublication, &time1);
	if (res != KSI_OK) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	res = KSI_PublicationData_getImprint(sig->verificationResult.userPublication, &hsh1);
	if (res != KSI_OK) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	res = KSI_PublicationData_getTime(sig->publication->publishedData, &time2);
	if (res != KSI_OK) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	res = KSI_PublicationData_getImprint(sig->publication->publishedData, &hsh2);
	if (res != KSI_OK) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}

	if (KSI_Integer_compare(time1, time2) != 0) {
		KSI_LOG_debug(ctx, "Publication time from publication record:", time2);
		KSI_LOG_debug(ctx, "Publication time from user publication  :", time1);
		res = KSI_VerificationResult_addFailure(info, step, "Publication not trusted.");
		goto cleanup;
	}

	if (KSI_DataHash_equals(hsh1, hsh2) != 1) {
		KSI_LOG_logDataHash(ctx, KSI_LOG_DEBUG, "Root hash from publication record:", hsh2);
		KSI_LOG_logDataHash(ctx, KSI_LOG_DEBUG, "Root hash from user publication:", hsh1);
		res = KSI_VerificationResult_addFailure(info, step, "Publication not trusted.");
		goto cleanup;
	}

	res = KSI_VerificationResult_addSuccess(info, step, "Publication trusted.");


cleanup:

	return res;
}
int KSI_PKITruststore_verifySignature(KSI_PKITruststore *pki, const unsigned char *data, size_t data_len, const KSI_PKISignature *signature) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	PCCERT_CONTEXT subjectCert = NULL;
	CRYPT_VERIFY_MESSAGE_PARA msgPara;
	DWORD dLen;
	char buf[1024];

	if (pki == NULL || data == NULL || signature == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = pki->ctx;
	KSI_ERR_clearErrors(ctx);

	KSI_LOG_debug(ctx, "CryptoAPI: Start PKI signature verification.");

	if (data_len > INT_MAX) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Data too long (more than MAX_INT).");
		goto cleanup;
	}

	/*Verify signature and signed data. Certificate is extracted from signature*/
	msgPara.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
    msgPara.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
    msgPara.hCryptProv = 0;
    msgPara.pfnGetSignerCertificate = NULL;
    msgPara.pvGetArg = NULL;
	dLen = (DWORD)data_len;

	if (!CryptVerifyDetachedMessageSignature(&msgPara, 0, signature->pkcs7.pbData, signature->pkcs7.cbData, 1, &data, &dLen, &subjectCert)){
		DWORD error = GetLastError();
		const char *errmsg = getMSError(error, buf, sizeof(buf));
		KSI_LOG_debug(pki->ctx, "%s", errmsg);

		if (error == E_INVALIDARG || error == CRYPT_E_UNEXPECTED_MSG_TYPE || error == CRYPT_E_NO_SIGNER)
			KSI_pushError(ctx, res = KSI_INVALID_FORMAT, errmsg);
		else if (error == NTE_BAD_ALGID)
			KSI_pushError(ctx, res = KSI_INVALID_PKI_SIGNATURE, errmsg);
		else if (error == NTE_BAD_SIGNATURE)
			KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Verification of PKI signature failed.");
		else
			KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, errmsg);

		goto cleanup;
	}

	res = KSI_PKITruststore_verifyCertificate(pki, subjectCert);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_PKITruststore_verifySignatureCertificate(pki, signature);
	if (res != KSI_OK){
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}


	KSI_LOG_debug(ctx, "CryptoAPI: PKI signature verified successfully.");

	res = KSI_OK;

cleanup:

	if (subjectCert) CertFreeCertificateContext(subjectCert);

	return res;
}