Esempio n. 1
0
int KSI_PKISignature_serialize(KSI_PKISignature *sig, unsigned char **raw, unsigned *raw_len) {
	int res = KSI_UNKNOWN_ERROR;
	unsigned char *tmp = NULL;

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


	tmp = KSI_malloc(sig->pkcs7.cbData);
	if (tmp == NULL) {
		KSI_pushError(sig->ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	memcpy(tmp, sig->pkcs7.pbData, sig->pkcs7.cbData);

	*raw = tmp;
	*raw_len = (unsigned)sig->pkcs7.cbData;

	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_free(tmp);

	return res;
}
Esempio n. 2
0
int KSI_PKICertificate_serialize(KSI_PKICertificate *cert, unsigned char **raw, size_t *raw_len) {
	int res = KSI_UNKNOWN_ERROR;
	unsigned char *tmp_serialized = NULL;
	DWORD len = 0;


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

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

	memcpy(tmp_serialized, cert->x509->pbCertEncoded, len);

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

	res = KSI_OK;

cleanup:

	KSI_free(tmp_serialized);

	return res;
}
Esempio n. 3
0
int KSI_Utf8String_new(KSI_CTX *ctx, const char *str, size_t len, KSI_Utf8String **o) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_Utf8String *tmp = NULL;

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

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

	tmp->ctx = ctx;
	tmp->value = NULL;
	tmp->ref = 1;

	/* Verify that it is a null-terminated string. */
	if (len == 0 || str[len - 1] != '\0') {
		KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "String value is not null-terminated.");
		goto cleanup;
	}

	/* Verify correctness of utf-8 */
	res = verifyUtf8((const unsigned char *)str, len);
	if (res != KSI_OK) goto cleanup;

	tmp->value = KSI_malloc(len);
	if (tmp->value == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}
	memcpy(tmp->value, str, len);

	tmp->len = len;

	*o = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_Utf8String_free(tmp);

	return res;
}
Esempio n. 4
0
int KSI_PKISignature_new(KSI_CTX *ctx, const void *raw, unsigned raw_len, KSI_PKISignature **signature) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_PKISignature *tmp = NULL;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || raw == NULL || raw_len == 0 || signature == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}


	tmp = KSI_new(KSI_PKISignature);
	if (tmp == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}
	tmp->ctx = ctx;
	tmp->pkcs7.pbData = NULL;
	tmp->pkcs7.cbData = 0;

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

	tmp->pkcs7.pbData = KSI_malloc(raw_len);
	if (tmp->pkcs7.pbData == NULL) {
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	tmp->pkcs7.cbData = raw_len;
	memcpy(tmp->pkcs7.pbData, raw, raw_len);

	*signature = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_PKISignature_free(tmp);

	return res;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
int KSI_OctetString_new(KSI_CTX *ctx, const unsigned char *data, size_t data_len, KSI_OctetString **o) {
	int res = KSI_UNKNOWN_ERROR;
	KSI_OctetString *tmp = NULL;

	KSI_ERR_clearErrors(ctx);
	if (ctx == NULL || (data == NULL && data_len != 0) || o == NULL) {
		KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL);
		goto cleanup;
	}

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

	tmp->ctx = ctx;
	tmp->data = NULL;
	tmp->data_len = data_len;
	tmp->ref = 1;

	if (data_len > 0) {
		tmp->data = KSI_malloc(data_len);
		if (tmp->data == NULL) {
			KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
			goto cleanup;
		}

		memcpy(tmp->data, data, data_len);
	}

	*o = tmp;
	tmp = NULL;
	res = KSI_OK;

cleanup:

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

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


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

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

		consumed = ftlv.hdr_len + ftlv.dat_len;

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

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

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

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

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

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

			buf = NULL;

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

	}

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

	res = KSI_OK;

cleanup:

	KSI_free(buf);

	return res;
}
Esempio n. 8
0
int KSI_PublicationsFile_serialize(KSI_CTX *ctx, KSI_PublicationsFile *pubFile, char **raw, size_t *raw_len) {
	int res;
	const unsigned char *buf = NULL;
	size_t buf_len = 0;
	KSI_TLV *tlv = NULL;
	unsigned char *tmp = NULL;
	size_t tmp_len = 0;
	size_t sig_len = 0;

	KSI_ERR_clearErrors(ctx);

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

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

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

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

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


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

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

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

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

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

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

	res = KSI_OK;

cleanup:

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

	KSI_ERR_clearErrors(ctx);

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

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

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

	tmp->signedDataLength = hdrLen;

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

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

	tmp->signedDataLength += gen.sig_offset;

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

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

	*pubFile = tmp;
	tmp = NULL;

	res = KSI_OK;

cleanup:


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

	return res;
}
Esempio n. 10
0
/*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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
int KSI_CTX_new(KSI_CTX **context) {
	int res = KSI_UNKNOWN_ERROR;

	KSI_CTX *ctx = NULL;
	KSI_NetworkClient *client = NULL;

	ctx = KSI_new(KSI_CTX);
	if (ctx == NULL) {
		res = KSI_OUT_OF_MEMORY;
		goto cleanup;
	}
	/* Init error stack */
	ctx->errors_size = KSI_ERR_STACK_LEN;
	ctx->errors = KSI_malloc(sizeof(KSI_ERR) * ctx->errors_size);
	if (ctx->errors == NULL) {
		res = KSI_OUT_OF_MEMORY;
		goto cleanup;
	}
	ctx->errors_count = 0;
	ctx->publicationsFile = NULL;
	ctx->pkiTruststore = NULL;
	ctx->netProvider = NULL;
	ctx->publicationCertEmail_DEPRECATED = NULL;
	ctx->loggerCB = NULL;
	ctx->requestHeaderCB = NULL;
	ctx->flags[KSI_CTX_FLAG_AGGR_PDU_VER] = KSI_AGGREGATION_PDU_VERSION;
	ctx->flags[KSI_CTX_FLAG_EXT_PDU_VER] = KSI_EXTENDING_PDU_VERSION;
	ctx->loggerCtx = NULL;
	ctx->certConstraints = NULL;
	ctx->freeCertConstraintsArray = freeCertConstraintsArray;
	ctx->lastFailedSignature = NULL;
	KSI_ERR_clearErrors(ctx);

	/* Create global cleanup list as the first thing. */
	res = KSI_List_new(NULL, &ctx->cleanupFnList);
	if (res != KSI_OK) goto cleanup;

	/* Create and set the logger. */
	res = KSI_CTX_setLoggerCallback(ctx, KSI_LOG_StreamLogger, stdout);
	if (res != KSI_OK) goto cleanup;

	res = KSI_CTX_setLogLevel(ctx, KSI_LOG_NONE);
	if (res != KSI_OK) goto cleanup;

	res = KSI_UriClient_new(ctx, &client);
	if (res != KSI_OK) goto cleanup;

	res = KSI_CTX_setNetworkProvider(ctx, client);
	if (res != KSI_OK) goto cleanup;
	ctx->isCustomNetProvider = 0;
	client = NULL;

	/* Initialize truststore. */
	res = KSI_PKITruststore_registerGlobals(ctx);
	if (res != KSI_OK) goto cleanup;

	/* Return the context. */
	*context = ctx;
	ctx = NULL;

	res = KSI_OK;

cleanup:

	KSI_NetworkClient_free(client);

	KSI_CTX_free(ctx);

	return res;
}
Esempio n. 13
0
static int winINet_ReadFromHandle(KSI_RequestHandle *reqHandle, unsigned char **buf, DWORD *len){
	int res = KSI_UNKNOWN_ERROR;
	HINTERNET handle;
	KSI_HttpClient *http = NULL;
	DWORD dwordLen;
	DWORD http_payload_len = 0;
	DWORD http_status;
	DWORD tmp_len = 0;
	unsigned char *tmp = NULL;
	KSI_CTX *ctx = NULL;

	if (reqHandle == NULL || buf == NULL || len == NULL) {
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = reqHandle->ctx;
	KSI_ERR_clearErrors(ctx);


	handle = ((wininetNetHandleCtx*)reqHandle->implCtx)->request_handle;
	http = (KSI_HttpClient*)reqHandle->client;

	/*Get HTTP status code*/
	dwordLen = sizeof(DWORD);
	if (!HttpQueryInfo(handle, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &http_status, &dwordLen, 0)) {
		WININET_ERROR_1(ctx, ERROR_INSUFFICIENT_BUFFER, KSI_INVALID_ARGUMENT, "WinINet: Insufficient buffer.")
		WININET_ERROR_m(ctx, ERROR_HTTP_HEADER_NOT_FOUND, KSI_NETWORK_ERROR, "WinINet: HTTP status code header not found.")
		WININET_ERROR_N(ctx, KSI_UNKNOWN_ERROR, "WinINet: Unable to get HTTP status code.")
	}

	http->httpStatus = http_status;

	/*Get the length of the payload*/
	dwordLen = sizeof(DWORD);
	if (!HttpQueryInfo(handle, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &http_payload_len, &dwordLen, 0)){
		WININET_ERROR_1(ctx, ERROR_INSUFFICIENT_BUFFER, KSI_INVALID_ARGUMENT, "WinINet: Insufficient buffer.")
		WININET_ERROR_m(ctx, ERROR_HTTP_HEADER_NOT_FOUND, KSI_NETWORK_ERROR, "WinINet: HTTP content length not found.")
		WININET_ERROR_N(ctx, KSI_UNKNOWN_ERROR, "WinINet: Unable to get HTTP content length.")
	}

	/*Get memory for the HTTP payload*/
	tmp_len = http_payload_len;
	tmp = (unsigned char*)KSI_malloc(tmp_len);
	if (tmp == NULL){
		KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}

	/*Read data*/
	if (!InternetReadFile(handle, tmp, tmp_len, &tmp_len)) {
		WININET_ERROR_1(ctx, ERROR_INSUFFICIENT_BUFFER, KSI_INVALID_ARGUMENT, "WinINet: Insufficient buffer.")
		WININET_ERROR_N(ctx, KSI_UNKNOWN_ERROR, "WinINet: HTTP Internet read error.")
	}

	if (tmp_len != http_payload_len){
		KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "WinINet: Unable to read all bytes.");
		goto cleanup;
	}

	*buf = tmp;
	*len = tmp_len;
	tmp = NULL;

	res = KSI_OK;

cleanup:

	KSI_free(tmp);

	return res;
}
Esempio n. 14
0
static int readResponse(KSI_RequestHandle *handle) {
	int res;
	TcpClientCtx *tcp = NULL;
	KSI_TcpClient *client = NULL;
	int sockfd = -1;
	struct sockaddr_in serv_addr;
	struct hostent *server = NULL;
	size_t count;
	unsigned char buffer[0xffff + 4];
	KSI_FTLV ftlv;
#ifdef _WIN32
	DWORD transferTimeout = 0;
#else
	struct timeval  transferTimeout;
#endif

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

	KSI_ERR_clearErrors(handle->ctx);

	tcp = handle->implCtx;
	client = handle->client->impl;

	sockfd = (int)socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0) {
		KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, "Unable to open socket.");
		goto cleanup;
	}
#ifdef _WIN32
	transferTimeout = client->transferTimeoutSeconds * 1000;
#else
	transferTimeout.tv_sec = client->transferTimeoutSeconds;
	transferTimeout.tv_usec = 0;
#endif

	/*Set socket options*/
	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void*)&transferTimeout, sizeof(transferTimeout));
	setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void*)&transferTimeout, sizeof(transferTimeout));

	server = gethostbyname(tcp->host);
	if (server == NULL) {
		KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, "Unable to open host.");
		goto cleanup;
	}

	memset((char *) &serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;

	memmove((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);

	serv_addr.sin_port = htons(tcp->port);

	if ((res = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0) {
		KSI_ERR_push(handle->ctx, KSI_NETWORK_ERROR, res, __FILE__, __LINE__, "Unable to connect.");
		res = KSI_NETWORK_ERROR;
		goto cleanup;
	}

	KSI_LOG_logBlob(handle->ctx, KSI_LOG_DEBUG, "Sending request", handle->request, handle->request_length);
	count = 0;
	while (count < handle->request_length) {
		int c;

#ifdef _WIN32
		if (handle->request_length > INT_MAX) {
			KSI_pushError(handle->ctx, res = KSI_BUFFER_OVERFLOW, "Unable to send more than MAX_INT bytes.");
			goto cleanup;
		}
		c = send(sockfd, (char *) handle->request, (int) handle->request_length, 0);
#else
		c = send(sockfd, (char *) handle->request, handle->request_length, 0);
#endif
		if (c < 0) {
			KSI_pushError(handle->ctx, res = KSI_NETWORK_ERROR, "Unable to write to socket.");
			goto cleanup;
		}
		count += c;
	}

	res = KSI_FTLV_socketRead(sockfd, buffer, sizeof(buffer), &count, &ftlv);
	if (res != KSI_OK || count == 0) {
		KSI_pushError(handle->ctx, res = KSI_INVALID_ARGUMENT, "Unable to read TLV from socket.");
		goto cleanup;
	}

	if(count > UINT_MAX){
		KSI_pushError(handle->ctx, res = KSI_BUFFER_OVERFLOW, "Too much data read from socket.");
		goto cleanup;
	}

	handle->response = KSI_malloc(count);
	if (handle->response == NULL) {
		KSI_pushError(handle->ctx, res = KSI_OUT_OF_MEMORY, NULL);
		goto cleanup;
	}
	memcpy(handle->response, buffer, count);
	handle->response_length = count;

	handle->completed = true;

	res = KSI_OK;

cleanup:

	if (sockfd >= 0) close(sockfd);

	return res;
}