// store KeyB int __cdecl cpp_init_keyb(HANDLE context, LPCSTR key) { pCNTX ptr = get_context_on_id(context); if(!ptr) return 0; pSIMDATA p = (pSIMDATA) cpp_alloc_pdata(ptr); int clen = rtrim(key); ptr->features = 0; LPSTR pub_binary; if((clen==KEYSIZE*2) || (clen==(KEYSIZE+2)*2)) pub_binary = base16decode(key,&clen); else pub_binary = base64decode(key,&clen); if( !pub_binary || (clen!=KEYSIZE && clen!=KEYSIZE+2) ) { #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_init_keyb: error bad_keyb"); #endif ptr->error = ERROR_BAD_KEYB; SAFE_FREE(pub_binary); return 0; } if(clen==KEYSIZE+2) memcpy((PVOID)&ptr->features,(PVOID)(pub_binary+KEYSIZE),2); if(p->KeyP) { if(!(ptr->features & FEATURES_PSK)) { // if NO PSK on other side #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_init_keyb: error no_psk"); #endif ptr->error = ERROR_NO_PSK; return 0; } ptr->error = ERROR_BAD_PSK; try { // decrypt PUBLIC use PSK string unciphered; CFB_Mode<AES>::Decryption dec(p->KeyP,Tiger::DIGESTSIZE,IV); StreamTransformationFilter cbcDecryptor(dec,new StringSink(unciphered)); cbcDecryptor.Put((PBYTE)pub_binary,KEYSIZE); cbcDecryptor.MessageEnd(); memcpy(pub_binary,unciphered.data(),unciphered.length()); } catch (...) { #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_init_keyb: error bad_psk"); #endif return 0; } } SAFE_FREE(p->KeyB); p->KeyB = (PBYTE) pub_binary; if(p->PubA && memcmp(p->PubA,p->KeyB,KEYSIZE)==0) { #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_init_keyb: error bad_keyb keya==keyb"); #endif SAFE_FREE(p->KeyB); ptr->error = ERROR_BAD_KEYB; return 0; } ptr->error = ERROR_NONE; return 1; }
char *base16decode(const char *inBuffer) { int count = (int)strlen(inBuffer); return base16decode(inBuffer, &count); }
// decrypt string using KeyX, return decoded string as ASCII or NULL LPSTR __cdecl cpp_decrypt(pCNTX ptr, LPCSTR szEncMsg) { ptrA ciphered; try { ptr->error = ERROR_SEH; pSIMDATA p = (pSIMDATA)ptr->pdata; unsigned clen = (unsigned)strlen(szEncMsg); if (ptr->features & FEATURES_BASE64) ciphered = (LPSTR)mir_base64_decode(szEncMsg, &clen); else ciphered = base16decode(szEncMsg, &clen); LPSTR bciphered = ciphered; BYTE dataflag = 0; if (ptr->features & FEATURES_GZIP) { dataflag = *ciphered; bciphered++; clen--; // cut GZIP flag } if (ptr->features & FEATURES_CRC32) { int len = *(WORD*)bciphered; bciphered += 2; clen -= 2; // cut CRC32 length if ((int)clen - CRC32::DIGESTSIZE < len) { // mesage not full #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_decrypt: error bad_len"); #endif ptr->error = ERROR_BAD_LEN; return NULL; } BYTE crc32[CRC32::DIGESTSIZE]; memset(crc32, 0, sizeof(crc32)); CRC32().CalculateDigest(crc32, (PBYTE)(bciphered + CRC32::DIGESTSIZE), len); if (memcmp(crc32, bciphered, CRC32::DIGESTSIZE)) { // message is bad crc #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_decrypt: error bad_crc"); #endif ptr->error = ERROR_BAD_CRC; return NULL; } bciphered += CRC32::DIGESTSIZE; // cut CRC32 digest clen = len; } string unciphered; CBC_Mode<AES>::Decryption dec(p->KeyX, Tiger::DIGESTSIZE, IV); StreamTransformationFilter cbcDecryptor(dec, new StringSink(unciphered)); cbcDecryptor.Put((PBYTE)bciphered, clen); cbcDecryptor.MessageEnd(); if (dataflag & DATA_GZIP) { size_t clen2 = clen; LPSTR res = (LPSTR)cpp_gunzip((PBYTE)unciphered.data(), unciphered.length(), clen2); replaceStr(ptr->tmp, mir_strndup(res, clen2)); free(res); } else replaceStr(ptr->tmp, mir_strdup(unciphered.c_str())); ptr->error = ERROR_NONE; return ptr->tmp; } catch (...) { #if defined(_DEBUG) || defined(NETLIB_LOG) Sent_NetLog("cpp_decrypt: error seh"); #endif mir_free(ptr->tmp); ptr->tmp = 0; return NULL; } }
char *base16decode(const char *inBuffer) { unsigned count = (unsigned)strlen(inBuffer); return base16decode(inBuffer, &count); }