// VerifyCrlSign.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;
// Константы для хранилища :
#define STORE_HOST "127.0.0.1"
#define STORE_PORT "62222"
//Сертификат УЦ
#define CCERTIFICATE "MIICxTCCAm6gAwIBAgIgzTwle8CkqUG6HiBJktl0cfgg51ewTnL0DJYvhaplVlIwDgYKKwYBBAG1EQECAgUAMDM\
                      xEDAOBgNVBAMUB0FETUlOQ0ExEjAQBgNVBAoTCUdBTU1BVEVDSDELMAkGA1UEBhMCS1owIhgPMjAwODAxMDEwMT\
                      AxMDFaGA8yMDE4MDEwMTAxMDEwMVowMzEQMA4GA1UEAxQHQURNSU5DQTESMBAGA1UEChMJR0FNTUFURUNIMQswC\
                      QYDVQQGEwJLWjBjMA4GCisGAQQBtREBAgIFAANRAAYCAAA6qgAAAEVDMQACAADw2qYY1mq4OVlDu7PpgXZc8zZs\
                      hw6tM0INZDijLHnLOkSe+SaJGDBqd4gbOy2nGvRY3/fu4sLIJi8mUQVsPFjbo4IBQDCCATwwVQYDVR0jBE4wTIA\
                      gzTwle8CkqUG6HiBJktl0cfgg51ewTnL0DJYvhaplVlKhBocEfwAAAYIgzTwle8CkqUG6HiBJktl0cfgg51ewTn\
                      L0DJYvhaplVlIwKQYDVR0OBCIEIM08JXvApKlBuh4gSZLZdHH4IOdXsE5y9AyWL4WqZVZSMA4GA1UdDwEBAQQEA\
                      wIBBjASBgNVHRMBAQEECDAGAQEBAgECMIGTBgNVHSAEgYswgYgwgYUGCCsGAQQBtREDMHkwHwYIKwYBBQUHAgEW\
                      E2h0dHA6Ly93d3cuZ2FtbWEua3owVgYIKwYBBQUHAgIwSjAcFhXNyMsgw+Ds7OAg0uX17e7r7uPo/y4wAwIBARo\
                      qz/Do7OXwIO/u6+jy6OroIOjx7+7r/Ofu4uDt6P8g8eXw8uj06Org8uAuMA4GCisGAQQBtREBAgIFAANBAPzmGi\
                      BKNMZtSDuuPLgGIqzR+pP9a8SWdn+Z6pzrLbGiY5MRymCwl8TZxjOkIvJZzsv7ggxHqkkCS44SuEDSUDI="
//Список отозванных сертификатов
#define CRL          "MIIBKTCB0wIBATAOBgorBgEEAbURAQICBQAwMzEQMA4GA1UEAxQHQURNSU5DQTESMBAGA1UEChMJR0FNTUFURUN\
                      IMQswCQYDVQQGEwJLWhgPMjAwODAxMDEwMTAxMDFaGA8yMDA5MDEwMTAxMDEwMVowAKBlMGMwCgYDVR0UBAMCAQ\
                      EwVQYDVR0jBE4wTIAgzTwle8CkqUG6HiBJktl0cfgg51ewTnL0DJYvhaplVlKhBocEfwAAAYIgzTwle8CkqUG6H\
                      iBJktl0cfgg51ewTnL0DJYvhaplVlIwDgYKKwYBBAG1EQECAgUAA0EAOupS/vGyJ0RbFil5JI64Bi4P4A0ktGTh\
                      rO26G5BqgQAIsESh0WNqXnO7xeHGvSDe9xA4D4OfIjauNSdZ3YQrZg=="

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 *crptverifycrlsignature)
(const hCERTSTORE hStore,
	const unsigned char *crlBody,
	const unsigned long crlSize,
	const unsigned char *CABody,
	const unsigned long caSize);

cspopencontext					CSPOpenContext;
crtopenstore					CrtOpenStore;
crtclosestore					CrtCloseStore;
cspclosecontext					CSPCloseContext;
errorstring						ErrorString;
basetobin						BaseToBin;
crptverifycrlsignature			CrptVerifyCRLSignature;
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;
	}
	CrptVerifyCRLSignature = (crptverifycrlsignature)GetProcAddress(lib, "CrptVerifyCRLSignature");
	if (!CrptVerifyCRLSignature)
	{
		printf("error load function - %s", "CrptVerifyCRLSignature");
		return 1;
	}
	return 0;
}
//------------------------------------------------------------------------------
int main(void)
{
	int ret = 0;
	int code = 0;
	hCERTSTORE hStore = 0;
	HINSTANCE lib = NULL;
	HCRYPTPROV hP = 0;
	unsigned char *binCert = NULL;
	unsigned char *binCRL = NULL;
	long CRLSize;
	long binSize;
	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 = %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;
		}
		binCert = (unsigned char*)calloc(sizeof(CCERTIFICATE), sizeof(unsigned char));
		code = BaseToBin((unsigned char*)CCERTIFICATE, sizeof(CCERTIFICATE), binCert, &binSize);
		if (code)
		{
			printf("%s [BaseToBin: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		binCRL = (unsigned char*)calloc(sizeof(CRL), sizeof(unsigned char));
		code = BaseToBin((unsigned char*)CRL, sizeof(CRL), binCRL, &CRLSize);
		if (code)
		{
			printf("%s [BaseToBin: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		//проверить подпись СОС
		code = CrptVerifyCRLSignature(hStore, binCRL, CRLSize, binCert, binSize);
		if (code)
		{
			printf("%s [CrptVerifyCRLSignature: error = %d]\n", ErrorString(code), code);
			throw code;
		}
		printf("VerifyCRLSignature = OK\n");
	}
	catch (int er) { ret = er; }
	if (binCert) free(binCert);
	if (binCRL) free(binCRL);
	//закрыть хранилище сертификатов
	if (hStore)
	{
		CrtCloseStore(&hStore);
		hStore = (hCERTSTORE)NULL;
	}
	//удалить контекст криптопровайдера
	if (hP)
	{
		CSPCloseContext(&hP);
		hP = (HCRYPTPROV)NULL;
	}
	if (lib) lib_free(lib);
	return ret;
}
