#include #include #ifdef _WIN32 # include # include # include #else # include # include # include # include "reader/tchar.h" #endif #include #include //#define DEBUG_OUT 1 #define BLOCK_LENGTH 8 #define ASN1_LENGTH 172 #define ENCRKEY_OFFSET 7 #define ENCRKEY_LEN 32 #define MACKEY_OFFSET 41 #define MACKEY_LEN 4 #define PUBKEY_OFFSET 98 #define PUBKEY_LEN 64 #define SV_OFFSET 164 #define SV_LEN 8 static BYTE encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; static BYTE *decoding_table = NULL; static int mod_table[] = {0, 2, 1}; BYTE * base64_encode(const BYTE *data, DWORD input_length, DWORD *output_length); static void HandleError(char *s); static void CleanUp(void); static HCRYPTPROV hProv = 0; // Дескриптор CSP static HCRYPTKEY hKey = 0; // Дескриптор закрытого ключа static HCRYPTKEY hSessionKey = 0; // Дескриптор сессионного ключа static HCRYPTKEY hAgreeKey = 0; // Дескриптор ключа согласования static HCRYPTKEY hEphemeralKey = 0; // Дескриптор эфемерного ключа static FILE *fhCert=NULL; // Файл, в котором хранится сертификат static FILE *fhSource=NULL; // Исходный файл static FILE *fhOutput=NULL; // Исходный файл #ifdef DEBUG_OUT static FILE *fhEncrypt=NULL; // Зашифрованный файл static FILE *fhSession_SV=NULL; // Файл для хранения сессионного ключа (вектор инициализации) static FILE *fhSession_EncryptedKey=NULL; // Файл для хранения сессионного ключа (зашифрованный ключ) static FILE *fhSession_PublicKey=NULL; // Файл для хранения публичного эфемерного ключа static FILE *fhSession_MacKey=NULL; // Файл для хранения сессионного ключа (имита) static FILE *fhVector=NULL; // Файл для хранения вектора инициализации static FILE *fhEncryptionParam; // Файл для хранения неменяемой части блоба #endif static BYTE *pbKeyBlobSimple = NULL; // Указатель на сессионный ключевой BLOB static BYTE *pbIV = NULL; // Вектор инициализации сессионного ключа static BYTE *pbCipherValue = NULL; // Указатель шифрованный контент #define MAX_PUBLICKEYBLOB_SIZE 200 int main(int argc, char *argv[]) { BYTE pbKeyBlob[MAX_PUBLICKEYBLOB_SIZE]; // Указатель на ключевой BLOB DWORD dwBlobLen = MAX_PUBLICKEYBLOB_SIZE; // Длина ключевого BLOBа DWORD dwBlobLenSimple; // Длина сессионного ключевого BLOBа BYTE pbSenderPublicKeyBlob[MAX_PUBLICKEYBLOB_SIZE]; // Указатель на ключевой BLOB публичный, отправителя DWORD dwSenderPublicBlobLen = MAX_PUBLICKEYBLOB_SIZE; // Длина ключевого BLOBа, публичного, отправителя DWORD keyParam = CRYPT_MODE_CBC; DWORD paddingMode = ISO10126_PADDING; //cpm_ISO10126 BYTE * pbBufferB64; DWORD dwBufferB64Len; DWORD dwCipherValue; BYTE * pbPubCertData; DWORD dwPubCertData; BYTE * pbContent; // указатель на исходное содержимое DWORD cbContent = 0; // Длина содержимого DWORD dwIV = 0; // Длина вектора инициализации DWORD bufLen = sizeof(pbContent); // Длина буфера ALG_ID ke_alg = CALG_PRO_EXPORT /*CALG_PRO12_EXPORT*/; // алгоритм ключа согласования DWORD cbEncryptionParamSetStandart; // длина неизменяемой части блоба DWORD cbCert = 4000; // максимальный размер файла сертификата BYTE pbCert[4000]; // указатель на сертификат PCCERT_CONTEXT pCertContext = NULL; HCRYPTKEY hPubKey; BYTE pbKeyCipherValue[ASN1_LENGTH] = {0x30, 0x81, 0xA9, 0x30, 0x28, 4, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // offs 7: len 32 = Session Encrypted Key 4, 4, 0, 0, 0, 0, // offs 41 len 4 = Session Mac Key 0xA0, 0x7D, 6, 9, 0x2A, 0x85, 3, 7, 1, 2, 5, 1, 1, // OBJECT IDENTIFIER 1.2.643.7.1.2.5.1.1 tc26CipherZ (TC26 params Z for GOST 28147-89) 0xA0, 0x66, 0x30, 0x1F, 6, 8, 0x2A, 0x85, 3, 7, 1, 1, 1, 1, // OBJECT IDENTIFIER 1.2.643.7.1.1.1.1 gost2012PublicKey256 (GOST R 34.10-2012 256 bit public key) 0x30, 0x13, 6, 7, 0x2A, 0x85, 3, 2, 2, 0x24, 0, // OBJECT IDENTIFIER 1.2.643.2.2.36.0 cryptoProSignXA (CryptoPro ell.curve XA for GOST R 34.10-2001) 6, 8, 0x2A, 0x85, 3, 7, 1, 1, 2, 2, 3, // OBJECT IDENTIFIER 1.2.643.7.1.1.2.2 gost2012Digest256 (GOST R 34.11-2012 256 bit digest) 0x43, 0, 4, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // offs 98 = : len 64 = Session Public Key 0x4, 0x8, 0, 0, 0, 0, 0, 0, 0, 0 // offs 164: len 8 = Session SV }; // Указатель на структуру ASN1 для ключа DWORD dwKeyCipherValue = ASN1_LENGTH; static BYTE xml_1[] = "" "" "" "" "" "" "" "" "" "" "" ""; static BYTE xml_2[] = "" "" "" "" ""; static BYTE xml_3[] = "" "" "" "" "" ""; static BYTE xml_4[] = "" "" "" "" ""; if(argc < 5) { printf("Encryption tool for FSS ELN service.\nver 0.01, IbZ(c) Studio (tm) :)\n" ); printf("\n\tusing: %s \n\n", argv[0]); HandleError( "Not enough input parameters given" ); } // Открытие файла, который будет зашифрован. if(!(fhSource = fopen(argv[3], "rb"))) HandleError( "Problem opening the source file \n" ); fseek(fhSource, 0, SEEK_END); cbContent = ftell(fhSource); rewind(fhSource); #ifdef DEBUG_OUT printf( "01. The file '%s' was opened, length = %d bytes\n", argv[3],cbContent ); #endif pbContent = (BYTE *)malloc(cbContent); if(!pbContent) HandleError("Out of memory. \n"); if(!(fhOutput = fopen(argv[4], "wb"))) HandleError( "Problem opening the file output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe file '%s' was opened\n", argv[4] ); // Открытие файла, в который будет производится запись блока зашифрованного файла. if(!(fhEncrypt = fopen("encrypt.bin", "wb"))) HandleError( "Problem opening the file 'encrypt.bin'\n" ); printf( "\tThe file 'encrypt.bin' was opened\n" ); // Открытие файла, в который производится запись синхропосылки. if(!(fhSession_SV = fopen("session_SV.bin", "wb"))) HandleError( "Problem opening the file 'session_SV.bin'\n" ); printf( "\tThe file 'session_SV.bin' was opened\n" ); // Открытие файла, в который производится запись сессионного ключа. if(!(fhSession_EncryptedKey = fopen("session_EncryptedKey.bin", "wb"))) HandleError( "Problem opening the file 'session_EncryptedKey.bin'\n" ); printf( "\tThe file 'session_EncryptedKey.bin' was opened\n" ); if(!(fhSession_PublicKey = fopen("session_PublicKey.bin", "wb"))) HandleError( "Problem opening the file 'session_PublicKey.bin'\n" ); printf( "\tThe file 'session_PublicKey.bin' was opened\n" ); // Открытие файла, в который производится запись MAC сессионного ключа. if(!(fhSession_MacKey = fopen("session_MacKey.bin", "wb"))) HandleError( "Problem opening the file 'session_MacKey.bin'\n" ); printf( "\tThe file 'session_MacKey.bin' was opened\n" ); // Открытие файла, в который производится запись вектора инициализации. if(!(fhVector = fopen("vector.bin", "wb"))) HandleError( "Problem opening the file 'vector.bin'\n" ); printf( "\tThe file 'vector.bin' was opened\n" ); // Открытие файла, в который производится запись вектора инициализации. if (!(fhEncryptionParam = fopen("EncryptionParam.bin", "wb"))) HandleError("Problem opening the file 'EncryptionParam.bin'\n"); printf( "\tThe file 'EncryptionParam.bin' was opened\n"); #endif // Получение дескриптора контейнера отправителя, находящегося в рамках провайдера. // if(CryptAcquireContext( &hProv, _TEXT("HDIMAGE\\\\2019rnik.000\\026C"), NULL, PROV_GOST_2012_256, 0)) if(!CryptAcquireContext( &hProv, argv[1], NULL, PROV_GOST_2012_256, 0)) HandleError("Error during CryptAcquireContext."); #ifdef DEBUG_OUT printf("02. The key container \"%s\" has been acquired. \n", argv[1]); #endif // Загрузка PUBLICKEYBLOB из сертификата, открытие файла, в котором содержится открытый ключ получателя. if((fhCert = fopen(argv[2], "rb"))) { #ifdef DEBUG_OUT printf( "\tThe file '%s' was opened\n", argv[2]); #endif cbCert = (DWORD)fread(pbCert, 1, cbCert, fhCert); if(!cbCert) HandleError( "Failed to read certificate\n" ); #ifdef DEBUG_OUT printf( "\tCertificate was read from the '%s'\n", argv[2] ); #endif pCertContext = CertCreateCertificateContext ( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbCert, cbCert); if (!pCertContext) HandleError( "CertCreateCertificateContext" ); // Импортируем открытый ключ if (!CryptImportPublicKeyInfoEx( hProv, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->SubjectPublicKeyInfo), 0, 0, NULL, &hPubKey)) { CertFreeCertificateContext(pCertContext); HandleError( "CryptImportPublicKeyInfoEx" ); } #ifdef DEBUG_OUT printf("\tPublic key imported from cert file\n"); #endif CertFreeCertificateContext(pCertContext); // экспорт открытого ключа получателя в BLOB if (!CryptExportKey( hPubKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) HandleError( "CryptExportKey" ); #ifdef DEBUG_OUT printf("\tPublic key exported to blob\n"); #endif } // begin hack // генерация эфемерной ключевой пары if(!CryptGenKey(hProv, /* CALG_DH_EL_EPHEM */ CALG_DH_GR3410_12_256_EPHEM, CRYPT_EXPORTABLE, &hEphemeralKey)) HandleError("Error during CryptGenKey Ephemeral key."); #ifdef DEBUG_OUT printf("03. The Ephemeral key has been acquired. \n"); #endif // экспорт открытого ключа отправителя в BLOB if(!CryptExportKey(hEphemeralKey, 0, PUBLICKEYBLOB, 0, pbSenderPublicKeyBlob, &dwSenderPublicBlobLen)) HandleError("Error during CryptExportKey of Sender\'s public key."); #ifdef DEBUG_OUT printf("04. The Sender public key has been acquired. size of Blob = %d bytes\n", dwSenderPublicBlobLen); #endif // получаем значение открытого ключа отправителя из PUBLICKEYBLOB memcpy(&pbKeyCipherValue[PUBKEY_OFFSET], &pbSenderPublicKeyBlob[dwSenderPublicBlobLen-PUBKEY_LEN], PUBKEY_LEN); #ifdef DEBUG_OUT if(!fwrite( pbSenderPublicKeyBlob, 1, dwSenderPublicBlobLen, fhSession_PublicKey)) HandleError( "The session key can not be written to the 'session_PublicKey.bin'\n" ); printf("\tThe session key was written to the 'session_PublicKey.bin'\n" ); #endif // Получение дескриптора закрытого ключа отправителя. нам нужно для получения сертификата который вставим в запрос if(!CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hKey)) HandleError("Error during CryptGetUserKey private key."); #ifdef DEBUG_OUT printf("05. The private key has been acquired. \n"); #endif // определяем размер блока памяти для получения нашего сертификата который мы пошлем в ФСС if(!CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &dwPubCertData, 0)) HandleError("Error during CryptGetKeyParam for determinating size of certificate."); #ifdef DEBUG_OUT printf("06. The size for Public Certificate has been acquired. \n"); #endif pbPubCertData = (BYTE*)malloc(dwPubCertData); if(!pbPubCertData) HandleError("Out of memory. \n"); // получачем сам сертификата который мы пошлем в ФСС в подготовленную область памяти if(!CryptGetKeyParam(hKey, KP_CERTIFICATE, pbPubCertData, &dwPubCertData, 0)) HandleError("Error during CryptGetKeyParam when get certificate"); #ifdef DEBUG_OUT printf("07. The our Certificate has been acquired. \n"); #endif // Получение ключа согласования импортом открытого ключа получателя на эфемерном ключе, ----не на закрытом ключе отправителя. if(!CryptImportKey(hProv, pbKeyBlob, dwBlobLen, hEphemeralKey, 0, &hAgreeKey)) HandleError("Error during CryptImportKey public key."); #ifdef DEBUG_OUT printf("08. get AgreeKey by importing the responder public key. \n"); #endif // Установление ----PRO12_EXPORT (на саомм деле нет, PRO_EXPORT) алгоритма ключа согласования if(!CryptSetKeyParam( hAgreeKey, KP_ALGID, (LPBYTE)&ke_alg, 0)) HandleError("Error during CryptSetKeyParam agree key."); //printf("22. PRO12_EXPORT agree key algorithm has been set. \n"); #ifdef DEBUG_OUT printf("09. PRO_EXPORT agree key algorithm has been set. \n"); #endif // Генерация случайного сессионного ключа. if(!CryptGenKey( hProv, CALG_G28147, CRYPT_EXPORTABLE, &hSessionKey)) HandleError("ERROR -- CryptGenKey failed for random session key."); #ifdef DEBUG_OUT printf("10. Original session key is created. \n"); #endif //-------------------------------------------------------------------- // Зашифрование сессионного ключа. //-------------------------------------------------------------------- // экспорт сессионного ключа в BLOB // Определение размера BLOBа сессионного ключа и распределение памяти. if(!CryptExportKey( hSessionKey, hAgreeKey, SIMPLEBLOB, 0, NULL, &dwBlobLenSimple)) HandleError("Error computing BLOB length."); #ifdef DEBUG_OUT printf("11. Size of the BLOB for the sender session key determined. \n"); #endif pbKeyBlobSimple = (BYTE*)malloc(dwBlobLenSimple); if(!pbKeyBlobSimple) HandleError("Out of memory. \n"); // Зашифрование сессионного ключа на ключе Agree. экспорт сессионного ключа на ключе согласования if(!CryptExportKey( hSessionKey, hAgreeKey, SIMPLEBLOB, 0, pbKeyBlobSimple, &dwBlobLenSimple)) HandleError("Error during CryptExportKey."); #ifdef DEBUG_OUT printf("12. Contents have been written to the BLOB. \n"); #endif memcpy(&pbKeyCipherValue[SV_OFFSET], ((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bSV, SV_LEN); memcpy(&pbKeyCipherValue[ENCRKEY_OFFSET], ((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptedKey, ENCRKEY_LEN); memcpy(&pbKeyCipherValue[MACKEY_OFFSET], ((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bMacKey, MACKEY_LEN); // режим шифрования CBC if(!CryptSetKeyParam(hSessionKey, KP_MODE, (LPBYTE)&keyParam, 0)) HandleError("Error during CryptSetKeyParam cipher mode."); #ifdef DEBUG_OUT printf("\tSet crypt param CRYPT_MODE_CBC. \n"); #endif // режим паддинга if(!CryptSetKeyParam(hSessionKey, KP_PADDING, (LPBYTE)&paddingMode, 0)) HandleError("Error during CryptSetKeyParam padding mode."); #ifdef DEBUG_OUT printf("\tSet crypt param ISO10126_PADDING. \n"); #endif //end hacking // Определение размера вектора инициализации сессионного ключа. if(!CryptGetKeyParam( hSessionKey, KP_IV, NULL, &dwIV, 0)) HandleError("Error computing IV length."); #ifdef DEBUG_OUT printf("13. Size of the IV for the session key determined. \n"); #endif pbIV = (BYTE*)malloc(dwIV); if (!pbIV) HandleError("Out of memory. \n"); // Получение вектора инициализации сессионного ключа. if(!CryptGetKeyParam( hSessionKey, KP_IV, pbIV, &dwIV, 0)) HandleError("Error during CryptGetKeyParam."); #ifdef DEBUG_OUT printf( "14. CryptGetKeyParam succeeded. \n"); //-------------------------------------------------------------------- // Запись вектора инициализации в файл. if(!fwrite( pbIV, 1, dwIV, fhVector)) HandleError( "The IV can not be written to the 'vector.bin'\n" ); printf( "\tThe IV was written to the 'vector.bin'\n" ); //-------------------------------------------------------------------- // Запись сессионного вектора в файл. if(!fwrite( ((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bSV, 1, SEANCE_VECTOR_LEN, fhSession_SV)) HandleError( "The session vector can not be written to the 'session_SV.bin'\n" ); printf( "\tThe session vector was written to the 'session_SV.bin'\n" ); //-------------------------------------------------------------------- // Запись сессионного зашифрованного ключа в файл. if(!fwrite( ((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptedKey, 1, G28147_KEYLEN, fhSession_EncryptedKey)) HandleError( "The session key can not be written to the 'session_EncryptedKey.bin'\n" ); printf( "\tThe session key was written to the 'session_EncryptedKey.bin'\n" ); //-------------------------------------------------------------------- // Запись сессионного MAC ключа в файл. if(!fwrite( ((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bMacKey, 1, EXPORT_IMIT_SIZE, fhSession_MacKey)) HandleError( "The session key can not be written to the 'session_MacKey.bin'\n" ); printf( "\tThe session key was written to the 'session_MacKey.bin'\n" ); #endif //-------------------------------------------------------------------- // Запись неизменяемой части блоба в файл. if (((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptionParamSet[0] != 0x30) HandleError("The EncryptionParam can not be written to the 'EncryptionParam.bin' - first byte is not 0x30\n"); cbEncryptionParamSetStandart = (DWORD)((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptionParamSet[1] + sizeof((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptionParamSet[0] + sizeof((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptionParamSet[1]; #ifdef DEBUG_OUT if (!fwrite(((CRYPT_SIMPLEBLOB*)pbKeyBlobSimple)->bEncryptionParamSet, 1, cbEncryptionParamSetStandart, fhEncryptionParam)) HandleError("The EncryptionParam can not be written to the 'EncryptionParam.bin'\n"); printf("\tThe EncryptionParam was written to the 'EncryptionParam.bin'\n"); //-------------------------------------------------------------------- // Чтение файла, и шифрование прочитанного блока и запись его в файл "encrypt.bin". Это будет // 'SOAP-ENV:Envelope -> SOAP-ENV:Body -> EncryptedData -> CipherData -> CipherValue //-------------------------------------------------------------------- printf( "15. Begin Encryption:\n"); #endif // сначала копируем вектор инициализации dwCipherValue = dwIV; pbCipherValue = (BYTE*)malloc(dwIV); if (!pbCipherValue) HandleError("Out of memory. \n"); memcpy(pbCipherValue,pbIV,dwIV); bufLen = cbContent; if( (DWORD)fread(pbContent, 1, cbContent, fhSource) != cbContent ) HandleError( "Problem reading the source xml file \n" ); // сначала определяем необходимый размер блока памяти if(!CryptEncrypt(hSessionKey, 0, TRUE, 0, NULL, &bufLen, 0)) HandleError("get memory size for Encryption failed."); #ifdef DEBUG_OUT printf( "\tget memory size %d bytes for encryption success....\n", bufLen); #endif pbContent = (BYTE*)realloc(pbContent, bufLen); if (!pbContent) HandleError("Out of memory. \n"); if(!CryptEncrypt(hSessionKey, 0, TRUE, 0, pbContent, &cbContent, bufLen)) HandleError("Encryption failed."); pbCipherValue = (BYTE*)realloc(pbCipherValue, dwCipherValue+cbContent); if (!pbCipherValue) HandleError("Out of memory. \n"); memcpy(&pbCipherValue[dwCipherValue], pbContent, cbContent); dwCipherValue += cbContent; #ifdef DEBUG_OUT if(!fwrite( pbContent, 1, cbContent, fhEncrypt)) HandleError( "The encrypted content can not be written \n" ); printf( "\tencrypted %d bytes, to %d bytes....\n" , cbContent, bufLen); #endif // ------------------------------------------------------- // начинаем запись результирующего зашифрованного XML // ------------------------------------------------------- if(!fwrite(xml_1, 1,sizeof(xml_1)-1, fhOutput)) HandleError( "The 1st part of xml can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "-------- writing result file xml ----------\n\tThe 1st part of xml was written to the '%s'\n", argv[4] ); #endif pbBufferB64 = base64_encode(pbPubCertData, dwPubCertData, &dwBufferB64Len); if(!fwrite( pbBufferB64, 1, dwBufferB64Len, fhOutput)) HandleError( "The encrypted data can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe encrypted data was written to the '%s'\n", argv[4] ); #endif if(!fwrite(xml_2, 1,sizeof(xml_2)-1, fhOutput))HandleError( "The 2nd part of xml can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe 2nd part of xml was written to the '%s'\n", argv[4] ); #endif pbBufferB64 = base64_encode(pbKeyCipherValue, ASN1_LENGTH, &dwBufferB64Len); if(!fwrite( pbBufferB64, 1, dwBufferB64Len, fhOutput)) HandleError( "The session structure can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe session structure was written to the '%s'\n", argv[4] ); #endif if(!fwrite(xml_3, 1,sizeof(xml_3)-1, fhOutput)) HandleError( "The 3rd part of xml can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe 3rd part of xml was written to the '%s'\n", argv[4] ); #endif pbBufferB64 = base64_encode(pbCipherValue, dwCipherValue, &dwBufferB64Len); if(!fwrite( pbBufferB64, 1, dwBufferB64Len, fhOutput)) HandleError( "The encrypted data can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe encrypted data was written to the '%s'\n", argv[4] ); #endif if(!fwrite(xml_4, 1,sizeof(xml_4)-1, fhOutput)) HandleError( "The 4th part of xml can not be written to the output xml file\n" ); #ifdef DEBUG_OUT printf( "\tThe 4th part of xml was written to the '%s'\n---- writing result file xml complete ------\n", argv[4] ); #endif CleanUp(); #ifdef DEBUG_OUT printf("\nThe program ran to completion without error. \n"); #endif return 0; } void CleanUp(void) { if(fhSource) fclose (fhSource); if(fhOutput) fclose (fhOutput); if(fhCert) fclose (fhCert); #ifdef DEBUG_OUT if(fhEncrypt) fclose (fhEncrypt); if(fhSession_SV) fclose (fhSession_SV); if(fhSession_EncryptedKey) fclose (fhSession_EncryptedKey); if(fhSession_PublicKey) fclose (fhSession_PublicKey); if(fhSession_MacKey) fclose (fhSession_MacKey); if(fhVector) fclose (fhVector); if(fhEncryptionParam) fclose(fhEncryptionParam); #endif if(hKey) CryptDestroyKey(hKey); if(hEphemeralKey) CryptDestroyKey(hEphemeralKey); if(hSessionKey) CryptDestroyKey(hSessionKey); if(hAgreeKey) CryptDestroyKey(hAgreeKey); if(hProv) CryptReleaseContext(hProv, 0); if(pbKeyBlobSimple) free(pbKeyBlobSimple); if(pbIV) free(pbIV); } BYTE * base64_encode(const BYTE *data, DWORD input_length, DWORD *output_length) { WORD i, j; DWORD octet_a, octet_b, octet_c, triple; *output_length = 4 * ((input_length + 2) / 3); BYTE * encoded_data = malloc(*output_length); if (encoded_data == NULL) return NULL; for (i = 0, j = 0; i < input_length;) { octet_a = i < input_length ? (BYTE)data[i++] : 0; octet_b = i < input_length ? (BYTE)data[i++] : 0; octet_c = i < input_length ? (BYTE)data[i++] : 0; triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; } for (i = 0; i < mod_table[input_length % 3]; i++) encoded_data[*output_length - 1 - i] = '='; return encoded_data; } void HandleError(char *s) { DWORD err = GetLastError(); printf("Error number : 0x%x\n", err); printf("Error description: %s\n", s); CleanUp(); if(!err) err = 1; exit(err); }