예제 #1
0
char* KSI_OctetString_toString(const KSI_OctetString *id, char separator, char *buf, size_t buf_len) {
	int res = 0;
	const unsigned char *raw = NULL;
	size_t raw_len;
	size_t written = 0;
	size_t i = 0;


	if (id == NULL || buf == NULL || buf_len == 0) {
		return NULL;
	}

	res = KSI_OctetString_extract(id, &raw, &raw_len);
	if(res != KSI_OK || raw == NULL) return NULL;

	for (i = 0; i < raw_len; i++) {
		if(buf_len - written <= 0) return NULL;
		if(separator == '\0' || i == raw_len - 1)
			written += KSI_snprintf(buf + written, buf_len - written, "%02x", raw[i]);
		else
			written += KSI_snprintf(buf + written, buf_len - written, "%02x%c", raw[i], separator);
		if (written == 0) return NULL;
	}

	return buf;
}
예제 #2
0
static void addInput(CuTest *tc, KSI_BlockSigner *bs, int genMeta) {
	int res = KSI_UNKNOWN_ERROR;
	size_t i;
	KSI_DataHash *hsh = NULL;
	KSI_MetaData *md = NULL;

	for (i = 0; input_data[i] != NULL; i++) {
		res = KSI_DataHash_create(ctx, input_data[i], strlen(input_data[i]), KSI_HASHALG_SHA2_256, &hsh);
		CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL);

		if (genMeta) {
			char clientId[100];
			KSI_snprintf(clientId, sizeof(clientId), "Client-%d", i);

			res = createMetaData(clientId, &md);
			CuAssert(tc, "Unable to create metadata.", res == KSI_OK && md != NULL);

			res = KSI_BlockSigner_addLeaf(bs, hsh, 0, md, NULL);
			CuAssert(tc, "Unable to add leaf with meta data.", res == KSI_OK);

			KSI_MetaData_free(md);
			md = NULL;
		} else {
			res = KSI_BlockSigner_add(bs, hsh);
			CuAssert(tc, "Unable to add data hash to the block signer.", res == KSI_OK);
		}
		KSI_DataHash_free(hsh);
		hsh = NULL;
	}
}
예제 #3
0
static void testMaskingInput(CuTest *tc) {
	static const unsigned char diceRolls[] = {0xd5, 0x58, 0xaf, 0xfa, 0x80, 0x67, 0xf4, 0x2c, 0xd9, 0x48, 0x36, 0x21, 0xd1, 0xab,
			0xae, 0x23, 0xed, 0xd6, 0xca, 0x04, 0x72, 0x7e, 0xcf, 0xc7, 0xdb, 0xc7, 0x6b, 0xde, 0x34, 0x77, 0x1e, 0x53};
	int res;
	KSI_BlockSigner *bs = NULL;
	KSI_OctetString *iv = NULL;
	KSI_DataHash *zero = NULL;
	size_t i;

	struct {
		KSI_CTX *ctx;
		KSI_HashAlgorithm algo_id;
		KSI_DataHash *prevHash;
		KSI_OctetString *iv;
		KSI_BlockSigner **bs;
		int expectedRes;
	} tests[] = {
			{NULL, KSI_HASHALG_SHA3_512, NULL, NULL, NULL, KSI_INVALID_ARGUMENT},
			{NULL, KSI_HASHALG_SHA3_512, NULL, NULL, &bs, KSI_INVALID_ARGUMENT},
			{NULL, KSI_HASHALG_SHA3_512, NULL, iv, &bs, KSI_INVALID_ARGUMENT},
			{NULL, KSI_HASHALG_SHA3_512, zero, NULL, &bs, KSI_INVALID_ARGUMENT},
			{ctx, KSI_HASHALG_SHA3_512, NULL, NULL, &bs, KSI_UNAVAILABLE_HASH_ALGORITHM},
			{NULL, KSI_HASHALG_SHA2_512, NULL, NULL, NULL, KSI_INVALID_ARGUMENT},
			{NULL, KSI_HASHALG_SHA2_512, NULL, NULL, &bs, KSI_INVALID_ARGUMENT},
			{NULL, KSI_HASHALG_SHA2_512, NULL, iv, &bs, KSI_INVALID_ARGUMENT},
			{NULL, KSI_HASHALG_SHA2_512, zero, NULL, &bs, KSI_INVALID_ARGUMENT},
			{ctx, KSI_HASHALG_SHA2_512, zero, NULL, &bs, KSI_OK},
			{NULL, -1, NULL, NULL, NULL, -1}
	};

	/* Create zero hash. */
	res = KSI_DataHash_createZero(ctx, KSI_HASHALG_SHA2_512, &zero);
	CuAssert(tc, "Unable to create zero hash.", res == KSI_OK && zero != NULL);

	/* Create random initial vector. */
	res = KSI_OctetString_new(ctx, diceRolls, sizeof(diceRolls), &iv);
	CuAssert(tc, "Unable to create initial vector.", res == KSI_OK && iv != NULL);

	res = KSI_BlockSigner_new(ctx, KSI_HASHALG_SHA1, zero, iv, &bs);
	CuAssert(tc, "Unable to create block signer instance with masking.", res == KSI_OK && bs != NULL);

	for (i = 0; tests[i].expectedRes != -1; i++) {
		res = KSI_BlockSigner_new(tests[i].ctx, tests[i].algo_id, tests[i].prevHash, tests[i].iv, tests[i].bs);
		KSI_BlockSigner_free(bs);
		bs = NULL;
		if (res != tests[i].expectedRes) {
			char buf[1000];
			KSI_snprintf(buf, sizeof(buf), "Unexpected result @%i (expected = '%s', but was '%s').", i, KSI_getErrorString(tests[i].expectedRes), KSI_getErrorString(res));
			CuFail(tc, buf);
		}
	}

	KSI_OctetString_free(iv);
	KSI_DataHash_free(zero);
}
예제 #4
0
KSI_END_TLV_TEMPLATE

static char *track_str(struct tlv_track_s *tr, size_t tr_len, size_t tr_size, char *buf, size_t buf_len) {
	size_t len = 0;
	size_t i;

	/* Make sure, the return value is null-terminated. */
	buf[0] = '\0';

	/* Generate the printable result string, by separating values with "->" */
	for (i = 0; i < tr_len && i < tr_size; i++) {
		if (i != 0) len += KSI_snprintf(buf + len, buf_len - len, "->");
		len += KSI_snprintf(buf + len, buf_len - len, "[0x%02x]%s", tr[i].tag, tr[i].desc != NULL ? tr[i].desc : "");
	}

	/* Just in case the buffer was too short, but in real life, this should not happen with correct KSI objects. */
	if (tr_len >= tr_size) {
		KSI_snprintf(buf + len, buf_len - len, "->...");
	}

	return buf;
}
예제 #5
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;
}
예제 #6
0
char *KSI_PublicationRecord_toString(KSI_PublicationRecord *t, char *buffer, size_t buffer_len) {
	int res = KSI_UNKNOWN_ERROR;
	char *ret = NULL;
	char tmp[256];
	size_t len = 0;
	size_t i;

	len += KSI_snprintf(buffer + len, buffer_len - len, "%s", KSI_PublicationData_toString(t->publishedData, tmp, sizeof(tmp)));

	for (i = 0; i < KSI_Utf8StringList_length(t->publicationRef); i++) {
		KSI_Utf8String *ref = NULL;

		res = KSI_Utf8StringList_elementAt(t->publicationRef, i, &ref);
		if (res != KSI_OK) goto cleanup;

		len += KSI_snprintf(buffer + len, buffer_len - len, "\nRef: %s", KSI_Utf8String_cstr(ref));
	}

	ret = buffer;

cleanup:

	return ret;
}
예제 #7
0
char* KSI_PKICertificate_toString(KSI_PKICertificate *cert, char *buf, unsigned buf_len){
	char *ret = NULL;
	char strSubjectname[256];
	char strIssuerName[256];

	if (cert == NULL  || buf == NULL) goto cleanup;

	CertGetNameString(cert->x509, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, strSubjectname, sizeof(strSubjectname));
	CertGetNameString(cert->x509, CERT_NAME_SIMPLE_DISPLAY_TYPE , CERT_NAME_ISSUER_FLAG, 0,strIssuerName, sizeof(strIssuerName));
	KSI_snprintf(buf, buf_len, "Subject: '%s',  Issuer '%s'.", strSubjectname, strIssuerName);

	ret = buf;

cleanup:

return ret;
}
예제 #8
0
파일: hash.c 프로젝트: GuardTime/libksi
char *KSI_DataHash_toString(const KSI_DataHash *hsh, char *buf, size_t buf_len) {
	char *ret = NULL;
	size_t i;
	size_t len = 0;

	if (hsh == NULL || buf == NULL) goto cleanup;

	for (i = 0; i < hsh->imprint_length && len < buf_len; i++) {
		len += KSI_snprintf(buf + len, buf_len - len, "%02x", hsh->imprint[i]);
	}

	ret = buf;

cleanup:

	return ret;
}
예제 #9
0
static void testObjectSerialization(CuTest *tc, const char *sample,
									int (*parse)(KSI_CTX *, unsigned char *, size_t, void **),
									int (*serialize)(void *, unsigned char **, size_t *),
									void (*objFree)(void *)) {
	int res;
	void *pdu = NULL;
	unsigned char in[0xffff + 4];
	size_t in_len;
	unsigned char *out = NULL;
	size_t out_len;
	FILE *f = NULL;
	char errm[1024];

	f = fopen(sample, "rb");
	KSI_snprintf(errm, sizeof(errm), "Unable to open pdu file: '%s'.", sample);
	CuAssert(tc, errm, f != NULL);

	in_len = (unsigned)fread(in, 1, sizeof(in), f);
	fclose(f);
	KSI_snprintf(errm, sizeof(errm), "Unable to read pdu file: '%s'.", sample);
	CuAssert(tc, errm, in_len > 0);

	res = parse(ctx, in, in_len, &pdu);
	KSI_snprintf(errm, sizeof(errm), "Unable to parse pdu: '%s'.", sample);
	CuAssert(tc, errm, res == KSI_OK && pdu != NULL);

	res = serialize(pdu, &out, &out_len);
	KSI_snprintf(errm, sizeof(errm), "Unable to serialize pdu: '%s'.", sample);
	CuAssert(tc, errm, res == KSI_OK && out != NULL && out_len > 0);

	KSI_snprintf(errm, sizeof(errm), "Serialized pdu length mismatch: '%s'.", sample);
	CuAssert(tc, errm, res == KSI_OK && out_len == in_len);

	KSI_snprintf(errm, sizeof(errm), "Serialised pdu content mismatch: '%s'.", sample);
	CuAssert(tc, errm, !KSITest_memcmp(in, out, in_len));

	KSI_free(out);
	objFree(pdu);
}
예제 #10
0
int KSI_DataHasher_open(KSI_CTX *ctx, KSI_HashAlgorithm algo_id, KSI_DataHasher **hasher) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_DataHasher *tmp_hasher = NULL;
	CRYPTO_HASH_CTX *tmp_cryptoCTX = NULL;
	HCRYPTPROV tmp_CSP = 0;

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

	/*Test if hash algorithm is valid*/
	if (!KSI_isHashAlgorithmSupported(algo_id)) {
		KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL);
		goto cleanup;
	}

	/*Create new abstract data hasher object*/
	tmp_hasher = KSI_new(KSI_DataHasher);
	if (tmp_hasher == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	tmp_hasher->hashContext = NULL;
	tmp_hasher->ctx = ctx;
	tmp_hasher->algorithm = algo_id;
	tmp_hasher->closeExisting = closeExisting;

	/*Create new helper context for crypto api*/
	res = CRYPTO_HASH_CTX_new(&tmp_cryptoCTX);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	/*Create new crypto service provider (CSP)*/
	if (!CryptAcquireContext(&tmp_CSP, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){
		char errm[1024];
		KSI_snprintf(errm, sizeof(errm), "Wincrypt Error (%d)", GetLastError());
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, errm);
		goto cleanup;
		}

	/*Set CSP in helper struct*/
	tmp_cryptoCTX->pt_CSP = tmp_CSP;
	/*Set helper struct in abstract struct*/
	tmp_hasher->hashContext = tmp_cryptoCTX;

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

	*hasher = tmp_hasher;
	tmp_hasher = NULL;
	tmp_cryptoCTX = NULL;
	tmp_CSP = 0;

	res = KSI_OK;

cleanup:

	KSI_DataHasher_free(tmp_hasher);
	if (tmp_CSP) CryptReleaseContext(tmp_CSP, 0);
	CRYPTO_HASH_CTX_free(tmp_cryptoCTX);

	return res;
}
예제 #11
0
static void testMedaData(CuTest *tc) {
#define TEST_AGGR_RESPONSE_FILE  "resource/tlv/test_meta_data_response.tlv"
	int res = KSI_UNKNOWN_ERROR;
	KSI_BlockSigner *bs = NULL;
	KSI_MetaData *md = NULL;
	char data[] = "LAPTOP";
	char *clientId[] = { "Alice", "Bob", "Claire", NULL };
	size_t i;
	KSI_DataHash *hsh = NULL;
	KSI_BlockSignerHandle *hndl[] = {NULL, NULL, NULL};
	KSI_Signature *sig = NULL;
	char *id = NULL;

	res = KSI_DataHash_create(ctx, data, strlen(data), KSI_HASHALG_SHA2_256, &hsh);
	CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL);

	res = KSI_BlockSigner_new(ctx, KSI_HASHALG_SHA2_256, NULL, NULL, &bs);
	CuAssert(tc, "Unable to create block signer instance.", res == KSI_OK && bs != NULL);

	for (i = 0; clientId[i] != NULL; i++) {
		res = createMetaData(clientId[i], &md);
		CuAssert(tc, "Unable to create meta-data.", res == KSI_OK && md != NULL);

		res = KSI_BlockSigner_addLeaf(bs, hsh, 0, md, &hndl[i]);
		CuAssert(tc, "Unable to add leaf to the block signer.", res == KSI_OK && hndl[i] != NULL);

		KSI_MetaData_free(md);
		md = NULL;

	}

	res = KSI_CTX_setAggregator(ctx, getFullResourcePathUri(TEST_AGGR_RESPONSE_FILE), TEST_USER, TEST_PASS);
	CuAssert(tc, "Unable to set aggregator file URI.", res == KSI_OK);

	res = KSI_BlockSigner_close(bs, NULL);
	CuAssert(tc, "Unable to close the blocksigner.", res == KSI_OK);

	/* Loop over all the handles, and extract the signature. */
	for (i = 0; clientId[i] != NULL; i++) {
		char expId[0xff];

		/* Extract the signature. */
		res = KSI_BlockSignerHandle_getSignature(hndl[i], &sig);
		CuAssert(tc, "Unable to extract signature.", res == KSI_OK && sig != NULL);

		/* Verify the signature. */
		res = KSI_verifySignature(ctx, sig);
		CuAssert(tc, "Unable to verify the extracted signature.", res == KSI_OK);

		/* Extract the id attribution. */
		res = KSI_Signature_getSignerIdentity(sig, &id);
		CuAssert(tc, "Unable to extract the signer identity.", res == KSI_OK && id != NULL);

		/* Create the expected id value. */
		KSI_snprintf(expId, sizeof(expId), "%s :: %s", "GT :: GT :: release test :: anon http", clientId[i]);
		CuAssert(tc, "Client id not what expected.", !strcmp(id, expId));

		/* Cleanup. */
		KSI_Signature_free(sig);
		sig = NULL;

		KSI_free(id);
		id = NULL;

		KSI_BlockSignerHandle_free(hndl[i]);
	}

	KSI_DataHash_free(hsh);
	KSI_MetaData_free(md);
	KSI_BlockSigner_free(bs);
#undef TEST_AGGR_RESPONSE_FILE
}
예제 #12
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;

}
예제 #13
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;
}
예제 #14
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;
}
예제 #15
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;
}
예제 #16
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;
}
예제 #17
0
int main(int argc, char **argv) {
	KSI_CTX *ksi = NULL;
	int res = KSI_UNKNOWN_ERROR;

	KSI_DataHash *hsh = NULL;
	KSI_RequestHandle *handle[REQUESTS];
	KSI_NetworkClient *http = NULL;

	FILE *logFile = NULL;

	size_t i;

	KSI_DataHasher *hsr = NULL;

	const KSI_CertConstraint pubFileCertConstr[] = {
			{ KSI_CERT_EMAIL, "*****@*****.**"},
			{ NULL, NULL }
	};

	struct {
		size_t ok;
		size_t nok;
	} stat;

	stat.ok = 0;
	stat.nok = 0;




	/* Create new KSI context for this thread. */
	res = KSI_CTX_new(&ksi);
	if (res != KSI_OK) {
		fprintf(stderr, "Unable to create context.\n");
		goto cleanup;
	}

	res = KSI_CTX_setDefaultPubFileCertConstraints(ksi, pubFileCertConstr);
	if (res != KSI_OK) {
		fprintf(stderr, "Unable to configure publications file cert constraints.\n");
		goto cleanup;
	}

	/* Configure the logger. */
	res = OpenLogging(ksi, "multi_curl.log", &logFile);
	if (res != KSI_OK) goto cleanup;


	KSI_LOG_info(ksi, "Using KSI version: '%s'", KSI_getVersion());

	/* Check publications file url. */
	res = KSI_CTX_setPublicationUrl(ksi, "http://verify.guardtime.com/ksi-publications.bin");
	if (res != KSI_OK) {
		fprintf(stderr, "Unable to set publications file url.\n");
		goto cleanup;
	}

	res = KSI_HttpClient_new(ksi, &http);
	if (res != KSI_OK) {
		fprintf(stderr, "Unable to create http client.\n");
		goto cleanup;
	}

	res = KSI_HttpClient_setAggregator(http, "http://ksigw.test.guardtime.com:3332", "anon", "anon");
	if (res != KSI_OK) {
		fprintf(stderr, "Unable to set aggregator url.\n");
		goto cleanup;
	}

	KSI_HttpClient_setReadTimeoutSeconds(http, 10);
	KSI_HttpClient_setConnectTimeoutSeconds(http, 10);

	for (i = 0; i < REQUESTS; i++) {
		char buf[100];
		size_t len;
		KSI_AggregationReq *req = NULL;

		len = KSI_snprintf(buf, sizeof(buf), "Hello %d", i);
		res = KSI_DataHash_create(ksi, buf, len, KSI_getHashAlgorithmByName("default"), &hsh);
		if (res != KSI_OK) {
			fprintf(stderr, "Unable to create hash.");
			goto cleanup;
		}

		res = KSI_AggregationReq_new(ksi, &req);
		if (res != KSI_OK) {
			fprintf(stderr, "Unable to create request.");
			goto cleanup;
		}

		res = KSI_AggregationReq_setRequestHash(req, hsh);
		if (res != KSI_OK) {
			fprintf(stderr, "Unable to set request hash.");
			goto cleanup;
		}

		res = KSI_NetworkClient_sendSignRequest(http, req, &handle[i]);
		if (res != KSI_OK) {
			fprintf(stderr, "Unable to send aggregation request.");
			goto cleanup;
		}

		KSI_AggregationReq_free(req);
	}

	res = KSI_NetworkClient_performAll(http, handle, REQUESTS);
	if (res != KSI_OK) {
		fprintf(stderr, "Unable to perform requests.");
		goto cleanup;
	}

	for (i = 0; i < REQUESTS; i++) {
		KSI_AggregationResp *resp = NULL;
		res = KSI_RequestHandle_getAggregationResponse(handle[i], &resp);
		if (res != KSI_OK) {
			const KSI_RequestHandleStatus *st = NULL;
			res = KSI_RequestHandle_getResponseStatus(handle[i], &st);
			if (res == KSI_OK) {
				printf("Status code = %ld: %s\n", st->code, st->errm);
			}

			KSI_ERR_statusDump(ksi, stdout);
			stat.nok++;
		} else {
			stat.ok ++;
		}

		KSI_AggregationResp_free(resp);
	}

	printf("Requests:\n"
			"  Successful: %llu\n"
			"      Failed: %llu\n"
			"       TOTAL: %llu\n", (unsigned long long)stat.ok, (unsigned long long)stat.nok, (unsigned long long)(stat.ok + stat.nok));

	res = KSI_OK;

cleanup:

	if (logFile != NULL) fclose(logFile);

	if (res != KSI_OK && ksi != NULL) {
		KSI_ERR_statusDump(ksi, stderr);
	}

	KSI_DataHash_free(hsh);
	KSI_DataHasher_free(hsr);

	KSI_CTX_free(ksi);

	return res;

}
예제 #18
0
static int verifyOnline(KSI_CTX *ctx, KSI_Signature *sig) {
	int res = KSI_UNKNOWN_ERROR;

	KSI_ExtendReq *req = NULL;
	KSI_Integer *start = NULL;
	KSI_Integer *end = NULL;
	KSI_RequestHandle *handle = NULL;
	KSI_DataHash *extHash = NULL;
	KSI_DataHash *calHash = NULL;
	KSI_ExtendResp *resp = NULL;
	KSI_Integer *status = NULL;
	KSI_CalendarHashChain *calChain = NULL;
	KSI_DataHash *rootHash = NULL;
	KSI_DataHash *pubHash = NULL;
	KSI_VerificationStep step = KSI_VERIFY_CALCHAIN_ONLINE;
	KSI_VerificationResult *info = &sig->verificationResult;

	KSI_LOG_info(sig->ctx, "Verifying signature online.");

	/* Extract start time */
	res = KSI_CalendarHashChain_getAggregationTime(sig->calendarChain, &start);
	if (res != KSI_OK) goto cleanup;

	/* Clone the start time object */
	KSI_Integer_ref(start);

	if (sig->verificationResult.useUserPublication) {
		/* Extract end time. */
		res = KSI_PublicationData_getTime(sig->verificationResult.userPublication, &end);
		if (res != KSI_OK) goto cleanup;
	}
	res = KSI_createExtendRequest(sig->ctx, start, end, &req);
	if (res != KSI_OK) goto cleanup;

	res = KSI_sendExtendRequest(ctx, req, &handle);
	if (res != KSI_OK) goto cleanup;

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

	res = KSI_RequestHandle_getExtendResponse(handle, &resp);
	if (res != KSI_OK) goto cleanup;

	/* Verify the correctness of the response. */
	res = KSI_ExtendResp_verifyWithRequest(resp, req);
	if (res != KSI_OK) {
		KSI_pushError(ctx, res, NULL);
		goto cleanup;
	}

	res = KSI_ExtendResp_getStatus(resp, &status);
	if (res != KSI_OK) goto cleanup;

	/* Verify status. */
	if (status != NULL && !KSI_Integer_equalsUInt(status, 0)) {
		KSI_Utf8String *respErr = NULL;
		char errm[1024];

		res = KSI_ExtendResp_getErrorMsg(resp, &respErr);
		if (res != KSI_OK) goto cleanup;

		KSI_snprintf(errm, sizeof(errm), "Extend failure from server: '%s'", KSI_Utf8String_cstr(respErr));

		res = KSI_VerificationResult_addFailure(info, step, errm);
		goto cleanup;
	}

	res = KSI_ExtendResp_getCalendarHashChain(resp, &calChain);
	if (res != KSI_OK) goto cleanup;

	res = KSI_CalendarHashChain_getInputHash(calChain, &extHash);
	if (res != KSI_OK) goto cleanup;

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

	if (!KSI_DataHash_equals(extHash, calHash)) {
		res = KSI_VerificationResult_addFailure(info, step, "Extender returned different input hash for calendar hash chain.");
		goto cleanup;
	}

	if (sig->verificationResult.useUserPublication) {
		res = KSI_CalendarHashChain_aggregate(calChain, &rootHash);
		if (res != KSI_OK) goto cleanup;

		if (!KSI_DataHash_equals(rootHash, pubHash)) {
			res = KSI_VerificationResult_addFailure(info, step, "External publication imprint mismatch.");
			goto cleanup;
		}
	}

	res = KSI_VerificationResult_addSuccess(info, step, "Verified online.");

cleanup:

	KSI_Integer_free(start);
	KSI_ExtendReq_free(req);
	KSI_RequestHandle_free(handle);
	KSI_ExtendResp_free(resp);

	return res;
}