// VerifyCert.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 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 TRUE 1
#define FALSE 0
#endif
#define CRYPT_VERIFYCONTEXT     0xF0000000
#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;
//Сертификаты пользователя и УЦ соответственно. В формате Base64:
#define CERTIFICATE "MIIEMjCCA5qgAwIBAgIUHFtJDkujVVDhRbdQfB5yeYMi+7kwDgYKKoMOAwoBAQID\
					AgUAMIHxMQswCQYDVQQGEwJLWjGBwzCBwAYDVQQKDIG40JDQutGG0LjQvtC90LXR\
					gNC90L7QtSDQvtCx0YnQtdGB0YLQstC + ICLQndCw0YbQuNC + 0L3QsNC70YzQvdCw\
					0Y8g0L / Qu9Cw0YLRkdC20L3QsNGPINC60L7RgNC / 0L7RgNCw0YbQuNGPIiDQndCw\
					0YbQuNC + 0L3QsNC70YzQvdC + 0LPQviDQkdCw0L3QutCwINCg0LXRgdC / 0YPQsdC7\
					0LjQutC4INCa0LDQt9Cw0YXRgdGC0LDQvTEcMBoGA1UEAwwT0KPQpiAyINGD0YDQ\
					vtCy0L3RjzAeFw0yNDEyMTIwNzMzNDhaFw0yNTEyMTIwNzM4NDhaMCoxCzAJBgNV\
					BAYTAktaMQwwCgYDVQQKEwNTREsxDTALBgNVBAMTBFVTRVIwgawwIwYJKoMOAwoB\
					AQICMBYGCiqDDgMKAQECAgEGCCqDDgMKAQMDA4GEAASBgPmmzl6n + 1hyj3B2ecQ1\
					DmvF6OMm27gwaVE5g1t968Om2X / 8ZuAsM + hXywWgFaQk / 1gYs6QArT9plmhYio57\
					vG9 / 8sIhuHWUHDbZZL + 6dngT7SuMnM + x0Y0S8EreYNOQeSnHtQumLqJVESF7WLiZ\
					h + / LV2D2jGZF1YghoEZ19Umyo4IBfDCCAXgwCwYDVR0PBAQDAgbAMBMGA1UdJQQM\
					MAoGCCsGAQUFBwMEMB0GA1UdDgQWBBQcW0kOS6NVUOFFt1B8HnJ5gyL7uTCCATMG\
					A1UdIwSCASowggEmgBRCy5rn4q9zCLEbMC0dv93F12WUH6GB96SB9DCB8TELMAkG\
					A1UEBhMCS1oxgcMwgcAGA1UECgyBuNCQ0LrRhtC40L7QvdC10YDQvdC + 0LUg0L7Q\
					sdGJ0LXRgdGC0LLQviAi0J3QsNGG0LjQvtC90LDQu9GM0L3QsNGPINC / 0LvQsNGC\
					0ZHQttC90LDRjyDQutC + 0YDQv9C + 0YDQsNGG0LjRjyIg0J3QsNGG0LjQvtC90LDQ\
					u9GM0L3QvtCz0L4g0JHQsNC90LrQsCDQoNC10YHQv9GD0LHQu9C40LrQuCDQmtCw\
					0LfQsNGF0YHRgtCw0L0xHDAaBgNVBAMME9Cj0KYgMiDRg9GA0L7QstC90Y + CFELL\
					mufir3MIsRswLR2 / 3cXXZZQfMA4GCiqDDgMKAQECAwIFAAOBgQAmdybSJ7VFQ2NZ\
					anXSOpVu2DMh9Er8JIDCXJUn13 / rdwr4AxNgyGa25NgANY5LeWUlD61KtRGs126I\
					af0S2HPu8Fy06FnOjCrjD8SLKUnJJ4tShXksagCltNP + etn4vttPdThl8Ara8PDB\
					Ja + nKvEYk2JpI0hki9kCNXEx3DOQEA == "

#define CA          "MIIE/DCCBGSgAwIBAgIUQsua5+KvcwixGzAtHb/dxddllB8wDgYKKoMOAwoBAQID\
					AgUAMIHxMQswCQYDVQQGEwJLWjGBwzCBwAYDVQQKDIG40JDQutGG0LjQvtC90LXR\
					gNC90L7QtSDQvtCx0YnQtdGB0YLQstC + ICLQndCw0YbQuNC + 0L3QsNC70YzQvdCw\
					0Y8g0L / Qu9Cw0YLRkdC20L3QsNGPINC60L7RgNC / 0L7RgNCw0YbQuNGPIiDQndCw\
					0YbQuNC + 0L3QsNC70YzQvdC + 0LPQviDQkdCw0L3QutCwINCg0LXRgdC / 0YPQsdC7\
					0LjQutC4INCa0LDQt9Cw0YXRgdGC0LDQvTEcMBoGA1UEAwwT0KPQpiAyINGD0YDQ\
					vtCy0L3RjzAeFw0yMzA4MTUxMDExMTJaFw0zMzA4MTIxMDExMTJaMIHxMQswCQYD\
					VQQGEwJLWjGBwzCBwAYDVQQKDIG40JDQutGG0LjQvtC90LXRgNC90L7QtSDQvtCx\
					0YnQtdGB0YLQstC + ICLQndCw0YbQuNC + 0L3QsNC70YzQvdCw0Y8g0L / Qu9Cw0YLR\
					kdC20L3QsNGPINC60L7RgNC / 0L7RgNCw0YbQuNGPIiDQndCw0YbQuNC + 0L3QsNC7\
					0YzQvdC + 0LPQviDQkdCw0L3QutCwINCg0LXRgdC / 0YPQsdC70LjQutC4INCa0LDQ\
					t9Cw0YXRgdGC0LDQvTEcMBoGA1UEAwwT0KPQpiAyINGD0YDQvtCy0L3RjzCBrDAj\
					Bgkqgw4DCgEBAgIwFgYKKoMOAwoBAQICAQYIKoMOAwoBAwMDgYQABIGAO3B2qZpT\
					x6ocrFkM2Ee4h6nXZzZxiv0S1J8EbfkJi1192sAVI + dCIGtS1s5LN5tKIYwy + AXA\
					dMSsrTTBLoGQC0JFulhl5GZGz7b4Ww4Y3sOX7TdA5 / I9rplTIxs8CHgvMK3DcMkb\
					dKUwkh9AWaCpM8dJ5ecMXulomiibKcIkywKjggF + MIIBejASBgNVHRMBAf8ECDAG\
					AQH / AgEAMA4GA1UdDwEB / wQEAwIBBjAdBgNVHQ4EFgQUQsua5 + KvcwixGzAtHb / d\
					xddllB8wggEzBgNVHSMEggEqMIIBJoAUQsua5 + KvcwixGzAtHb / dxddllB + hgfek\
					gfQwgfExCzAJBgNVBAYTAktaMYHDMIHABgNVBAoMgbjQkNC60YbQuNC + 0L3QtdGA\
					0L3QvtC1INC + 0LHRidC10YHRgtCy0L4gItCd0LDRhtC40L7QvdCw0LvRjNC90LDR\
					jyDQv9C70LDRgtGR0LbQvdCw0Y8g0LrQvtGA0L / QvtGA0LDRhtC40Y8iINCd0LDR\
					htC40L7QvdCw0LvRjNC90L7Qs9C + INCR0LDQvdC60LAg0KDQtdGB0L / Rg9Cx0LvQ\
					uNC60Lgg0JrQsNC30LDRhdGB0YLQsNC9MRwwGgYDVQQDDBPQo9CmIDIg0YPRgNC +\
					0LLQvdGPghRCy5rn4q9zCLEbMC0dv93F12WUHzAOBgoqgw4DCgEBAgMCBQADgYEA\
					K + c1 / 7u + KM / +RpdlmO1gaUZjNPYwvDiUFyiE524cbNgcTt41pBXK408jMwiQUp9 +\
					q6JIxRv7Puw3fx4dsJpvOMnxfI / stXp / JwKe9JBiHl8VD6pGS8eEr88ZulVAhzxs\
					3xB4gcBHjFwXHYXPvLfICHNtFhs7jGslrWVZgRSWusQ = "
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 *basetobin)
(unsigned char *inBuf,
	long inSize,
	unsigned char *ouBuf,
	long *outSize);
typedef int(_cdecl *crptverifycertificatesignature)
(const hCERTSTORE hStore,
	const unsigned char *certBody,
	const unsigned long certSize,
	const unsigned char *CABody,
	const unsigned long caSize);

cspopencontext					CSPOpenContext;
crtopenstore					CrtOpenStore;
crtclosestore					CrtCloseStore;
cspclosecontext					CSPCloseContext;
errorstring						ErrorString;
basetobin						BaseToBin;
crptverifycertificatesignature	CrptVerifyCertificateSignature;

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;
	}
	BaseToBin = (basetobin)GetProcAddress(lib, "BaseToBin");
	if (!BaseToBin)
	{
		printf("error load function - %s", "BaseToBin");
		return 1;
	}
	CrptVerifyCertificateSignature = (crptverifycertificatesignature)GetProcAddress(lib, "CrptVerifyCertificateSignature");
	if (!CrptVerifyCertificateSignature)
	{
		printf("error load function - %s", "CrptVerifyCertificateSignature");
		return 1;
	}
	return 0;
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
	int ret = 0;
	HINSTANCE lib = NULL;
	int code = 0;
	hCERTSTORE hStore = 0;
	HCRYPTPROV hP = 0;
	unsigned char *userCert = NULL, *CACert = NULL;
	long userSize = 0, CASize = 0;

	try
	{
		lib = load_lib(strlib);
		if (get_func(lib))
		{
			printf("error load func.\n");
			exit(1);
		}
		//Открыть контекст CSP
		code = CSPOpenContext(&hP, NULL, 25, 0, CRYPT_VERIFYCONTEXT, NULL, 0, NULL, NULL, NULL);
		if (code)
		{
			printf("%s [CSPOpenContext: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		// Открыть конекст хранилища
		code = CrtOpenStore(0, hP, 0, false, NULL, &hStore);
		if (code)
		{
			printf("%s [CrtOpenStore: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		// Конвертация сертификата пользователя 
		userCert = (unsigned char*)calloc(sizeof(CERTIFICATE), sizeof(unsigned char));
		code = BaseToBin((unsigned char *)CERTIFICATE, sizeof(CERTIFICATE), userCert, &userSize);
		if (code)
		{
			printf("%s [BaseToBin: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		// Конвертация сертификата центра сертификации
		CACert = (unsigned char*)calloc(sizeof(CA), sizeof(unsigned char));
		code = BaseToBin((unsigned char *)CA, sizeof(CA), CACert, &CASize);
		if (code)
		{
			printf("%s [BaseToBin: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		// Проверка ЭЦП сертификата пользователя
		code = CrptVerifyCertificateSignature(hStore, userCert, userSize, CACert, CASize);
		if (code)
		{
			printf("%s [CrptVerifyCertificateSignature: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		printf("Signature is correct.\n");
	}
	catch (int er) { ret = er; }
	if (userCert) { free(userCert); userCert = NULL; }
	if (CACert) { free(CACert); CACert = NULL; }
	if (hStore) { CrtCloseStore(&hStore); hStore = 0; }
	if (hP) { CSPCloseContext(&hP); hP = 0; }
	if (lib) lib_free(lib);
	return ret;
}

