Added properly working CBC mode implementation to AES.
[crypto.git] / lib / silccrypt / ciphers_def.h
1 /*
2
3   ciphers_def.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1999 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #ifndef CIPHERS_DEF_H
21 #define CIPHERS_DEF_H
22
23
24 #include "silclog.h"
25
26 /* General definitions for algorithms */
27 typedef unsigned char u1byte;
28 typedef SilcUInt32 u4byte;
29 typedef SilcUInt32 u32;
30 typedef SilcUInt32 uint_32t;
31 typedef SilcUInt8 uint_8t;
32
33 #define rotr(x, nr) silc_ror(x, nr)
34 #define rotl(x, nr) silc_rol(x, nr)
35 #define byte(x, nr) ((x) >> (nr * 8) & 255)
36
37 /* Byte key to words */
38 #define SILC_GET_WORD_KEY(s, d, len)            \
39 do {                                            \
40   int _i;                                       \
41   for (_i = 0; _i < (len / 8) / 4; _i++)        \
42     SILC_GET32_LSB(d[_i], s + (_i * 4));        \
43 } while(0);
44
45 /* CBC mode 128-bit block, LSB, 8-bit iv argument must be encrypted */
46
47 #ifndef WORDS_BIGENDIAN
48 #ifdef SILC_X86_64
49 /* x86-64 */
50 #define SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i, enc)               \
51 do {                                                                    \
52   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
53   if (len & (16 - 1))                                                   \
54     return FALSE;                                                       \
55                                                                         \
56   for (i = 0; i < len; i += 16) {                                       \
57     *(SilcUInt64 *)iv ^= *(SilcUInt64 *)src;                            \
58     *(SilcUInt64 *)(iv + 8) ^= *(SilcUInt64 *)(src + 8);                \
59                                                                         \
60     enc;                                                                \
61                                                                         \
62     *(SilcUInt64 *)dst = *(SilcUInt64 *)iv;                             \
63     *(SilcUInt64 *)(dst + 8) = *(SilcUInt64 *)(iv + 8);                 \
64                                                                         \
65     dst += 16;                                                          \
66     src += 16;                                                          \
67   }                                                                     \
68 } while(0)
69 #else /* !SILC_X86_64 */
70 /* x86 */
71 #define SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i, enc)               \
72 do {                                                                    \
73   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
74   if (len & (16 - 1))                                                   \
75     return FALSE;                                                       \
76                                                                         \
77   for (i = 0; i < len; i += 16) {                                       \
78     *(SilcUInt32 *)iv ^= *(SilcUInt32 *)src;                            \
79     *(SilcUInt32 *)(iv + 4) ^= *(SilcUInt32 *)(src + 4);                \
80     *(SilcUInt32 *)(iv + 8) ^= *(SilcUInt32 *)(src + 8);                \
81     *(SilcUInt32 *)(iv + 12) ^= *(SilcUInt32 *)(src + 12);              \
82                                                                         \
83     enc;                                                                \
84                                                                         \
85     memcpy(dst, iv, 16);                                                \
86     dst += 16;                                                          \
87     src += 16;                                                          \
88   }                                                                     \
89 } while(0)
90 #endif /* SILC_X86_64 */
91 #else /* WORDS_BIGENDIAN */
92 /* big-endian machines */
93 #define SILC_CBC_ENC_MSB_128_8(len, iv, src, dst, i, enc)               \
94 do {                                                                    \
95   SilcUInt32 tmp[4], tmp2[4];                                           \
96                                                                         \
97   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
98   if (len & (16 - 1))                                                   \
99     return FALSE;                                                       \
100                                                                         \
101   for (i = 0; i < len; i += 16) {                                       \
102     SILC_GET32_MSB(tmp[0], &iv[0]);                                     \
103     SILC_GET32_MSB(tmp[1], &iv[4]);                                     \
104     SILC_GET32_MSB(tmp[2], &iv[8]);                                     \
105     SILC_GET32_MSB(tmp[3], &iv[12]);                                    \
106                                                                         \
107     SILC_GET32_MSB(tmp2[0], &src[0]);                                   \
108     SILC_GET32_MSB(tmp2[1], &src[4]);                                   \
109     SILC_GET32_MSB(tmp2[2], &src[8]);                                   \
110     SILC_GET32_MSB(tmp2[3], &src[12]);                                  \
111                                                                         \
112     tmp[0] = tmp[0] ^ tmp2[0];                                          \
113     tmp[1] = tmp[1] ^ tmp2[1];                                          \
114     tmp[2] = tmp[2] ^ tmp2[2];                                          \
115     tmp[3] = tmp[3] ^ tmp2[3];                                          \
116                                                                         \
117     SILC_PUT32_MSB(tmp[0], &iv[0]);                                     \
118     SILC_PUT32_MSB(tmp[1], &iv[4]);                                     \
119     SILC_PUT32_MSB(tmp[2], &iv[8]);                                     \
120     SILC_PUT32_MSB(tmp[3], &iv[12]);                                    \
121                                                                         \
122     enc;                                                                \
123                                                                         \
124     memcpy(dst, iv, 16);                                                \
125     dst += 16;                                                          \
126     src += 16;                                                          \
127   }                                                                     \
128 } while(0)
129 #endif /* !WORDS_BIGENDIAN */
130
131 /* CBC mode 128-bit block, MSB, 32-bit block argument must be encrypted */
132
133 #define SILC_CBC_ENC_LSB_128_32(len, iv, block, src, dst, i, enc)       \
134 do {                                                                    \
135   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
136   if (len & (16 - 1))                                                   \
137     return FALSE;                                                       \
138                                                                         \
139   SILC_GET32_LSB(block[0], &iv[0]);                                     \
140   SILC_GET32_LSB(block[1], &iv[4]);                                     \
141   SILC_GET32_LSB(block[2], &iv[8]);                                     \
142   SILC_GET32_LSB(block[3], &iv[12]);                                    \
143                                                                         \
144   for (i = 0; i < len; i += 16) {                                       \
145     SILC_GET32_X_LSB(block[0], &src[0]);                                \
146     SILC_GET32_X_LSB(block[1], &src[4]);                                \
147     SILC_GET32_X_LSB(block[2], &src[8]);                                \
148     SILC_GET32_X_LSB(block[3], &src[12]);                               \
149                                                                         \
150     enc;                                                                \
151                                                                         \
152     SILC_PUT32_LSB(block[0], &dst[0]);                                  \
153     SILC_PUT32_LSB(block[1], &dst[4]);                                  \
154     SILC_PUT32_LSB(block[2], &dst[8]);                                  \
155     SILC_PUT32_LSB(block[3], &dst[12]);                                 \
156                                                                         \
157     dst += 16;                                                          \
158     src += 16;                                                          \
159   }                                                                     \
160                                                                         \
161   SILC_PUT32_LSB(block[0], &iv[0]);                                     \
162   SILC_PUT32_LSB(block[1], &iv[4]);                                     \
163   SILC_PUT32_LSB(block[2], &iv[8]);                                     \
164   SILC_PUT32_LSB(block[3], &iv[12]);                                    \
165 } while(0)
166
167 /* CBC mode 128-bit block, LSB, decrypt block to block_dec. */
168
169 #define SILC_CBC_DEC_LSB_128_32(len, iv, block_prev, block,             \
170                                 block_dec, src, dst, i, dec)            \
171 do {                                                                    \
172   if (!len || len & (16 - 1))                                           \
173     return FALSE;                                                       \
174                                                                         \
175   SILC_GET32_LSB(block_prev[0], &iv[0]);                                \
176   SILC_GET32_LSB(block_prev[1], &iv[4]);                                \
177   SILC_GET32_LSB(block_prev[2], &iv[8]);                                \
178   SILC_GET32_LSB(block_prev[3], &iv[12]);                               \
179                                                                         \
180   for (i = 0; i < len; i += 16) {                                       \
181     SILC_GET32_LSB(block[0], &src[0]);                                  \
182     SILC_GET32_LSB(block[1], &src[4]);                                  \
183     SILC_GET32_LSB(block[2], &src[8]);                                  \
184     SILC_GET32_LSB(block[3], &src[12]);                                 \
185                                                                         \
186     dec;                                                                \
187                                                                         \
188     block_dec[0] ^= block_prev[0];                                      \
189     block_dec[1] ^= block_prev[1];                                      \
190     block_dec[2] ^= block_prev[2];                                      \
191     block_dec[3] ^= block_prev[3];                                      \
192                                                                         \
193     SILC_PUT32_LSB(block_dec[0], &dst[0]);                              \
194     SILC_PUT32_LSB(block_dec[1], &dst[4]);                              \
195     SILC_PUT32_LSB(block_dec[2], &dst[8]);                              \
196     SILC_PUT32_LSB(block_dec[3], &dst[12]);                             \
197                                                                         \
198     block_prev[0] = block[0];                                           \
199     block_prev[1] = block[1];                                           \
200     block_prev[2] = block[2];                                           \
201     block_prev[3] = block[3];                                           \
202                                                                         \
203     dst += 16;                                                          \
204     src += 16;                                                          \
205   }                                                                     \
206                                                                         \
207   SILC_PUT32_LSB(block[0], &iv[0]);                                     \
208   SILC_PUT32_LSB(block[1], &iv[4]);                                     \
209   SILC_PUT32_LSB(block[2], &iv[8]);                                     \
210   SILC_PUT32_LSB(block[3], &iv[12]);                                    \
211 } while(0)
212
213 /* CBC mode 128-bit block, MSB, 32-bit block argument must be encrypted */
214
215 #define SILC_CBC_ENC_MSB_128_32(len, iv, block, src, dst, i, enc)       \
216 do {                                                                    \
217   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
218   if (len & (16 - 1))                                                   \
219     return FALSE;                                                       \
220                                                                         \
221   SILC_GET32_MSB(block[0], &iv[0]);                                     \
222   SILC_GET32_MSB(block[1], &iv[4]);                                     \
223   SILC_GET32_MSB(block[2], &iv[8]);                                     \
224   SILC_GET32_MSB(block[3], &iv[12]);                                    \
225                                                                         \
226   for (i = 0; i < len; i += 16) {                                       \
227     SILC_GET32_X_MSB(block[0], &src[0]);                                \
228     SILC_GET32_X_MSB(block[1], &src[4]);                                \
229     SILC_GET32_X_MSB(block[2], &src[8]);                                \
230     SILC_GET32_X_MSB(block[3], &src[12]);                               \
231                                                                         \
232     enc;                                                                \
233                                                                         \
234     SILC_PUT32_MSB(block[0], &dst[0]);                                  \
235     SILC_PUT32_MSB(block[1], &dst[4]);                                  \
236     SILC_PUT32_MSB(block[2], &dst[8]);                                  \
237     SILC_PUT32_MSB(block[3], &dst[12]);                                 \
238                                                                         \
239     dst += 16;                                                          \
240     src += 16;                                                          \
241   }                                                                     \
242                                                                         \
243   SILC_PUT32_MSB(block[0], &iv[0]);                                     \
244   SILC_PUT32_MSB(block[1], &iv[4]);                                     \
245   SILC_PUT32_MSB(block[2], &iv[8]);                                     \
246   SILC_PUT32_MSB(block[3], &iv[12]);                                    \
247 } while(0)
248
249 /* CBC mode 128-bit block, LSB, 8-bit src argument must be decrypted
250    to dst. */
251
252 #ifndef WORDS_BIGENDIAN
253 #ifdef SILC_X86_64
254 /* x86-64 */
255 #define SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i, dec)         \
256 {                                                                       \
257   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
258   if (len & (16 - 1))                                                   \
259     return FALSE;                                                       \
260                                                                         \
261   for (i = 0; i < len; i += 16) {                                       \
262     *(SilcUInt64 *)prev = *(SilcUInt64 *)src;                           \
263     *(SilcUInt64 *)(prev + 8) = *(SilcUInt64 *)(src + 8);               \
264                                                                         \
265     dec;                                                                \
266                                                                         \
267     *(SilcUInt64 *)dst ^= *(SilcUInt64 *)iv;                            \
268     *(SilcUInt64 *)(dst + 8) ^= *(SilcUInt64 *)(iv + 8);                \
269     *(SilcUInt64 *)iv = *(SilcUInt64 *)prev;                            \
270     *(SilcUInt64 *)(iv + 8) = *(SilcUInt64 *)(prev + 8);                \
271                                                                         \
272     dst += 16;                                                          \
273     src += 16;                                                          \
274   }                                                                     \
275 } while(0)
276 #else /* !SILC_X86_64 */
277 /* x86 */
278 #define SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i, dec)         \
279 do {                                                                    \
280   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
281   if (len & (16 - 1))                                                   \
282     return FALSE;                                                       \
283                                                                         \
284   for (i = 0; i < len; i += 16) {                                       \
285     memcpy(prev, src, 16);                                              \
286                                                                         \
287     dec;                                                                \
288                                                                         \
289     *(SilcUInt32 *)dst ^= *(SilcUInt32 *)iv;                            \
290     *(SilcUInt32 *)(dst + 4) ^= *(SilcUInt32 *)(iv + 4);                \
291     *(SilcUInt32 *)(dst + 8) ^= *(SilcUInt32 *)(iv + 8);                \
292     *(SilcUInt32 *)(dst + 12) ^= *(SilcUInt32 *)(iv + 12);              \
293     memcpy(iv, prev, 16);                                               \
294                                                                         \
295     dst += 16;                                                          \
296     src += 16;                                                          \
297   }                                                                     \
298 } while(0)
299 #endif /* SILC_X86_64 */
300 #else /* WORDS_BIGENDIAN */
301 /* big-endian machines */
302 #define SILC_CBC_DEC_MSB_128_8(len, iv, prev, src, dst, i, dec)         \
303 do {                                                                    \
304   SilcUInt32 tmp2[4], tmp3[4];                                          \
305                                                                         \
306   SILC_ASSERT((len & (16 - 1)) == 0);                                   \
307   if (len & (16 - 1))                                                   \
308     return FALSE;                                                       \
309                                                                         \
310   for (i = 0; i < len; i += 16) {                                       \
311     memcpy(prev, src, 16);                                              \
312                                                                         \
313     dec;                                                                \
314                                                                         \
315     SILC_GET32_MSB(tmp2[0], &iv[0]);                                    \
316     SILC_GET32_MSB(tmp2[1], &iv[4]);                                    \
317     SILC_GET32_MSB(tmp2[2], &iv[8]);                                    \
318     SILC_GET32_MSB(tmp2[3], &iv[12]);                                   \
319                                                                         \
320     SILC_GET32_MSB(tmp3[0], &dst[0]);                                   \
321     SILC_GET32_MSB(tmp3[1], &dst[4]);                                   \
322     SILC_GET32_MSB(tmp3[2], &dst[8]);                                   \
323     SILC_GET32_MSB(tmp3[3], &dst[12]);                                  \
324                                                                         \
325     tmp2[0] = tmp3[0] ^ tmp2[0];                                        \
326     tmp2[1] = tmp3[1] ^ tmp2[1];                                        \
327     tmp2[2] = tmp3[2] ^ tmp2[2];                                        \
328     tmp2[3] = tmp3[3] ^ tmp2[3];                                        \
329                                                                         \
330     SILC_PUT32_MSB(tmp2[0], &dst[0]);                                   \
331     SILC_PUT32_MSB(tmp2[1], &dst[4]);                                   \
332     SILC_PUT32_MSB(tmp2[2], &dst[8]);                                   \
333     SILC_PUT32_MSB(tmp2[3], &dst[12]);                                  \
334                                                                         \
335     memcpy(iv, prev, 16);                                               \
336                                                                         \
337     dst += 16;                                                          \
338     src += 16;                                                          \
339   }                                                                     \
340 } while(0)
341 #endif /* !WORDS_BIGENDIAN */
342
343 /* CBC mode 128-bit block, MSB, decrypt block to block_dec. */
344
345 #define SILC_CBC_DEC_MSB_128_32(len, iv, block_prev, block,             \
346                                 block_dec, src, dst, i, dec)            \
347 do {                                                                    \
348   if (!len || len & (16 - 1))                                           \
349     return FALSE;                                                       \
350                                                                         \
351   SILC_GET32_MSB(block_prev[0], &iv[0]);                                \
352   SILC_GET32_MSB(block_prev[1], &iv[4]);                                \
353   SILC_GET32_MSB(block_prev[2], &iv[8]);                                \
354   SILC_GET32_MSB(block_prev[3], &iv[12]);                               \
355                                                                         \
356   for (i = 0; i < len; i += 16) {                                       \
357     SILC_GET32_MSB(block[0], &src[0]);                                  \
358     SILC_GET32_MSB(block[1], &src[4]);                                  \
359     SILC_GET32_MSB(block[2], &src[8]);                                  \
360     SILC_GET32_MSB(block[3], &src[12]);                                 \
361                                                                         \
362     dec;                                                                \
363                                                                         \
364     block_dec[0] ^= block_prev[0];                                      \
365     block_dec[1] ^= block_prev[1];                                      \
366     block_dec[2] ^= block_prev[2];                                      \
367     block_dec[3] ^= block_prev[3];                                      \
368                                                                         \
369     SILC_PUT32_MSB(block_dec[0], &dst[0]);                              \
370     SILC_PUT32_MSB(block_dec[1], &dst[4]);                              \
371     SILC_PUT32_MSB(block_dec[2], &dst[8]);                              \
372     SILC_PUT32_MSB(block_dec[3], &dst[12]);                             \
373                                                                         \
374     block_prev[0] = block[0];                                           \
375     block_prev[1] = block[1];                                           \
376     block_prev[2] = block[2];                                           \
377     block_prev[3] = block[3];                                           \
378                                                                         \
379     dst += 16;                                                          \
380     src += 16;                                                          \
381   }                                                                     \
382                                                                         \
383   SILC_PUT32_MSB(block[0], &iv[0]);                                     \
384   SILC_PUT32_MSB(block[1], &iv[4]);                                     \
385   SILC_PUT32_MSB(block[2], &iv[8]);                                     \
386   SILC_PUT32_MSB(block[3], &iv[12]);                                    \
387 } while(0)
388
389 /* CBC mode 64-bit block, MSB, 32-bit block argument must be encrypted */
390
391 #define SILC_CBC_ENC_MSB_64_32(len, iv, block, src, dst, i, enc)        \
392 do {                                                                    \
393   SILC_ASSERT((len & (8 - 1)) == 0);                                    \
394   if (len & (8 - 1))                                                    \
395     return FALSE;                                                       \
396                                                                         \
397   SILC_GET32_MSB(block[0], &iv[0]);                                     \
398   SILC_GET32_MSB(block[1], &iv[4]);                                     \
399                                                                         \
400   for (i = 0; i < len; i += 8) {                                        \
401     SILC_GET32_X_MSB(block[0], &src[0]);                                \
402     SILC_GET32_X_MSB(block[1], &src[4]);                                \
403                                                                         \
404     enc;                                                                \
405                                                                         \
406     SILC_PUT32_MSB(block[0], &dst[0]);                                  \
407     SILC_PUT32_MSB(block[1], &dst[4]);                                  \
408                                                                         \
409     dst += 8;                                                           \
410     src += 8;                                                           \
411   }                                                                     \
412                                                                         \
413   SILC_PUT32_MSB(block[0], &iv[0]);                                     \
414   SILC_PUT32_MSB(block[1], &iv[4]);                                     \
415 } while(0)
416
417 /* CBC mode 64-bit block, MSB, decrypt block to block_dec. */
418
419 #define SILC_CBC_DEC_MSB_64_32(len, iv, block_prev, block,              \
420                                block_dec, src, dst, i, dec)             \
421 do {                                                                    \
422   if (!len || len & (8 - 1))                                            \
423     return FALSE;                                                       \
424                                                                         \
425   SILC_GET32_MSB(block_prev[0], &iv[0]);                                \
426   SILC_GET32_MSB(block_prev[1], &iv[4]);                                \
427                                                                         \
428   for (i = 0; i < len; i += 8) {                                        \
429     SILC_GET32_MSB(block[0], &src[0]);                                  \
430     SILC_GET32_MSB(block[1], &src[4]);                                  \
431                                                                         \
432     dec;                                                                \
433                                                                         \
434     block_dec[0] ^= block_prev[0];                                      \
435     block_dec[1] ^= block_prev[1];                                      \
436                                                                         \
437     SILC_PUT32_MSB(block_dec[0], &dst[0]);                              \
438     SILC_PUT32_MSB(block_dec[1], &dst[4]);                              \
439                                                                         \
440     block_prev[0] = block[0];                                           \
441     block_prev[1] = block[1];                                           \
442                                                                         \
443     dst += 8;                                                           \
444     src += 8;                                                           \
445   }                                                                     \
446                                                                         \
447   SILC_PUT32_MSB(block[0], &iv[0]);                                     \
448   SILC_PUT32_MSB(block[1], &iv[4]);                                     \
449 } while(0)
450
451 #ifndef WORDS_BIGENDIAN
452
453 /* CTR mode 128-bit block, MSB, MSB counter, the 8-bit ctr argument must
454    be encrypted to enc_ctr */
455
456 #define SILC_CTR_MSB_128_8(ctr, enc_ctr, pad, src, dst, enc)            \
457 do {                                                                    \
458   while (len > 0) {                                                     \
459     if (pad == 16) {                                                    \
460       for (i = 15; i >= 0; i--)                                         \
461         if (++ctr[i])                                                   \
462           break;                                                        \
463                                                                         \
464       enc;                                                              \
465                                                                         \
466       if (len >= 16) {                                                  \
467         *(SilcUInt64 *)dst = *(SilcUInt64 *)src ^ *(SilcUInt64 *)enc_ctr; \
468         *(SilcUInt64 *)(dst + 8) = *(SilcUInt64 *)(src + 8) ^           \
469           *(SilcUInt64 *)(enc_ctr + 8);                                 \
470         src += 16;                                                      \
471         dst += 16;                                                      \
472         len -= 16;                                                      \
473         silc_prefetch((void *)src, 0, 0);                               \
474         continue;                                                       \
475       }                                                                 \
476       pad = 0;                                                          \
477     }                                                                   \
478     *dst++ = *src++ ^ enc_ctr[pad++];                                   \
479     len--;                                                              \
480   }                                                                     \
481 } while(0)
482
483 #else /* WORDS_BIGENDIAN */
484
485 #define SILC_CTR_MSB_128_8(ctr, enc_ctr, pad, src, dst, enc)            \
486 do {                                                                    \
487   while (len-- > 0) {                                                   \
488     if (pad == 16) {                                                    \
489       for (i = 15; i >= 0; i--)                                         \
490         if (++ctr[i])                                                   \
491           break;                                                        \
492                                                                         \
493       enc;                                                              \
494       pad = 0;                                                          \
495     }                                                                   \
496     *dst++ = *src++ ^ enc_ctr[pad++];                                   \
497   }                                                                     \
498 } while(0)
499
500 #endif /* !WORDS_BIGENDIAN */
501
502 /* CTR mode 128-bit block, LSB, MSB counter, the 32-bit tmp argument
503    must be encrypted, enc_ctr must have the encrypted data too.  */
504
505 #define SILC_CTR_LSB_128_32(ctr, tmp, enc_ctr, pad, src, dst, enc)      \
506 do {                                                                    \
507   while (len-- > 0) {                                                   \
508     if (pad == 16) {                                                    \
509       for (i = 15; i >= 0; i--)                                         \
510         if (++ctr[i])                                                   \
511           break;                                                        \
512                                                                         \
513       SILC_GET32_LSB(tmp[0], ctr);                                      \
514       SILC_GET32_LSB(tmp[1], ctr + 4);                                  \
515       SILC_GET32_LSB(tmp[2], ctr + 8);                                  \
516       SILC_GET32_LSB(tmp[3], ctr + 12);                                 \
517       enc;                                                              \
518       SILC_PUT32_LSB(tmp[0], enc_ctr);                                  \
519       SILC_PUT32_LSB(tmp[1], enc_ctr + 4);                              \
520       SILC_PUT32_LSB(tmp[2], enc_ctr + 8);                              \
521       SILC_PUT32_LSB(tmp[3], enc_ctr + 12);                             \
522       pad = 0;                                                          \
523     }                                                                   \
524     *dst++ = *src++ ^ enc_ctr[pad++];                                   \
525   }                                                                     \
526 } while(0)
527
528 /* CTR mode 128-bit block, LSB, MSB counter, the 32-bit tmp argument
529    must be encrypted, enc_ctr must have the encrypted data too.  */
530
531 #define SILC_CTR_MSB_64_32(ctr, tmp, enc_ctr, pad, src, dst, enc)       \
532 do {                                                                    \
533   while (len-- > 0) {                                                   \
534     if (pad == 8) {                                                     \
535       for (i = 7; i >= 0; i--)                                          \
536         if (++ctr[i])                                                   \
537           break;                                                        \
538                                                                         \
539       SILC_GET32_MSB(tmp[0], ctr);                                      \
540       SILC_GET32_MSB(tmp[1], ctr + 4);                                  \
541       enc;                                                              \
542       SILC_PUT32_MSB(tmp[0], enc_ctr);                                  \
543       SILC_PUT32_MSB(tmp[1], enc_ctr + 4);                              \
544       pad = 0;                                                          \
545     }                                                                   \
546     *dst++ = *src++ ^ enc_ctr[pad++];                                   \
547   }                                                                     \
548 } while(0)
549
550 /* CFB 128-bit block, LSB, the 32-bit cfb argument must be encrypted. */
551
552 #define SILC_CFB_ENC_LSB_128_32(iv, cfb, pad, src, dst, enc)            \
553 do {                                                                    \
554   while (len-- > 0) {                                                   \
555     if (pad == 16) {                                                    \
556       SILC_GET32_LSB(cfb[0], iv);                                       \
557       SILC_GET32_LSB(cfb[1], iv + 4);                                   \
558       SILC_GET32_LSB(cfb[2], iv + 8);                                   \
559       SILC_GET32_LSB(cfb[3], iv + 12);                                  \
560                                                                         \
561       enc;                                                              \
562                                                                         \
563       SILC_PUT32_LSB(cfb[0], iv);                                       \
564       SILC_PUT32_LSB(cfb[1], iv + 4);                                   \
565       SILC_PUT32_LSB(cfb[2], iv + 8);                                   \
566       SILC_PUT32_LSB(cfb[3], iv + 12);                                  \
567       pad = 0;                                                          \
568     }                                                                   \
569     iv[pad] = (*dst = *src ^ iv[pad]);                                  \
570     dst++;                                                              \
571     src++;                                                              \
572     pad++;                                                              \
573   }                                                                     \
574 } while(0)
575
576 /* CFB 128-bit block, LSB, the 32-bit cfb argument must be decrypted. */
577
578 #define SILC_CFB_DEC_LSB_128_32(iv, cfb, pad, src, dst, dec)            \
579 do {                                                                    \
580   unsigned char temp;                                                   \
581   while (len-- > 0) {                                                   \
582     if (pad == 16) {                                                    \
583       SILC_GET32_LSB(cfb[0], iv);                                       \
584       SILC_GET32_LSB(cfb[1], iv + 4);                                   \
585       SILC_GET32_LSB(cfb[2], iv + 8);                                   \
586       SILC_GET32_LSB(cfb[3], iv + 12);                                  \
587                                                                         \
588       dec;                                                              \
589                                                                         \
590       SILC_PUT32_LSB(cfb[0], iv);                                       \
591       SILC_PUT32_LSB(cfb[1], iv + 4);                                   \
592       SILC_PUT32_LSB(cfb[2], iv + 8);                                   \
593       SILC_PUT32_LSB(cfb[3], iv + 12);                                  \
594       pad = 0;                                                          \
595     }                                                                   \
596     temp = *src;                                                        \
597     *dst = temp ^ iv[pad];                                              \
598     iv[pad++] = temp;                                                   \
599     dst++;                                                              \
600     src++;                                                              \
601   }                                                                     \
602 } while(0)
603
604 /* CFB 128-bit block, MSB, the 32-bit cfb argument must be encrypted. */
605
606 #define SILC_CFB_ENC_MSB_128_32(iv, cfb, pad, src, dst, enc)            \
607 do {                                                                    \
608   while (len-- > 0) {                                                   \
609     if (pad == 16) {                                                    \
610       SILC_GET32_MSB(cfb[0], iv);                                       \
611       SILC_GET32_MSB(cfb[1], iv + 4);                                   \
612       SILC_GET32_MSB(cfb[2], iv + 8);                                   \
613       SILC_GET32_MSB(cfb[3], iv + 12);                                  \
614                                                                         \
615       enc;                                                              \
616                                                                         \
617       SILC_PUT32_MSB(cfb[0], iv);                                       \
618       SILC_PUT32_MSB(cfb[1], iv + 4);                                   \
619       SILC_PUT32_MSB(cfb[2], iv + 8);                                   \
620       SILC_PUT32_MSB(cfb[3], iv + 12);                                  \
621       pad = 0;                                                          \
622     }                                                                   \
623     iv[pad] = (*dst = *src ^ iv[pad]);                                  \
624     dst++;                                                              \
625     src++;                                                              \
626     pad++;                                                              \
627   }                                                                     \
628 } while(0)
629
630 /* CFB 128-bit block, MSB, the 32-bit cfb argument must be decrypted. */
631
632 #define SILC_CFB_DEC_MSB_128_32(iv, cfb, pad, src, dst, dec)            \
633 do {                                                                    \
634   unsigned char temp;                                                   \
635   while (len-- > 0) {                                                   \
636     if (pad == 16) {                                                    \
637       SILC_GET32_MSB(cfb[0], iv);                                       \
638       SILC_GET32_MSB(cfb[1], iv + 4);                                   \
639       SILC_GET32_MSB(cfb[2], iv + 8);                                   \
640       SILC_GET32_MSB(cfb[3], iv + 12);                                  \
641                                                                         \
642       dec;                                                              \
643                                                                         \
644       SILC_PUT32_MSB(cfb[0], iv);                                       \
645       SILC_PUT32_MSB(cfb[1], iv + 4);                                   \
646       SILC_PUT32_MSB(cfb[2], iv + 8);                                   \
647       SILC_PUT32_MSB(cfb[3], iv + 12);                                  \
648       pad = 0;                                                          \
649     }                                                                   \
650     temp = *src;                                                        \
651     *dst = temp ^ iv[pad];                                              \
652     iv[pad++] = temp;                                                   \
653     dst++;                                                              \
654     src++;                                                              \
655   }                                                                     \
656 } while(0)
657
658 /* CFB 64-bit block, MSB, the 32-bit cfb argument must be encrypted. */
659
660 #define SILC_CFB_ENC_MSB_64_32(iv, cfb, pad, src, dst, enc)             \
661 do {                                                                    \
662   while (len-- > 0) {                                                   \
663     if (pad == 8) {                                                     \
664       SILC_GET32_MSB(cfb[0], iv);                                       \
665       SILC_GET32_MSB(cfb[1], iv + 4);                                   \
666                                                                         \
667       enc;                                                              \
668                                                                         \
669       SILC_PUT32_MSB(cfb[0], iv);                                       \
670       SILC_PUT32_MSB(cfb[1], iv + 4);                                   \
671       pad = 0;                                                          \
672     }                                                                   \
673     iv[pad] = (*dst = *src ^ iv[pad]);                                  \
674     dst++;                                                              \
675     src++;                                                              \
676     pad++;                                                              \
677   }                                                                     \
678 } while(0)
679
680 /* CFB 64-bit block, MSB, the 32-bit cfb argument must be decrypted. */
681
682 #define SILC_CFB_DEC_MSB_64_32(iv, cfb, pad, src, dst, dec)             \
683 do {                                                                    \
684   unsigned char temp;                                                   \
685   while (len-- > 0) {                                                   \
686     if (pad == 8) {                                                     \
687       SILC_GET32_MSB(cfb[0], iv);                                       \
688       SILC_GET32_MSB(cfb[1], iv + 4);                                   \
689                                                                         \
690       dec;                                                              \
691                                                                         \
692       SILC_PUT32_MSB(cfb[0], iv);                                       \
693       SILC_PUT32_MSB(cfb[1], iv + 4);                                   \
694       pad = 0;                                                          \
695     }                                                                   \
696     temp = *src;                                                        \
697     *dst = temp ^ iv[pad];                                              \
698     iv[pad++] = temp;                                                   \
699     dst++;                                                              \
700     src++;                                                              \
701   }                                                                     \
702 } while(0)
703
704 /* CFB 128-bit block, MSB, the 8-bit iv argument must be encrypted. */
705
706 #define SILC_CFB_ENC_MSB_128_8(iv, pad, src, dst, enc)                  \
707 do {                                                                    \
708   while (len-- > 0) {                                                   \
709     if (pad == 16) {                                                    \
710       enc;                                                              \
711       pad = 0;                                                          \
712     }                                                                   \
713     iv[pad] = (*dst = *src ^ iv[pad]);                                  \
714     dst++;                                                              \
715     src++;                                                              \
716     pad++;                                                              \
717   }                                                                     \
718 } while(0)
719
720 /* CFB 128-bit block, MSB, the 8-bit iv argument must be decrypted. */
721
722 #define SILC_CFB_DEC_MSB_128_8(iv, pad, src, dst, dec)                  \
723 do {                                                                    \
724   unsigned char temp;                                                   \
725   while (len-- > 0) {                                                   \
726     if (pad == 16) {                                                    \
727       dec;                                                              \
728       pad = 0;                                                          \
729     }                                                                   \
730     temp = *src;                                                        \
731     *dst = temp ^ iv[pad];                                              \
732     iv[pad++] = temp;                                                   \
733     dst++;                                                              \
734     src++;                                                              \
735   }                                                                     \
736 } while(0)
737
738 #endif