| 1 | #ifdef HAVE_LIBCRYPTOPP
|
|---|
| 2 | #include <cryptopp/cryptlib.h>
|
|---|
| 3 | #include <cryptopp/modes.h>
|
|---|
| 4 | #include <cryptopp/des.h>
|
|---|
| 5 | #include <cryptopp/aes.h>
|
|---|
| 6 | #include <cryptopp/cast.h>
|
|---|
| 7 | #include <cryptopp/tea.h>
|
|---|
| 8 | #include <cryptopp/3way.h>
|
|---|
| 9 | #include <cryptopp/blowfish.h>
|
|---|
| 10 | #include <cryptopp/twofish.h>
|
|---|
| 11 | #include <cryptopp/rc2.h>
|
|---|
| 12 | #include <cryptopp/arc4.h>
|
|---|
| 13 | #include <cryptopp/serpent.h>
|
|---|
| 14 | #include <cryptopp/gost.h>
|
|---|
| 15 | #include <cryptopp/filters.h>
|
|---|
| 16 | #include <cryptopp/osrng.h>
|
|---|
| 17 | #endif
|
|---|
| 18 |
|
|---|
| 19 | #define TRANSMITTED_IV_SIZE 128 /* size of IV to transmit - must be as big as largest IV needed for any crypto algorithm */
|
|---|
| 20 |
|
|---|
| 21 | /********************* ENCRYPTION TYPES ****************/
|
|---|
| 22 |
|
|---|
| 23 | #define ENCRYPT_NONE 0 /* no encryption */
|
|---|
| 24 | #define ENCRYPT_XOR 1 /* not really encrypted, just obfuscated */
|
|---|
| 25 |
|
|---|
| 26 | #ifdef HAVE_LIBCRYPTOPP
|
|---|
| 27 | #define ENCRYPT_DES 2 /* DES */
|
|---|
| 28 | #define ENCRYPT_3DES 3 /* 3DES or Triple DES */
|
|---|
| 29 | #define ENCRYPT_CAST128 4 /* CAST-128 */
|
|---|
| 30 | #define ENCRYPT_CAST256 5 /* CAST-256 */
|
|---|
| 31 | #define ENCRYPT_XTEA 6 /* xTEA */
|
|---|
| 32 | #define ENCRYPT_3WAY 7 /* 3-WAY */
|
|---|
| 33 | #define ENCRYPT_BLOWFISH 8 /* SKIPJACK */
|
|---|
| 34 | #define ENCRYPT_TWOFISH 9 /* TWOFISH */
|
|---|
| 35 | #define ENCRYPT_LOKI97 10 /* LOKI97 */
|
|---|
| 36 | #define ENCRYPT_RC2 11 /* RC2 */
|
|---|
| 37 | #define ENCRYPT_ARCFOUR 12 /* RC4 */
|
|---|
| 38 | #define ENCRYPT_RC6 13 /* RC6 */ /* UNUSED */
|
|---|
| 39 | #define ENCRYPT_RIJNDAEL128 14 /* RIJNDAEL-128 */
|
|---|
| 40 | #define ENCRYPT_RIJNDAEL192 15 /* RIJNDAEL-192 */
|
|---|
| 41 | #define ENCRYPT_RIJNDAEL256 16 /* RIJNDAEL-256 */
|
|---|
| 42 | #define ENCRYPT_MARS 17 /* MARS */ /* UNUSED */
|
|---|
| 43 | #define ENCRYPT_PANAMA 18 /* PANAMA */ /* UNUSED */
|
|---|
| 44 | #define ENCRYPT_WAKE 19 /* WAKE */
|
|---|
| 45 | #define ENCRYPT_SERPENT 20 /* SERPENT */
|
|---|
| 46 | #define ENCRYPT_IDEA 21 /* IDEA */ /* UNUSED */
|
|---|
| 47 | #define ENCRYPT_ENIGMA 22 /* ENIGMA (Unix crypt) */
|
|---|
| 48 | #define ENCRYPT_GOST 23 /* GOST */
|
|---|
| 49 | #define ENCRYPT_SAFER64 24 /* SAFER-sk64 */
|
|---|
| 50 | #define ENCRYPT_SAFER128 25 /* SAFER-sk128 */
|
|---|
| 51 | #define ENCRYPT_SAFERPLUS 26 /* SAFER+ */
|
|---|
| 52 | #endif
|
|---|
| 53 | #define LAST_ENCRYPTION_ID 26
|
|---|
| 54 |
|
|---|
| 55 | class nsca_encrypt {
|
|---|
| 56 | public:
|
|---|
| 57 | class encryption_exception {
|
|---|
| 58 | std::wstring msg_;
|
|---|
| 59 | public:
|
|---|
| 60 | encryption_exception() {}
|
|---|
| 61 | encryption_exception(std::wstring msg) : msg_(msg) {}
|
|---|
| 62 | std::wstring getMessage() const { return msg_; }
|
|---|
| 63 |
|
|---|
| 64 | };
|
|---|
| 65 | class any_encryption {
|
|---|
| 66 | public:
|
|---|
| 67 | virtual void init(std::string password, unsigned char *transmitted_iv, int iv_size) = 0;
|
|---|
| 68 | virtual void encrypt(unsigned char *buffer, int buffer_size) = 0;
|
|---|
| 69 | virtual void decrypt(unsigned char *buffer, int buffer_size) = 0;
|
|---|
| 70 | virtual std::wstring getName() = 0;
|
|---|
| 71 | };
|
|---|
| 72 | #ifdef HAVE_LIBCRYPTOPP
|
|---|
| 73 | template <class TMethod>
|
|---|
| 74 | class cryptopp_encryption : public any_encryption {
|
|---|
| 75 | private:
|
|---|
| 76 | typedef CryptoPP::CFB_Mode_ExternalCipher::Encryption TEncryption;
|
|---|
| 77 | typedef typename TMethod::Encryption TCipher;
|
|---|
| 78 | TEncryption crypto_;
|
|---|
| 79 | TCipher cipher_;
|
|---|
| 80 | int keysize_;
|
|---|
| 81 | public:
|
|---|
| 82 | cryptopp_encryption() : keysize_(TMethod::DEFAULT_KEYLENGTH) {}
|
|---|
| 83 | cryptopp_encryption(int keysize) : keysize_(keysize) {}
|
|---|
| 84 | int get_keySize() {
|
|---|
| 85 | return keysize_;
|
|---|
| 86 | }
|
|---|
| 87 | int get_blockSize() {
|
|---|
| 88 | return TMethod::BLOCKSIZE;
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | void init(std::string password, unsigned char *transmitted_iv, int iv_size) {
|
|---|
| 92 | /* generate an encryption/description key using the password */
|
|---|
| 93 | unsigned int keysize=get_keySize();
|
|---|
| 94 |
|
|---|
| 95 | unsigned char *key = new unsigned char[keysize+1];
|
|---|
| 96 | if (key == NULL){
|
|---|
| 97 | throw encryption_exception(_T("Could not allocate memory for encryption/decryption key"));
|
|---|
| 98 | }
|
|---|
| 99 | ZeroMemory(key,keysize*sizeof(unsigned char));
|
|---|
| 100 | strncpy(reinterpret_cast<char*>(key),password.c_str(),min(keysize,password.length()));
|
|---|
| 101 |
|
|---|
| 102 |
|
|---|
| 103 | /* determine size of IV buffer for this algorithm */
|
|---|
| 104 | int blocksize = get_blockSize();
|
|---|
| 105 | if(blocksize>iv_size){
|
|---|
| 106 | throw encryption_exception(_T("IV size for crypto algorithm exceeds limits"));
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | /* allocate memory for IV buffer */
|
|---|
| 110 | unsigned char *iv = new unsigned char[blocksize+1];
|
|---|
| 111 | if (iv == NULL){
|
|---|
| 112 | throw encryption_exception(_T("Could not allocate memory for IV buffer"));
|
|---|
| 113 | }
|
|---|
| 114 |
|
|---|
| 115 | /* fill IV buffer with first bytes of IV that is going to be used to crypt (determined by server) */
|
|---|
| 116 | memcpy(iv, transmitted_iv, sizeof(unsigned char)*blocksize);
|
|---|
| 117 |
|
|---|
| 118 | try {
|
|---|
| 119 | cipher_.SetKey(key, keysize);
|
|---|
| 120 | crypto_.SetCipherWithIV(cipher_, iv, 1);
|
|---|
| 121 | } catch (...) {
|
|---|
| 122 | throw encryption_exception(_T("Unknown exception when trying to setup crypto"));
|
|---|
| 123 | }
|
|---|
| 124 | delete [] iv;
|
|---|
| 125 | delete [] key;
|
|---|
| 126 | }
|
|---|
| 127 | void encrypt(unsigned char *buffer, int buffer_size) {
|
|---|
| 128 | /* encrypt each byte of buffer, one byte at a time (CFB mode) */
|
|---|
| 129 | try {
|
|---|
| 130 | for(int x=0;x<buffer_size;x++)
|
|---|
| 131 | crypto_.ProcessData(&buffer[x], &buffer[x], 1);
|
|---|
| 132 | } catch (...) {
|
|---|
| 133 | throw encryption_exception(_T("Unknown exception when trying to setup crypto"));
|
|---|
| 134 | }
|
|---|
| 135 | }
|
|---|
| 136 | void decrypt(unsigned char *buffer, int buffer_size) {
|
|---|
| 137 | throw encryption_exception(_T("Decryption not supported"));
|
|---|
| 138 | }
|
|---|
| 139 | std::wstring getName() {
|
|---|
| 140 | return strEx::string_to_wstring(TMethod::StaticAlgorithmName());
|
|---|
| 141 | }
|
|---|
| 142 |
|
|---|
| 143 | };
|
|---|
| 144 | #endif
|
|---|
| 145 | class no_encryption : public any_encryption {
|
|---|
| 146 | public:
|
|---|
| 147 | static int get_keySize() {
|
|---|
| 148 | return 0;
|
|---|
| 149 | }
|
|---|
| 150 | static int get_blockSize() {
|
|---|
| 151 | return 1;
|
|---|
| 152 | }
|
|---|
| 153 | void init(std::string password, unsigned char *transmitted_iv, int iv_size) {}
|
|---|
| 154 | void encrypt(unsigned char *buffer, int buffer_size) {}
|
|---|
| 155 | void decrypt(unsigned char *buffer, int buffer_size) {}
|
|---|
| 156 | std::wstring getName() {
|
|---|
| 157 | return _T("No Encryption (not safe)");
|
|---|
| 158 | }
|
|---|
| 159 | };
|
|---|
| 160 | class xor_encryption : public any_encryption {
|
|---|
| 161 | private:
|
|---|
| 162 | int password_size_;
|
|---|
| 163 | int iv_size_;
|
|---|
| 164 | unsigned char* transmitted_iv_;
|
|---|
| 165 | unsigned char* password_;
|
|---|
| 166 | public:
|
|---|
| 167 | xor_encryption() : transmitted_iv_(NULL), password_(NULL) {}
|
|---|
| 168 | ~xor_encryption() {
|
|---|
| 169 | delete [] password_;
|
|---|
| 170 | delete [] transmitted_iv_;
|
|---|
| 171 | }
|
|---|
| 172 | static int get_keySize() {
|
|---|
| 173 | return 0;
|
|---|
| 174 | }
|
|---|
| 175 | static int get_blockSize() {
|
|---|
| 176 | return 1;
|
|---|
| 177 | }
|
|---|
| 178 | void init(std::string password, unsigned char *transmitted_iv, int iv_size) {
|
|---|
| 179 | iv_size_ = iv_size;
|
|---|
| 180 | delete [] transmitted_iv_;
|
|---|
| 181 | transmitted_iv_ = new unsigned char[iv_size_+1];
|
|---|
| 182 | if (transmitted_iv_ == NULL)
|
|---|
| 183 | throw encryption_exception(_T("Failed to allocate memory for iv"));
|
|---|
| 184 | memcpy(transmitted_iv_, transmitted_iv, sizeof(unsigned char)*iv_size_);
|
|---|
| 185 |
|
|---|
| 186 | password_size_ = password.length();
|
|---|
| 187 | delete [] password_;
|
|---|
| 188 | password_ = new unsigned char[password_size_+1];
|
|---|
| 189 | if (password_ == NULL)
|
|---|
| 190 | throw encryption_exception(_T("Failed to allocate memory for password"));
|
|---|
| 191 | memcpy(password_, password.c_str(), sizeof(unsigned char)*password_size_);
|
|---|
| 192 |
|
|---|
| 193 | }
|
|---|
| 194 | void encrypt(unsigned char *buffer, int buffer_size) {
|
|---|
| 195 | /* rotate over IV we received from the server... */
|
|---|
| 196 | for (int y=0,x=0;y<buffer_size;y++,x++) {
|
|---|
| 197 | /* keep rotating over IV */
|
|---|
| 198 | if (x >= iv_size_)
|
|---|
| 199 | x = 0;
|
|---|
| 200 | buffer[y] ^= transmitted_iv_[x];
|
|---|
| 201 | }
|
|---|
| 202 |
|
|---|
| 203 | /* rotate over password... */
|
|---|
| 204 | for(int y=0,x=0; y < buffer_size; y++,x++) {
|
|---|
| 205 | /* keep rotating over password */
|
|---|
| 206 | if (x >= password_size_)
|
|---|
| 207 | x = 0;
|
|---|
| 208 | buffer[y] ^= password_[x];
|
|---|
| 209 | }
|
|---|
| 210 | return;
|
|---|
| 211 | }
|
|---|
| 212 | void decrypt(unsigned char *buffer, int buffer_size) {
|
|---|
| 213 | throw encryption_exception(_T("Decryption not supported"));
|
|---|
| 214 | }
|
|---|
| 215 | std::wstring getName() {
|
|---|
| 216 | return _T("XOR (not safe)");
|
|---|
| 217 | }
|
|---|
| 218 | };
|
|---|
| 219 |
|
|---|
| 220 | private:
|
|---|
| 221 | any_encryption *core_;
|
|---|
| 222 | public:
|
|---|
| 223 |
|
|---|
| 224 | nsca_encrypt() : core_(NULL) {}
|
|---|
| 225 | ~nsca_encrypt() {
|
|---|
| 226 | delete core_;
|
|---|
| 227 | }
|
|---|
| 228 |
|
|---|
| 229 |
|
|---|
| 230 | static bool hasEncryption(int encryption_method) {
|
|---|
| 231 | switch(encryption_method) {
|
|---|
| 232 | case ENCRYPT_NONE:
|
|---|
| 233 | case ENCRYPT_XOR:
|
|---|
| 234 | #ifdef HAVE_LIBCRYPTOPP
|
|---|
| 235 | case ENCRYPT_DES:
|
|---|
| 236 | case ENCRYPT_3DES:
|
|---|
| 237 | case ENCRYPT_CAST128:
|
|---|
| 238 | case ENCRYPT_XTEA:
|
|---|
| 239 | case ENCRYPT_BLOWFISH:
|
|---|
| 240 | case ENCRYPT_TWOFISH:
|
|---|
| 241 | case ENCRYPT_RC2:
|
|---|
| 242 | case ENCRYPT_RIJNDAEL128:
|
|---|
| 243 | case ENCRYPT_SERPENT:
|
|---|
| 244 | case ENCRYPT_GOST:
|
|---|
| 245 | #endif
|
|---|
| 246 | return true;
|
|---|
| 247 |
|
|---|
| 248 | // UNdefined
|
|---|
| 249 | #ifdef HAVE_LIBCRYPTOPP
|
|---|
| 250 | case ENCRYPT_3WAY:
|
|---|
| 251 | case ENCRYPT_ARCFOUR:
|
|---|
| 252 | case ENCRYPT_CAST256:
|
|---|
| 253 | case ENCRYPT_LOKI97:
|
|---|
| 254 | case ENCRYPT_WAKE:
|
|---|
| 255 | case ENCRYPT_ENIGMA:
|
|---|
| 256 | case ENCRYPT_RIJNDAEL192:
|
|---|
| 257 | case ENCRYPT_RIJNDAEL256:
|
|---|
| 258 | case ENCRYPT_SAFER64:
|
|---|
| 259 | case ENCRYPT_SAFER128:
|
|---|
| 260 | case ENCRYPT_SAFERPLUS:
|
|---|
| 261 | #endif
|
|---|
| 262 | default:
|
|---|
| 263 | return false;
|
|---|
| 264 | }
|
|---|
| 265 | }
|
|---|
| 266 |
|
|---|
| 267 |
|
|---|
| 268 | static any_encryption* get_encryption_core(int encryption_method) {
|
|---|
| 269 | switch(encryption_method) {
|
|---|
| 270 | case ENCRYPT_NONE:
|
|---|
| 271 | return new no_encryption();
|
|---|
| 272 | case ENCRYPT_XOR:
|
|---|
| 273 | return new xor_encryption();
|
|---|
| 274 | #ifdef HAVE_LIBCRYPTOPP
|
|---|
| 275 | case ENCRYPT_DES:
|
|---|
| 276 | return new cryptopp_encryption<CryptoPP::DES>();
|
|---|
| 277 | case ENCRYPT_3DES:
|
|---|
| 278 | return new cryptopp_encryption<CryptoPP::DES_EDE3>();
|
|---|
| 279 | case ENCRYPT_CAST128:
|
|---|
| 280 | return new cryptopp_encryption<CryptoPP::CAST128>();
|
|---|
| 281 | case ENCRYPT_XTEA:
|
|---|
| 282 | return new cryptopp_encryption<CryptoPP::XTEA>();
|
|---|
| 283 | case ENCRYPT_3WAY:
|
|---|
| 284 | return new cryptopp_encryption<CryptoPP::ThreeWay>();
|
|---|
| 285 | case ENCRYPT_BLOWFISH:
|
|---|
| 286 | return new cryptopp_encryption<CryptoPP::Blowfish>(56);
|
|---|
| 287 | case ENCRYPT_TWOFISH:
|
|---|
| 288 | return new cryptopp_encryption<CryptoPP::Twofish>(32);
|
|---|
| 289 | case ENCRYPT_RC2:
|
|---|
| 290 | return new cryptopp_encryption<CryptoPP::RC2>(128);
|
|---|
| 291 | case ENCRYPT_RIJNDAEL128:
|
|---|
| 292 | return new cryptopp_encryption<CryptoPP::AES>(32);
|
|---|
| 293 | case ENCRYPT_SERPENT:
|
|---|
| 294 | return new cryptopp_encryption<CryptoPP::Serpent>(32);
|
|---|
| 295 | case ENCRYPT_GOST:
|
|---|
| 296 | return new cryptopp_encryption<CryptoPP::GOST>();
|
|---|
| 297 | #endif
|
|---|
| 298 | default:
|
|---|
| 299 | return NULL;
|
|---|
| 300 | }
|
|---|
| 301 | }
|
|---|
| 302 | static void generate_transmitted_iv(unsigned char *transmitted_iv){
|
|---|
| 303 | int x;
|
|---|
| 304 | int seed=0;
|
|---|
| 305 |
|
|---|
| 306 | /*********************************************************/
|
|---|
| 307 | /* fill IV buffer with data that's as random as possible */
|
|---|
| 308 | /*********************************************************/
|
|---|
| 309 |
|
|---|
| 310 | /* else fall back to using the current time as the seed */
|
|---|
| 311 | seed=(int)time(NULL);
|
|---|
| 312 |
|
|---|
| 313 | /* generate pseudo-random IV */
|
|---|
| 314 | srand(seed);
|
|---|
| 315 | for(x=0;x<TRANSMITTED_IV_SIZE;x++)
|
|---|
| 316 | transmitted_iv[x]=(int)((256.0*rand())/(RAND_MAX+1.0));
|
|---|
| 317 |
|
|---|
| 318 | return;
|
|---|
| 319 | }
|
|---|
| 320 |
|
|---|
| 321 | /* initializes encryption routines */
|
|---|
| 322 | void encrypt_init(std::string password, int encryption_method, unsigned char *received_iv){
|
|---|
| 323 | delete core_;
|
|---|
| 324 | core_ = get_encryption_core(encryption_method);
|
|---|
| 325 | if (core_ == NULL)
|
|---|
| 326 | throw encryption_exception(_T("Failed to get encryption core!"));
|
|---|
| 327 |
|
|---|
| 328 | /* server generates IV used for encryption */
|
|---|
| 329 | if (received_iv==NULL) {
|
|---|
| 330 | unsigned char generated_iv[TRANSMITTED_IV_SIZE];
|
|---|
| 331 | generate_transmitted_iv(generated_iv);
|
|---|
| 332 | core_->init(password, generated_iv, TRANSMITTED_IV_SIZE);
|
|---|
| 333 | } else /* client receives IV from server */
|
|---|
| 334 | core_->init(password, received_iv, TRANSMITTED_IV_SIZE);
|
|---|
| 335 | }
|
|---|
| 336 |
|
|---|
| 337 | /* encrypt a buffer */
|
|---|
| 338 | void encrypt_buffer(unsigned char *buffer,int buffer_size) {
|
|---|
| 339 | if (core_ == NULL)
|
|---|
| 340 | throw encryption_exception(_T("No encryption core!"));
|
|---|
| 341 | core_->encrypt(buffer, buffer_size);
|
|---|
| 342 | }
|
|---|
| 343 | unsigned char* get_rand_buffer(int length) {
|
|---|
| 344 | unsigned char * buffer = new unsigned char[length+1];
|
|---|
| 345 | #if HAVE_LIBCRYPTOPP
|
|---|
| 346 | CryptoPP::AutoSeededRandomPool rng;
|
|---|
| 347 | rng.GenerateBlock(buffer, length);
|
|---|
| 348 | #endif
|
|---|
| 349 | return buffer;
|
|---|
| 350 | }
|
|---|
| 351 | void destroy_random_buffer(unsigned char* buffer) {
|
|---|
| 352 | delete [] buffer;
|
|---|
| 353 | }
|
|---|
| 354 |
|
|---|
| 355 | }; |
|---|