source: nscp/trunk/modules/NSCAAgent/nsca_enrypt.hpp @ cdddecc

Last change on this file since cdddecc was cdddecc, checked in by Michael Medin <michael@…>, 5 years ago

+ Added encryption subsystem to NSCA module (still no mcrypt support, but atleast you have "xor" and passwords)

  • Property mode set to 100644
File size: 9.1 KB
Line 
1
2#define TRANSMITTED_IV_SIZE     128     /* size of IV to transmit - must be as big as largest IV needed for any crypto algorithm */
3
4/********************* ENCRYPTION TYPES ****************/
5
6#define ENCRYPT_NONE            0       /* no encryption */
7#define ENCRYPT_XOR             1       /* not really encrypted, just obfuscated */
8
9#ifdef HAVE_LIBMCRYPT
10#define ENCRYPT_DES             2       /* DES */
11#define ENCRYPT_3DES            3       /* 3DES or Triple DES */
12#define ENCRYPT_CAST128         4       /* CAST-128 */
13#define ENCRYPT_CAST256         5       /* CAST-256 */
14#define ENCRYPT_XTEA            6       /* xTEA */
15#define ENCRYPT_3WAY            7       /* 3-WAY */
16#define ENCRYPT_BLOWFISH        8       /* SKIPJACK */
17#define ENCRYPT_TWOFISH         9       /* TWOFISH */
18#define ENCRYPT_LOKI97          10      /* LOKI97 */
19#define ENCRYPT_RC2             11      /* RC2 */
20#define ENCRYPT_ARCFOUR         12      /* RC4 */
21#define ENCRYPT_RC6             13      /* RC6 */            /* UNUSED */
22#define ENCRYPT_RIJNDAEL128     14      /* RIJNDAEL-128 */
23#define ENCRYPT_RIJNDAEL192     15      /* RIJNDAEL-192 */
24#define ENCRYPT_RIJNDAEL256     16      /* RIJNDAEL-256 */
25#define ENCRYPT_MARS            17      /* MARS */           /* UNUSED */
26#define ENCRYPT_PANAMA          18      /* PANAMA */         /* UNUSED */
27#define ENCRYPT_WAKE            19      /* WAKE */
28#define ENCRYPT_SERPENT         20      /* SERPENT */
29#define ENCRYPT_IDEA            21      /* IDEA */           /* UNUSED */
30#define ENCRYPT_ENIGMA          22      /* ENIGMA (Unix crypt) */
31#define ENCRYPT_GOST            23      /* GOST */
32#define ENCRYPT_SAFER64         24      /* SAFER-sk64 */
33#define ENCRYPT_SAFER128        25      /* SAFER-sk128 */
34#define ENCRYPT_SAFERPLUS       26      /* SAFER+ */
35#endif
36
37
38class nsca_encrypt {
39private:
40        char transmitted_iv_[TRANSMITTED_IV_SIZE];
41        bool isInialized_;
42        std::string password_;
43        int encryption_method_;
44#ifdef HAVE_LIBMCRYPT
45        MCRYPT td_;
46        char *key_;
47        char *IV_;
48        char block_buffer_;
49        int blocksize_;
50        int keysize_;
51        std::string mcrypt_algorithm_;
52        std::string mcrypt_mode_;
53#endif
54public:
55        class exception {
56                std::wstring error_;
57        public:
58                exception(std::wstring error) : error_(error) {}
59                std::wstring getMessage() const { return error_; }
60
61        };
62
63        nsca_encrypt() : isInialized_(false)
64#ifdef HAVE_LIBMCRYPT
65                , key_(NULL), IV_(NULL)
66#endif
67        {}
68        ~nsca_encrypt() {
69#ifdef HAVE_LIBMCRYPT
70                /* mcrypt cleanup */
71                if(encryption_method!=ENCRYPT_NONE && encryption_method!=ENCRYPT_XOR){
72                        mcrypt_generic_end(td);
73                        delete [] key;
74                        key=NULL;
75                        delete [] IV;
76                        IV=NULL;
77                }
78#endif
79        }
80
81
82        static bool hasEncryption(int encryption_method) {
83                switch(encryption_method) {
84                        case ENCRYPT_NONE:
85                        case ENCRYPT_XOR:
86#ifdef HAVE_LIBMCRYPT
87                        case ENCRYPT_DES:
88                        case ENCRYPT_3DES:
89                        case ENCRYPT_CAST128:
90                        case ENCRYPT_CAST256:
91                        case ENCRYPT_XTEA:
92                        case ENCRYPT_3WAY:
93                        case ENCRYPT_BLOWFISH:
94                        case ENCRYPT_TWOFISH:
95                        case ENCRYPT_LOKI97:
96                        case ENCRYPT_RC2:
97                        case ENCRYPT_ARCFOUR:
98                        case ENCRYPT_RIJNDAEL128:
99                        case ENCRYPT_RIJNDAEL192:
100                        case ENCRYPT_RIJNDAEL256:
101                        case ENCRYPT_WAKE:
102                        case ENCRYPT_SERPENT:
103                        case ENCRYPT_ENIGMA:
104                        case ENCRYPT_GOST:
105                        case ENCRYPT_SAFER64:
106                        case ENCRYPT_SAFER128:
107                        case ENCRYPT_SAFERPLUS:
108#endif
109                                return true;
110                        default:
111                                return false;
112                }
113        }
114
115        static void generate_transmitted_iv(char *transmitted_iv){
116                int x;
117                int seed=0;
118
119                /*********************************************************/
120                /* fill IV buffer with data that's as random as possible */
121                /*********************************************************/
122
123                /* else fallback to using the current time as the seed */
124                seed=(int)time(NULL);
125
126                /* generate pseudo-random IV */
127                srand(seed);
128                for(x=0;x<TRANSMITTED_IV_SIZE;x++)
129                        transmitted_iv[x]=(int)((256.0*rand())/(RAND_MAX+1.0));
130
131                return;
132        }
133
134
135
136        /* initializes encryption routines */
137        void encrypt_init(std::string password, int encryption_method, char *received_iv){
138#ifdef HAVE_LIBMCRYPT
139                int i;
140                int iv_size;
141#endif
142                if (isInialized_)
143                        throw exception(_T("already iniatilized!"));
144                encryption_method_ = encryption_method;
145                password_ = password;
146                isInialized_ = true;
147
148                /* server generates IV used for encryption */
149                if(received_iv==NULL)
150                        generate_transmitted_iv(transmitted_iv_);
151
152                /* client receives IV from server */
153                else
154                        memcpy(transmitted_iv_,received_iv,TRANSMITTED_IV_SIZE);
155
156#ifdef HAVE_LIBMCRYPT
157                blocksize=1;                        /* block size = 1 byte w/ CFB mode */
158                keysize=7;                          /* default to 56 bit key length */
159                mcrypt_mode="cfb";                  /* CFB = 8-bit cipher-feedback mode */
160                mcrypt_algorithm="unknown";
161#endif
162
163
164
165                /* get the name of the mcrypt encryption algorithm to use */
166                switch(encryption_method){
167                /* no encryption */
168                case ENCRYPT_NONE:
169                        return;
170                        /* XOR or no encryption */
171                case ENCRYPT_XOR:
172                        return;
173#ifdef HAVE_LIBMCRYPT
174                case ENCRYPT_DES:
175                        mcrypt_algorithm=MCRYPT_DES;
176                        break;
177                case ENCRYPT_3DES:
178                        mcrypt_algorithm=MCRYPT_3DES;
179                        break;
180                case ENCRYPT_CAST128:
181                        mcrypt_algorithm=MCRYPT_CAST_128;
182                        break;
183                case ENCRYPT_CAST256:
184                        mcrypt_algorithm=MCRYPT_CAST_256;
185                        break;
186                case ENCRYPT_XTEA:
187                        mcrypt_algorithm=MCRYPT_XTEA;
188                        break;
189                case ENCRYPT_3WAY:
190                        mcrypt_algorithm=MCRYPT_3WAY;
191                        break;
192                case ENCRYPT_BLOWFISH:
193                        mcrypt_algorithm=MCRYPT_BLOWFISH;
194                        break;
195                case ENCRYPT_TWOFISH:
196                        mcrypt_algorithm=MCRYPT_TWOFISH;
197                        break;
198                case ENCRYPT_LOKI97:
199                        mcrypt_algorithm=MCRYPT_LOKI97;
200                        break;
201                case ENCRYPT_RC2:
202                        mcrypt_algorithm=MCRYPT_RC2;
203                        break;
204                case ENCRYPT_ARCFOUR:
205                        mcrypt_algorithm=MCRYPT_ARCFOUR;
206                        break;
207                case ENCRYPT_RIJNDAEL128:
208                        mcrypt_algorithm=MCRYPT_RIJNDAEL_128;
209                        break;
210                case ENCRYPT_RIJNDAEL192:
211                        mcrypt_algorithm=MCRYPT_RIJNDAEL_192;
212                        break;
213                case ENCRYPT_RIJNDAEL256:
214                        mcrypt_algorithm=MCRYPT_RIJNDAEL_256;
215                        break;
216                case ENCRYPT_WAKE:
217                        mcrypt_algorithm=MCRYPT_WAKE;
218                        break;
219                case ENCRYPT_SERPENT:
220                        mcrypt_algorithm=MCRYPT_SERPENT;
221                        break;
222                case ENCRYPT_ENIGMA:
223                        mcrypt_algorithm=MCRYPT_ENIGMA;
224                        break;
225                case ENCRYPT_GOST:
226                        mcrypt_algorithm=MCRYPT_GOST;
227                        break;
228                case ENCRYPT_SAFER64:
229                        mcrypt_algorithm=MCRYPT_SAFER_SK64;
230                        break;
231                case ENCRYPT_SAFER128:
232                        mcrypt_algorithm=MCRYPT_SAFER_SK128;
233                        break;
234                case ENCRYPT_SAFERPLUS:
235                        mcrypt_algorithm=MCRYPT_SAFERPLUS;
236                        break;
237#endif
238                default:
239                        throw exception(_T("Invalid encryption algorithm!"));
240                }
241
242#ifdef HAVE_LIBMCRYPT
243                /* open encryption module */
244                if((td=mcrypt_module_open(mcrypt_algorithm,NULL,mcrypt_mode,NULL))==MCRYPT_FAILED){
245                        throw exception(_T("Could not open mcrypt algorithm '") + mcrypt_algorithm + _T("' with mode '") + mcrypt_mode + _T("'"));
246                }
247
248                /* determine size of IV buffer for this algorithm */
249                iv_size=mcrypt_enc_get_iv_size(td);
250                if(iv_size>TRANSMITTED_IV_SIZE){
251                        throw exception(_T("IV size for crypto algorithm exceeds limits"));
252                }
253
254                /* allocate memory for IV buffer */
255                if((IV=new char[iv_size])==NULL){
256                        throw exception(_T("Could not allocate memory for IV buffer"));
257                }
258
259                /* fill IV buffer with first bytes of IV that is going to be used to crypt (determined by server) */
260                for(i=0;i<iv_size;i++)
261                        IV[i]=transmitted_iv[i];
262
263                /* get maximum key size for this algorithm */
264                keysize=mcrypt_enc_get_key_size(td);
265
266                /* generate an encryption/decription key using the password */
267                if((key=new char[keysize])==NULL){
268                        throw exception(_T("Could not allocate memory for encryption/decryption key"));
269                        return ERROR;
270                }
271                ZeroMemory(key,keysize);
272
273                if(keysize<password.length())
274                        strncpy(key,password.c_str(),keysize);
275                else
276                        strncpy(key,password.c_str(),password.length());
277
278                /* initialize encryption buffers */
279                mcrypt_generic_init(td,key,keysize,IV);
280#endif
281        }
282
283        /* encrypt a buffer */
284        void encrypt_buffer(char *buffer,int buffer_size){
285                int x;
286                int y;
287                int password_length;
288
289                /* no crypt instance */
290                if (!isInialized_)
291                        throw new exception(_T("Not initialized!"));
292
293                /* no encryption */
294                if(encryption_method_==ENCRYPT_NONE)
295                        return;
296
297                /* simple XOR "encryption" - not meant for any real security, just obfuscates data, but its fast... */
298                else if(encryption_method_==ENCRYPT_XOR){
299
300                        /* rotate over IV we received from the server... */
301                        for(y=0,x=0;y<buffer_size;y++,x++){
302
303                                /* keep rotating over IV */
304                                if(x>=TRANSMITTED_IV_SIZE)
305                                        x=0;
306
307                                buffer[y]^=transmitted_iv_[x];
308                        }
309
310                        /* rotate over password... */
311                        password_length=password_.length();
312                        for(y=0,x=0;y<buffer_size;y++,x++){
313                                /* keep rotating over password */
314                                if(x>=password_length)
315                                        x=0;
316                                buffer[y]^=password_[x];
317                        }
318                        return;
319                }
320
321#ifdef HAVE_LIBMCRYPT
322                /* use mcrypt routines */
323                else{
324                        /* encrypt each byte of buffer, one byte at a time (CFB mode) */
325                        for(x=0;x<buffer_size;x++)
326                                mcrypt_generic(td,&buffer[x],1);
327                }
328#endif
329                return;
330        }
331
332};
Note: See TracBrowser for help on using the repository browser.