1 /*
2  * Copyright (C) 1998,1999,2000,2001 Nikos Mavroyanopoulos
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Library General Public License as published
6  * by the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #include <libdefs.h>
21 #include <mcrypt_modules.h>
22 
23 #define _init_mcrypt ncfb_LTX__init_mcrypt
24 #define _mcrypt_set_state ncfb_LTX__mcrypt_set_state
25 #define _mcrypt_get_state ncfb_LTX__mcrypt_get_state
26 #define _end_mcrypt ncfb_LTX__end_mcrypt
27 #define _mcrypt ncfb_LTX__mcrypt
28 #define _mdecrypt ncfb_LTX__mdecrypt
29 #define _has_iv ncfb_LTX__has_iv
30 #define _is_block_mode ncfb_LTX__is_block_mode
31 #define _is_block_algorithm_mode ncfb_LTX__is_block_algorithm_mode
32 #define _mcrypt_get_modes_name ncfb_LTX__mcrypt_get_modes_name
33 #define _mcrypt_mode_get_size ncfb_LTX__mcrypt_mode_get_size
34 #define _mcrypt_mode_version ncfb_LTX__mcrypt_mode_version
35 
36 typedef struct ncfb_buf {
37 	byte*   enc_s_register;
38 	byte* s_register;
39 	int   s_register_pos;
40 	int   blocksize;
41 } nCFB_BUFFER;
42 
43 /* nCFB MODE */
44 
_init_mcrypt(nCFB_BUFFER * buf,void * key,int lenofkey,void * IV,int size)45 int _init_mcrypt( nCFB_BUFFER* buf, void *key, int lenofkey, void *IV, int size)
46 {
47     buf->enc_s_register = buf->s_register = NULL;
48     buf->s_register_pos = 0;
49 
50     buf->blocksize = size;
51 
52 /* For cfb */
53 	buf->enc_s_register=malloc( size);
54     if (buf->enc_s_register==NULL) goto freeall;
55 
56 	buf->s_register=malloc( size);
57     if (buf->s_register==NULL) goto freeall;
58 
59 	if (IV!=NULL) {
60 		memcpy(buf->enc_s_register, IV, size);
61 		memcpy(buf->s_register, IV, size);
62 	} else {
63 		memset(buf->enc_s_register, 0, size);
64 		memset(buf->s_register, 0, size);
65 	}
66 
67 /* End ncfb */
68 
69 	return 0;
70 	freeall:
71 		free(buf->enc_s_register);
72 		free(buf->s_register);
73 		return -1;
74 }
75 
_mcrypt_set_state(nCFB_BUFFER * buf,byte * IV,int size)76 int _mcrypt_set_state( nCFB_BUFFER* buf, byte *IV, int size)
77 {
78 	buf->s_register_pos = IV[0];
79 	memcpy(buf->enc_s_register, &IV[1], size-1);
80 	memcpy(buf->s_register, &IV[1], size-1);
81 
82 	return 0;
83 }
84 
_mcrypt_get_state(nCFB_BUFFER * buf,byte * IV,int * size)85 int _mcrypt_get_state( nCFB_BUFFER* buf, byte *IV, int *size)
86 {
87 	if (*size < buf->blocksize + 1) {
88 		*size = buf->blocksize + 1;
89 		return -1;
90 	}
91 	*size = buf->blocksize + 1;
92 
93 	IV[0] = buf->s_register_pos;
94 	memcpy( &IV[1], buf->s_register, buf->blocksize);
95 
96 	return 0;
97 }
98 
_end_mcrypt(nCFB_BUFFER * buf)99 void _end_mcrypt( nCFB_BUFFER* buf) {
100 	free(buf->enc_s_register);
101 	free(buf->s_register);
102 }
103 
104 inline static
xor_stuff_en(nCFB_BUFFER * buf,void * akey,void (* func)(void *,void *),byte * plain,int blocksize,int xor_size)105 void xor_stuff_en( nCFB_BUFFER *buf, void* akey, void (*func)(void*,void*), byte* plain,  int blocksize, int xor_size)
106 {
107 	void (*_mcrypt_block_encrypt) (void *, void *);
108 
109 	_mcrypt_block_encrypt = func;
110 
111 	if (xor_size == blocksize) {
112 		if (buf->s_register_pos == 0) {
113 
114 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
115 
116 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
117 
118 			memxor( plain, buf->enc_s_register, blocksize);
119 
120 			memcpy(buf->s_register, plain, blocksize);
121 
122 		} else {
123 			int size = blocksize - buf->s_register_pos;
124 
125 			memxor( plain, &buf->enc_s_register[buf->s_register_pos],
126 				size);
127 
128 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
129 
130 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
131 
132 			memxor( &plain[size], buf->enc_s_register,
133 				buf->s_register_pos);
134 
135 			memcpy( &buf->s_register[size],
136 				plain, buf->s_register_pos);
137 
138 			/* buf->s_register_pos remains the same */
139 		}
140 	} else { /* xor_size != blocksize */
141 		if (buf->s_register_pos == 0) {
142 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
143 
144 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
145 
146 			memxor( plain, buf->enc_s_register, xor_size);
147 
148 			memcpy(buf->s_register, plain, xor_size);
149 
150 			buf->s_register_pos = xor_size;
151 		} else {
152 			int size = blocksize - buf->s_register_pos;
153 			int min_size =  size < xor_size ? size: xor_size;
154 
155 			memxor( plain, &buf->enc_s_register[buf->s_register_pos],
156 				min_size);
157 
158 			memcpy( &buf->s_register[buf->s_register_pos], plain, min_size);
159 
160 			buf->s_register_pos += min_size;
161 
162 			if (min_size >= xor_size)
163 				return;
164 
165 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
166 
167 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
168 
169 			memxor( &plain[min_size], buf->s_register,
170 				xor_size - min_size);
171 
172 			buf->s_register_pos = xor_size - min_size;
173 
174 			memcpy(buf->s_register, plain, xor_size - min_size);
175 		}
176 
177 	}
178 	return;
179 }
180 
181 inline static
xor_stuff_de(nCFB_BUFFER * buf,void * akey,void (* func)(void *,void *),byte * cipher,int blocksize,int xor_size)182 void xor_stuff_de( nCFB_BUFFER *buf, void* akey, void (*func)(void*,void*), byte* cipher,  int blocksize, int xor_size)
183 {
184 	void (*_mcrypt_block_encrypt) (void *, void *);
185 
186 	_mcrypt_block_encrypt = func;
187 
188 	if (xor_size == blocksize) {
189 		if (buf->s_register_pos == 0) {
190 
191 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
192 
193 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
194 
195 			memcpy(buf->s_register, cipher, blocksize);
196 
197 			memxor( cipher, buf->enc_s_register, blocksize);
198 
199 
200 		} else {
201 			int size = blocksize - buf->s_register_pos;
202 
203 			memxor( cipher, &buf->enc_s_register[buf->s_register_pos],
204 				size);
205 
206 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
207 
208 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
209 
210 			memcpy( &buf->s_register[size],
211 				cipher, buf->s_register_pos);
212 
213 			memxor( &cipher[size], buf->enc_s_register,
214 				buf->s_register_pos);
215 
216 
217 			/* buf->s_register_pos remains the same */
218 		}
219 	} else { /* xor_size != blocksize */
220 		if (buf->s_register_pos == 0) {
221 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
222 
223 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
224 
225 			memcpy(buf->s_register, cipher, xor_size);
226 
227 			memxor( cipher, buf->enc_s_register, xor_size);
228 
229 
230 			buf->s_register_pos = xor_size;
231 		} else {
232 			int size = blocksize - buf->s_register_pos;
233 			int min_size =  size < xor_size ? size: xor_size;
234 
235 			memxor( cipher, &buf->enc_s_register[buf->s_register_pos],
236 				min_size);
237 
238 			memcpy( &buf->s_register[buf->s_register_pos], cipher, min_size);
239 
240 			buf->s_register_pos += min_size;
241 
242 			if (min_size >= xor_size)
243 				return;
244 
245 			memcpy(buf->enc_s_register, buf->s_register, blocksize);
246 
247 			_mcrypt_block_encrypt(akey, buf->enc_s_register);
248 
249 			memcpy(buf->s_register, cipher, xor_size - min_size);
250 
251 			memxor( &cipher[min_size], buf->s_register,
252 				xor_size - min_size);
253 
254 			buf->s_register_pos = xor_size - min_size;
255 
256 		}
257 
258 	}
259 	return;
260 }
261 
262 
_mcrypt(nCFB_BUFFER * buf,void * plaintext,int len,int blocksize,void * akey,void (* func)(void *,void *),void (* func2)(void *,void *))263 int _mcrypt( nCFB_BUFFER* buf,void *plaintext, int len, int blocksize, void* akey, void (*func)(void*,void*), void (*func2)(void*,void*))
264 {				/* plaintext is n*blocksize bytes (nbit cfb) */
265 	byte* plain;
266 	int i, j=0;
267 	void (*_mcrypt_block_encrypt) (void *, void *);
268 	int modlen;
269 
270 	_mcrypt_block_encrypt = func;
271 
272 	plain = plaintext;
273 	for (j = 0; j < len / blocksize; j++) {
274 		xor_stuff_en( buf, akey, func, plain, blocksize, blocksize);
275 
276 		plain += blocksize;
277 
278 	}
279 	modlen = len % blocksize;
280 	if (modlen > 0) {
281 		xor_stuff_en( buf, akey, func, plain, blocksize, modlen);
282 	}
283 
284 	return 0;
285 }
286 
287 
_mdecrypt(nCFB_BUFFER * buf,void * plaintext,int len,int blocksize,void * akey,void (* func)(void *,void *),void (* func2)(void *,void *))288 int _mdecrypt( nCFB_BUFFER* buf,void *plaintext, int len, int blocksize, void* akey, void (*func)(void*,void*), void (*func2)(void*,void*))
289 {				/* plaintext is n*blocksize bytes (nbit cfb) */
290 	byte* plain;
291 	int i, j=0;
292 	void (*_mcrypt_block_encrypt) (void *, void *);
293 	int modlen;
294 
295 	_mcrypt_block_encrypt = func;
296 
297 	plain = plaintext;
298 	for (j = 0; j < len / blocksize; j++) {
299 		xor_stuff_de( buf, akey, func, plain, blocksize, blocksize);
300 
301 		plain += blocksize;
302 
303 	}
304 	modlen = len % blocksize;
305 	if (modlen > 0) {
306 		xor_stuff_de( buf, akey, func, plain, blocksize, modlen);
307 	}
308 
309 	return 0;
310 }
311 
312 
_has_iv()313 int _has_iv() { return 1; }
_is_block_mode()314 int _is_block_mode() { return 0; }
_is_block_algorithm_mode()315 int _is_block_algorithm_mode() { return 1; }
_mcrypt_get_modes_name()316 const char *_mcrypt_get_modes_name() { return "nCFB";}
_mcrypt_mode_get_size()317 int _mcrypt_mode_get_size () {return sizeof(nCFB_BUFFER);}
318 
319 
_mcrypt_mode_version()320 word32 _mcrypt_mode_version() {
321 	return 20020307;
322 }
323 
324 #ifdef WIN32
325 # ifdef USE_LTDL
main(void)326 WIN32DLL_DEFINE int main (void)
327 {
328        /* empty main function to avoid linker error (see cygwin FAQ) */
329 }
330 # endif
331 #endif
332