// GetByCCNum.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <windows.h>
#define CRYPT_VERIFYCONTEXT     0xF0000000
#define strlib "..\\lib\\strlib.dll"
#else
#define GetProcAddress dlsym
#define FreeLibrary dlclose
#include <string>
#include  <unistd.h>
#include  <dlfcn.h>
#define strlib "../lib/libstr.so.1.0"
#define _cdecl
#define CRYPT_VERIFYCONTEXT 0xF0000000
#define TRUE 1
#define FALSE 0
#endif
#ifndef _WIN32
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef void *HINSTANCE;
typedef char CHAR;
#endif
typedef unsigned long hCERTSTORE;
typedef unsigned long hCERTCONTEXT;
typedef unsigned long hCERTCOLLECTION;
typedef unsigned long hCRYPTMSG;
typedef unsigned long HCRYPTPROV;
#define STORE_TYPE	"t=A;"
#define STORE_HOST	"127.0.0.1"
#define STORE_PORT	"62222"
#define HEXCCNUM	"42CB9AE7E2AF7308B11B302D1DBFDDC5D765941F"
#define DN			"C=KZ;O=LOCAL;CN=ROOT;"

typedef int(_cdecl *cspopencontext)
(HCRYPTPROV *phProv,
	CHAR *pszContainer,
	DWORD dwProvType,
	DWORD dwProvParam,
	DWORD dwFlags,
	BYTE * pbSignature,
	DWORD dwSigLen,
	BYTE * pbContainer,
	DWORD * dwContLen,
	HINSTANCE *phLib);
typedef int(_cdecl *crtopenstore)
(DWORD StoreProvider,
	HCRYPTPROV hProv,
	unsigned long dwFlags,
	bool  bFlag,
	const void *pvParam,
	hCERTSTORE *phStore);
typedef int(_cdecl *crtclosestore)                     (hCERTSTORE *phStore);
typedef int(_cdecl *cspclosecontext)                   (HCRYPTPROV *phProv);
typedef char* (_cdecl *errorstring)                     (const int err);
typedef int(_cdecl *crtsetstorepropertyext)
(const hCERTSTORE hStore,
	const unsigned long Flags,
	const char *DName,
	const char *host,
	const char *port,
	const int timeOut,
	const char *name,
	const char *pass);
typedef int(_cdecl *getcacertificatenum)
(hCERTSTORE hStore,
	const char *DName,
	const unsigned char *serNum,
	const long len,
	unsigned char *certBody,
	unsigned long *bodySize,
	char* fname);

cspopencontext				CSPOpenContext;
crtopenstore				CrtOpenStore;
crtclosestore				CrtCloseStore;
cspclosecontext				CSPCloseContext;
errorstring					ErrorString;
crtsetstorepropertyext		CrtSetStorePropertyExt;
getcacertificatenum			GetCACertificateNum;

HINSTANCE load_lib(char *lib)
{
#ifdef _WIN32
	return LoadLibraryA(lib);
#else
	return dlopen(lib, RTLD_LAZY);
#endif
}
void lib_free(HINSTANCE Instance)
{
#ifdef _WIN32
	FreeLibrary(Instance);
#else
	dlclose(Instance);
#endif
}
int get_func(HINSTANCE lib)
{
	CSPOpenContext = (cspopencontext)GetProcAddress(lib, "CSPOpenContext");
	if (!CSPOpenContext)
	{
		printf("error load function - %s", "CSPOpenContext");
		return 1;
	}
	CrtOpenStore = (crtopenstore)GetProcAddress(lib, "CrtOpenStore");
	if (!CrtOpenStore)
	{
		printf("error load function - %s", "CrtOpenStore");
		return 1;
	}
	CSPCloseContext = (cspclosecontext)GetProcAddress(lib, "CSPCloseContext");
	if (!CSPCloseContext)
	{
		printf("error load function - %s", "CSPCloseContext");
		return 1;
	}
	CrtCloseStore = (crtclosestore)GetProcAddress(lib, "CrtCloseStore");
	if (!CrtCloseStore)
	{
		printf("error load function - %s", "CrtCloseStore");
		return 1;
	}
	ErrorString = (errorstring)GetProcAddress(lib, "ErrorString");
	if (!ErrorString)
	{
		printf("error load function - %s", "ErrorString");
		return 1;
	}
	CrtSetStorePropertyExt = (crtsetstorepropertyext)GetProcAddress(lib, "CrtSetStorePropertyExt");
	if (!CrtSetStorePropertyExt)
	{
		printf("error load function - %s", "CrtSetStorePropertyExt");
		return 1;
	}
	GetCACertificateNum = (getcacertificatenum)GetProcAddress(lib, "GetCACertificateNum");
	if (!GetCACertificateNum)
	{
		printf("error load function - %s", "GetCACertificateNum");
		return 1;
	}
	return 0;
}
//---------------------------------------------------------------------------
void h2b(unsigned char *inbuf, long  insize, unsigned char *oubuf);
//---------------------------------------------------------------------------
int main(void)
{
	HINSTANCE lib = NULL;
	int ret = 0;
	int code = 0;
	int i, count;
	hCERTSTORE hStore = 0;
	HCRYPTPROV hP = 0;
	unsigned char BinCCNum[32];
	unsigned char *certBlob = NULL;
	unsigned long certSize;
	try
	{
		lib = load_lib(strlib);
		if (get_func(lib))
		{
			printf("error load func.\n");
			exit(1);
		}
		//получить контекст криптопровайдера
		code = CSPOpenContext(&hP, NULL, 25, 0, CRYPT_VERIFYCONTEXT, NULL, 0, NULL, 0, NULL);
		if (code)
		{
			printf("%s [CSPOpenContext: error = %i\n]", ErrorString(code), code);
			throw code;
		}
		//открыть хранилище сертификатов
		code = CrtOpenStore(0, hP, 0, false, NULL, &hStore);
		if (code)
		{
			printf("%s [CrtOpenStore: error = %i\n]", ErrorString(code), code);
			throw code;
		}
		// настроить хранилище сертификатов
		// вызов функции обязателен перед вызовом GetCACertificateNum
		code = CrtSetStorePropertyExt(hStore, 0, STORE_TYPE, STORE_HOST, STORE_PORT, 300, 0, 0);
		if (code)
		{
			printf("%s [CrtSetStorePropertyExt: error = %i\n]", ErrorString(code), code);
			throw code;
		}
		//получение сертификата ЦС по серийному номеру
		h2b((unsigned char*)HEXCCNUM, sizeof(HEXCCNUM), BinCCNum);
		code = GetCACertificateNum(hStore, DN, BinCCNum, sizeof(HEXCCNUM)/2, NULL, &certSize,NULL);
		if (code)
		{
			printf("%s [GetCACertificateNum: error = %i\n]", ErrorString(code), code);
			throw code;
		}
		printf("GetCACertificateNum - OK\nCertificate size = %d\n", certSize);
		certBlob = (unsigned char*)calloc(certSize, sizeof(unsigned char));
		memset(certBlob, 0, certSize);
		code = GetCACertificateNum(hStore, DN, BinCCNum, sizeof(HEXCCNUM)/2, certBlob, &certSize, NULL);
		if (code)
		{
			printf("%s [GetCACertificateNum: error = %i\n]", ErrorString(code), code);
			throw code;
		}
		printf("GetCACertificateNum - OK\nGet Certificate Body - OK\n");
	}
	catch (int er) { ret = er; }
	if (certBlob) free(certBlob);
	//закрыть хранилище сертификатов
	if (hStore)
	{
		CrtCloseStore(&hStore);
		hStore = (hCERTSTORE)NULL;
	}
	//удалить контекст криптопровайдера
	if (hP)
	{
		CSPCloseContext(&hP);
		hP = (HCRYPTPROV)NULL;
	}
	if (lib) lib_free(lib);
	return ret;
}
//---------------------------------------------------------------------------
void h2b(unsigned char *inbuf, long  insize, unsigned char *oubuf)
{
	char *HAlf = (char*)"0123456789ABCDEF";
	long l;
	for (l = 0; l<insize / 2; l++) oubuf[l] = (unsigned char)
		((((unsigned char)(strchr(HAlf, inbuf[2 * l]) - HAlf) << 4)) |
			((unsigned char)(strchr(HAlf, inbuf[(2 * l) + 1]) - HAlf)));
}
//---------------------------------------------------------------------------


