]> git.cryptolib.org Git - avr-crypto-lib.git/blob - seed-asm.S
even more ASM-fun now only decryption needs C-Stub
[avr-crypto-lib.git] / seed-asm.S
1 /* seed-asm.S */
2 /*
3     This file is part of the Crypto-avr-lib/microcrypt-lib.
4     Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /**
20  * \file        seed-asm.S
21  * \author      Daniel Otte 
22  * \date        2007-06-1
23  * \brief       SEED parts in assembler for AVR
24  * \par License 
25  * GPLv3 or later
26  * 
27  */
28 #include "avr-asm-macros.S"
29
30 .global bigendian_sum32
31 ; === bigendian_sum32 ===
32 ; function that adds two 32-bit words in the bigendian way and returns the result
33 ;  param1: the first 32-bit word
34 ;       given in r25,r24,r23,22 (r25 is most significant for little endian)
35 ;  param2: the second 32-bit word
36 ;       given in r21,r20,r19,18 (r21 is most significant for little endian)
37 ;  modifys: 
38 bigendian_sum32:
39         add r25, r21
40         adc r24, r20
41         adc r23, r19
42         adc r22, r18
43         ret
44         
45 .global bigendian_sub32
46 ; === bigendian_sub32 ===
47 ; function that subtracts a 32-bit words from another in the bigendian way and returns the result
48 ;  param1: the minuend 32-bit word
49 ;       given in r25,r24,r23,22 (r25 is most significant for little endian)
50 ;  param2: the subtrahend 32-bit word
51 ;       given in r21,r20,r19,18 (r21 is most significant for little endian)
52 ;  modifys: 
53 bigendian_sub32:
54         sub r25, r21
55         sbc r24, r20
56         sbc r23, r19
57         sbc r22, r18
58         ret
59
60 /******************************************************************************/        
61 /*
62 #define M0 0xfc
63 #define M1 0xf3
64 #define M2 0xcf
65 #define M3 0x3f
66
67 #define X3 (((uint8_t*)(&x))[0])
68 #define X2 (((uint8_t*)(&x))[1])
69 #define X1 (((uint8_t*)(&x))[2])
70 #define X0 (((uint8_t*)(&x))[3])
71
72 #define Z3 (((uint8_t*)(&z))[0])
73 #define Z2 (((uint8_t*)(&z))[1])
74 #define Z1 (((uint8_t*)(&z))[2])
75 #define Z0 (((uint8_t*)(&z))[3])
76
77 uint32_t g_function(uint32_t x){
78         uint32_t z;
79         / * sbox substitution * /
80         X3 = pgm_read_byte(&(seed_sbox2[X3]));
81         X2 = pgm_read_byte(&(seed_sbox1[X2]));
82         X1 = pgm_read_byte(&(seed_sbox2[X1]));
83         X0 = pgm_read_byte(&(seed_sbox1[X0]));
84         / * now the permutation * /
85         Z0 = (X0 & M0) ^ (X1 & M1) ^ (X2 & M2) ^ (X3 & M3);
86         Z1 = (X0 & M1) ^ (X1 & M2) ^ (X2 & M3) ^ (X3 & M0);
87         Z2 = (X0 & M2) ^ (X1 & M3) ^ (X2 & M0) ^ (X3 & M1);
88         Z3 = (X0 & M3) ^ (X1 & M0) ^ (X2 & M1) ^ (X3 & M2);
89         return z;
90 }
91 */
92 M0 = 0xfc
93 M1 = 0xf3
94 M2 = 0xcf
95 M3 = 0x3f
96 X0 = 18
97 X1 = 19
98 X2 = 20
99 X3 = 21
100 Z0 = 25
101 Z1 = 24
102 Z2 = 23
103 Z3 = 22
104 T0 = X0
105 T1 = 26
106 T2 = 27
107 T3 = X1
108 /*
109  *  param x: r22:r25
110  *  X0 = R25
111  *  X1 = R24
112  *  X2 = R23
113  *  X3 = R22
114  */    
115 .global seed_g_function
116 seed_g_function:
117         ldi r30, lo8(seed_sbox1)
118         ldi r31, hi8(seed_sbox1)
119         movw r26, r30
120         add r30, Z2
121         adc r31, r1
122         lpm X2, Z
123         movw r30, r26
124         add r30, Z0
125         adc r31, r1
126         lpm X0, Z
127         inc r27 /* switch X to point to sbox2 */
128         movw r30, r26
129         add r30, Z3
130         adc r31, r1
131         lpm X3, Z
132         movw r30, r26
133         add r30, Z1
134         adc r31, r1
135         lpm X1, Z
136         /* now the secound part */
137         mov Z0, X0
138         mov Z1, X0
139         mov Z2, X0
140         mov Z3, X0
141         andi Z0, M0
142         andi Z1, M1
143         andi Z2, M2
144         andi Z3, M3     
145         mov T0, X1
146         mov T1, X1
147         mov T2, X1
148         ; mov T3, X1 /* T3 = X1 */
149         andi T0, M1
150         andi T1, M2
151         andi T2, M3
152         andi T3, M0
153         eor Z0, T0
154         eor Z1, T1
155         eor Z2, T2
156         eor Z3, T3
157         mov T0, X2
158         mov T1, X2
159         mov T2, X2
160         mov T3, X2
161         andi T0, M2
162         andi T1, M3
163         andi T2, M0
164         andi T3, M1
165         eor Z0, T0
166         eor Z1, T1
167         eor Z2, T2
168         eor Z3, T3
169         mov T0, X3
170         mov T1, X3
171         mov T2, X3
172         mov T3, X3
173         andi T0, M3
174         andi T1, M0
175         andi T2, M1
176         andi T3, M2
177         eor Z0, T0
178         eor Z1, T1
179         eor Z2, T2
180         eor Z3, T3
181         ret
182
183 seed_sbox1:
184 .byte   169,  133,  214,  211,   84,   29,  172,   37 
185 .byte    93,   67,   24,   30,   81,  252,  202,   99 
186 .byte    40,   68,   32,  157,  224,  226,  200,   23 
187 .byte   165,  143,    3,  123,  187,   19,  210,  238 
188 .byte   112,  140,   63,  168,   50,  221,  246,  116 
189 .byte   236,  149,   11,   87,   92,   91,  189,    1 
190 .byte    36,   28,  115,  152,   16,  204,  242,  217 
191 .byte    44,   231, 114,  131,  155,  209,  134,  201 
192 .byte    96,   80,  163,  235,   13,  182,  158,   79 
193 .byte   183,   90,  198,  120,  166,   18,  175,  213 
194 .byte    97,  195,  180,   65,   82,  125,  141,    8 
195 .byte    31,  153,    0,   25,    4,   83,  247,  225 
196 .byte   253,  118,   47,   39,  176,  139,   14,  171 
197 .byte   162,  110,  147,   77,  105,  124,    9,   10 
198 .byte   191,  239,  243,  197,  135,   20,  254,  100 
199 .byte   222,   46,   75,   26,    6,   33,  107,  102 
200 .byte     2,  245,  146,  138,   12,  179,  126,  208 
201 .byte   122,   71,  150,  229,   38,  128,  173,  223 
202 .byte   161,   48,   55,  174,   54,   21,   34,   56 
203 .byte   244,  167,   69,   76,  129,  233,  132,  151 
204 .byte    53,  203,  206,   60,  113,   17,  199,  137 
205 .byte   117,  251,  218,  248,  148,   89,  130,  196 
206 .byte   255,   73,   57,  103,  192,  207,  215,  184 
207 .byte    15,  142,   66,   35,  145,  108,  219,  164 
208 .byte    52,  241,   72,  194,  111,   61,   45,   64 
209 .byte   190,   62,  188,  193,  170,  186,   78,   85 
210 .byte    59,  220,  104,  127,  156,  216,   74,   86 
211 .byte   119,  160,  237,   70,  181,   43,  101,  250 
212 .byte   227,  185,  177,  159,   94,  249,  230,  178 
213 .byte    49,  234,  109,   95,  228,  240,  205,  136 
214 .byte    22,   58,   88,  212,   98,   41,    7,   51 
215 .byte   232,   27,    5,  121,  144,  106,   42,  154
216
217
218 seed_sbox2:
219 .byte    56,  232,   45,  166,  207,  222,  179,  184 
220 .byte   175,   96,   85,  199,   68,  111,  107,   91 
221 .byte   195,   98,   51,  181,   41,  160,  226,  167 
222 .byte   211,  145,   17,    6,   28,  188,   54,   75 
223 .byte   239,  136,  108,  168,   23,  196,   22,  244 
224 .byte   194,   69,  225,  214,   63,   61,  142,  152 
225 .byte    40,   78,  246,   62,  165,  249,   13,  223 
226 .byte   216,   43,  102,  122,   39,   47,  241,  114 
227 .byte    66,  212,   65,  192,  115,  103,  172,  139 
228 .byte   247,  173,  128,   31,  202,   44,  170,   52 
229 .byte   210,   11,  238,  233,   93,  148,   24,  248 
230 .byte    87,  174,    8,  197,   19,  205,  134,  185 
231 .byte   255,  125,  193,   49,  245,  138,  106,  177 
232 .byte   209,   32,  215,    2,   34,    4,  104,  113 
233 .byte     7,  219,  157,  153,   97,  190,  230,   89 
234 .byte   221,   81,  144,  220,  154,  163,  171,  208 
235 .byte   129,   15,   71,   26,  227,  236,  141,  191 
236 .byte   150,  123,   92,  162,  161,   99,   35,   77 
237 .byte   200,  158,  156,   58,   12,   46,  186,  110 
238 .byte   159,   90,  242,  146,  243,   73,  120,  204 
239 .byte    21,  251,  112,  117,  127,   53,   16,    3 
240 .byte   100,  109,  198,  116,  213,  180,  234,    9 
241 .byte   118,   25,  254,   64,   18,  224,  189,    5 
242 .byte   250,    1,  240,   42,   94,  169,   86,   67 
243 .byte   133,   20,  137,  155,  176,  229,   72,  121 
244 .byte   151,  252,   30,  130,   33,  140,   27,   95 
245 .byte   119,   84,  178,   29,   37,   79,    0,   70 
246 .byte   237,   88,   82,  235,  126,  218,  201,  253 
247 .byte    48,  149,  101,   60,  182,  228,  187,  124 
248 .byte    14,   80,   57,   38,   50,  132,  105,  147 
249 .byte    55,  231,   36,  164,  203,   83,   10,  135 
250 .byte   217,   76,  131,  143,  206,   59,   74,  183 
251
252 /******************************************************************************/
253
254 /*
255 static
256 uint64_t f_function(const uint64_t* a, uint32_t k0, uint32_t k1){
257         uint32_t c,d;
258
259         c = *a & 0x00000000FFFFFFFFLL;
260         d = (*a>>32) & 0x00000000FFFFFFFFLL;
261         
262         c ^= k0; d ^= k1;
263         d ^= c;
264         d = g_function(d);
265         c = bigendian_sum32(c,d);
266         c = g_function(c);
267         d = bigendian_sum32(c,d);
268         d = g_function(d);
269         c = bigendian_sum32(c,d);       
270         return ((uint64_t)d << 32) | c;
271 }
272 */
273 /*
274  * param a   r24:r25
275  * param k0  r20:r23
276  * param k1  r16:r19
277  */
278 D0 = 10
279 D1 = 11
280 C0 = 12
281 C1 = 13
282 C2 = 14
283 C3 = 15
284 D2 = 16
285 D3 = 17
286 .global seed_f_function
287 seed_f_function:
288         push_range 10, 17
289         movw r30, r24
290         ld C0, Z+
291         ld C1, Z+
292         ld C2, Z+
293         ld C3, Z+
294         eor C0, r20
295         eor C1, r21
296         eor C2, r22
297         eor C3, r23
298         ld r22, Z+
299         ld r23, Z+
300         ld r24, Z+
301         ld r25, Z+
302         eor r22, r16
303         eor r23, r17
304         eor r24, r18
305         eor r25, r19
306         eor r22, C0
307         eor r23, C1
308         eor r24, C2
309         eor r25, C3
310         rcall seed_g_function
311         mov D0, r22
312         mov D1, r23
313         mov D2, r24
314         mov D3, r25
315
316         add r25, C3
317         adc r24, C2
318         adc r23, C1
319         adc r22, C0
320         rcall seed_g_function
321         mov C0, r22
322         mov C1, r23
323         mov C2, r24
324         mov C3, r25
325
326         add r25, D3
327         adc r24, D2
328         adc r23, D1
329         adc r22, D0
330         rcall seed_g_function
331         mov D0, r22
332         mov D1, r23
333         mov D2, r24
334         mov D3, r25
335
336         add C3, r25
337         adc C2, r24
338         adc C1, r23
339         adc C0, r22
340
341         mov r18, C0
342         mov r19, C1
343         mov r20, C2
344         mov r21, C3
345         
346         pop_range 10, 17
347         ret
348
349 /******************************************************************************/
350 /*
351 void seed_init(uint8_t * key, seed_ctx_t * ctx){
352         memcpy(ctx->k, key, 128/8);
353 }
354 */
355
356 .global seed_init
357 seed_init:
358         movw r26, r24
359         movw r30, r22
360         ldi r22, 16
361 1:
362         ld r0, X+
363         st Z+, r0
364         dec r22
365         brne 1b 
366         ret
367 /******************************************************************************/
368 /*
369 typedef struct {
370         uint32_t k0, k1;
371 } keypair_t;
372
373 keypair_t getnextkeys(uint32_t *keystate, uint8_t curround){
374         keypair_t ret;
375         if (curround>15){
376                 / * ERROR * /
377                 ret.k0 = ret.k1 = 0;
378         } else {
379         / *     ret.k0 = seed_g_function(keystate[0] + keystate[2] - pgm_read_dword(&(seed_kc[curround])));
380                 ret.k1 = seed_g_function(keystate[1] - keystate[3] + pgm_read_dword(&(seed_kc[curround]))); * /
381                 ret.k0 = bigendian_sum32(keystate[0], keystate[2]);
382                 ret.k0 = bigendian_sub32(ret.k0, pgm_read_dword(&(seed_kc[curround])));
383                 ret.k0 = seed_g_function(ret.k0);
384                 ret.k1 = bigendian_sub32(keystate[1], keystate[3]);
385                 ret.k1 = bigendian_sum32(ret.k1, pgm_read_dword(&(seed_kc[curround])));
386                 ret.k1 = seed_g_function(ret.k1);
387                 
388                 if (curround & 1){
389                         / * odd round (1,3,5, ...) * /
390                         ((uint64_t*)keystate)[1] = bigendian_rotl8_64( ((uint64_t*)keystate)[1] );
391                 } else {
392                         / * even round (0,2,4, ...) * /
393                         ((uint64_t*)keystate)[0] = bigendian_rotr8_64(((uint64_t*)keystate)[0]);
394                 }
395         }
396         return ret;
397 }
398 */
399 /*
400  * param keystate: r24:r25
401  * param curround: r22
402  */
403 XRC0 = 10
404 XRC1 = 11
405 XRC2 = 12
406 XRC3 = 13
407 D0 = 14
408 D1 = 15
409 D2 = 16
410 D3 = 17
411
412 compute_keys:
413         ldi r30, lo8(seed_kc)
414         ldi r31, hi8(seed_kc)
415         lsl r22
416         lsl r22
417         add r30, r22
418         adc r31, r1
419         lpm XRC0, Z+
420         lpm XRC1, Z+
421         lpm XRC2, Z+
422         lpm XRC3, Z+
423         movw r28, r24
424         ldd r25, Y+0*4+3
425         ldd r24, Y+0*4+2
426         ldd r23, Y+0*4+1
427         ldd r22, Y+0*4+0
428         
429         ldd r0, Y+2*4+3
430         add r25, r0
431         ldd r0, Y+2*4+2
432         adc r24, r0
433         ldd r0, Y+2*4+1
434         adc r23, r0
435         ldd r0, Y+2*4+0
436         adc r22, r0
437
438         sub r25, XRC3
439         sbc r24, XRC2
440         sbc r23, XRC1
441         sbc r22, XRC0
442         rcall seed_g_function
443         mov D0, r22
444         mov D1, r23
445         mov D2, r24
446         mov D3, r25
447         
448
449         ldd r25, Y+1*4+3
450         ldd r24, Y+1*4+2
451         ldd r23, Y+1*4+1
452         ldd r22, Y+1*4+0
453
454         ldd r0, Y+3*4+3
455         sub r25, r0
456         ldd r0, Y+3*4+2
457         sbc r24, r0
458         ldd r0, Y+3*4+1
459         sbc r23, r0
460         ldd r0, Y+3*4+0
461         sbc r22, r0
462
463         add r25, XRC3
464         adc r24, XRC2
465         adc r23, XRC1
466         adc r22, XRC0
467         rcall seed_g_function
468
469         mov r21, D3
470         mov r20, D2
471         mov r19, D1
472         mov r18, D0 
473         ret
474
475 .global seed_getnextkeys
476 seed_getnextkeys:
477         push_range 10, 17
478         push r28
479         push r29
480 ;       andi r22, 0x0F
481         bst r22,0
482         rcall compute_keys              
483         brtc even_round
484 odd_round:
485
486         adiw r28, 8
487         ld r26, Y
488         ldd r0, Y+1
489         std Y+0, r0
490         ldd r0, Y+2
491         std Y+1, r0
492         ldd r0, Y+3
493         std Y+2, r0
494         ldd r0, Y+4
495         std Y+3, r0
496         ldd r0, Y+5
497         std Y+4, r0
498         ldd r0, Y+6
499         std Y+5, r0
500         ldd r0, Y+7
501         std Y+6, r0
502         std Y+7, r26    
503 /*
504         movw r30, r28
505         ld r26, Z+
506         ldi r27, 7
507 1:
508         ld r0, Z+
509         st Y+, r0
510         dec r27
511         brne 1b
512         st Y, r26
513 */      
514         rjmp 4f
515
516 even_round:
517
518         ldd r26, Y+7
519         ldd r0, Y+6
520         std Y+7, r0
521         ldd r0, Y+5
522         std Y+6, r0
523         ldd r0, Y+4
524         std Y+5, r0
525         ldd r0, Y+3
526         std Y+4, r0
527         ldd r0, Y+2
528         std Y+3, r0
529         ldd r0, Y+1
530         std Y+2, r0
531         ldd r0, Y+0
532         std Y+1, r0
533         std Y+0, r26
534 /*
535         adiw r28, 7     
536         ld r26, Y
537         ldi r27, 7      
538 1:
539         ld r0, -Y
540         std Y+1, r0
541         dec r27
542         brne 1b
543         st Y, r26
544 */
545 4:      
546         pop r29
547         pop r28
548         pop_range 10, 17
549         ret
550
551 /******************************************************************************/
552 /*
553 keypair_t getprevkeys(uint32_t *keystate, uint8_t curround){
554         keypair_t ret;
555         if (curround>15){
556                 / * ERROR * /
557                 ret.k0 = ret.k1 = 0;
558         } else {
559                 if (curround & 1){
560                         / * odd round (1,3,5, ..., 15) * /
561                         ((uint64_t*)keystate)[1] = bigendian_rotr8_64( ((uint64_t*)keystate)[1] );
562                 } else {
563                         / * even round (0,2,4, ..., 14) * /
564                         ((uint64_t*)keystate)[0] = bigendian_rotl8_64(((uint64_t*)keystate)[0]);
565                 }
566         / *     ret.k0 = seed_g_function(keystate[0] + keystate[2] - pgm_read_dword(&(seed_kc[curround])));
567                 ret.k1 = seed_g_function(keystate[1] - keystate[3] + pgm_read_dword(&(seed_kc[curround]))); * /
568                 ret.k0 = bigendian_sum32(keystate[0], keystate[2]);
569                 ret.k0 = bigendian_sub32(ret.k0, pgm_read_dword(&(seed_kc[curround])));
570                 ret.k0 = seed_g_function(ret.k0);
571                 ret.k1 = bigendian_sub32(keystate[1], keystate[3]);
572                 ret.k1 = bigendian_sum32(ret.k1, pgm_read_dword(&(seed_kc[curround])));
573                 ret.k1 = seed_g_function(ret.k1);
574                 }
575         return ret;
576 }
577 */
578 /*
579  * param keystate: r24:r25
580  * param curround: r22
581  */
582
583 .global seed_getprevkeys
584 seed_getprevkeys:
585         push_range 10, 17
586         push r28
587         push r29
588         movw r28, r24   
589 ;       andi r22, 0x0F
590         bst r22, 0
591         brts r_odd_round
592 r_even_round:
593         ldd r26, Y+0
594         ldd r0, Y+1
595         std Y+0, r0
596         ldd r0, Y+2
597         std Y+1, r0
598         ldd r0, Y+3
599         std Y+2, r0
600         ldd r0, Y+4
601         std Y+3, r0
602         ldd r0, Y+5
603         std Y+4, r0
604         ldd r0, Y+6
605         std Y+5, r0
606         ldd r0, Y+7
607         std Y+6, r0
608         std Y+7, r26    
609 /*
610         movw r30, r28
611         ld r26, Z+
612         ldi r27, 7
613 1:
614         ld r0, Z+
615         st Y+, r0
616         dec r27
617         brne 1b
618         st Y, r26
619 */      
620
621         rjmp 4f
622 r_odd_round:
623         ldd r26, Y+8+7
624         ldd r0, Y+8+6
625         std Y+8+7, r0
626         ldd r0, Y+8+5
627         std Y+8+6, r0
628         ldd r0, Y+8+4
629         std Y+8+5, r0
630         ldd r0, Y+8+3
631         std Y+8+4, r0
632         ldd r0, Y+8+2
633         std Y+8+3, r0
634         ldd r0, Y+8+1
635         std Y+8+2, r0
636         ldd r0, Y+8+0
637         std Y+8+1, r0
638         std Y+8+0, r26
639 /*
640         adiw r28, 7     
641         ld r26, Y
642         ldi r27, 7      
643 1:
644         ld r0, -Y
645         std Y+1, r0
646         dec r27
647         brne 1b
648         st Y, r26
649 */
650 4:
651         rcall compute_keys      
652
653         pop r29
654         pop r28
655         pop_range 10, 17
656         ret
657
658 /******************************************************************************/
659
660 .global seed_kc
661 seed_kc:
662 .long   0xb979379e 
663 .long   0x73f36e3c
664 .long   0xe6e6dd78 
665 .long   0xcccdbbf1 
666 .long   0x999b77e3 
667 .long   0x3337efc6 
668 .long   0x676ede8d 
669 .long   0xcfdcbc1b 
670 .long   0x9eb97937
671 .long   0x3c73f36e      
672 .long   0x78e6e6dd
673 .long   0xf1cccdbb
674 .long   0xe3999b77
675 .long   0xc63337ef
676 .long   0x8d676ede
677 .long   0x1bcfdcbc
678
679 /******************************************************************************/
680 /*
681 #define L (((uint64_t*)buffer)[0])
682 #define R (((uint64_t*)buffer)[1])
683
684 void seed_enc(void * buffer, seed_ctx_t * ctx){
685         uint8_t r;
686         keypair_t k;
687         for(r=0; r<8; ++r){
688                         k = seed_getnextkeys(ctx->k, 2*r);
689 / *
690         DEBUG_S("\r\n\tDBG ka,0: "); uart_hexdump(&k.k0, 4);
691         DEBUG_S("\r\n\tDBG ka,1: "); uart_hexdump(&k.k1, 4);
692         DEBUG_S("\r\n\t DBG L:   "); uart_hexdump((uint8_t*)buffer+0, 8);
693         DEBUG_S("\r\n\t DBG R:   "); uart_hexdump((uint8_t*)buffer+8, 8);
694 * /
695                         L ^= seed_f_function(&R,k.k0,k.k1);
696                         
697                         k = seed_getnextkeys(ctx->k, 2*r+1);
698 / *
699         DEBUG_S("\r\n\tDBG kb,0: "); uart_hexdump(&k.k0, 4);
700         DEBUG_S("\r\n\tDBG kb,1: "); uart_hexdump(&k.k1, 4);
701         DEBUG_S("\r\n\t DBG L:   "); uart_hexdump((uint8_t*)buffer+8, 8);
702         DEBUG_S("\r\n\t DBG R:   "); uart_hexdump((uint8_t*)buffer+0, 8);
703 * /
704                         R ^= seed_f_function(&L,k.k0,k.k1);
705         }
706         / * just an exchange without temp. variable * /
707         L ^= R;
708         R ^= L;
709         L ^= R;
710 }
711 */
712 /*
713  * param buffer: r24:r25
714  * param ctx:    r22:r23
715  */
716 CTR  = 9
717 xLPTR = 10
718 xRPTR = 12
719 CPTR = 14
720
721 .global seed_enc
722 seed_enc:
723         push_range 9, 17
724         push r28
725         push r29        
726         clr CTR
727         movw xLPTR, r24
728         adiw r24, 8
729         movw xRPTR, r24         
730         movw CPTR, r22
731 1:
732         movw r28, xLPTR
733         movw r24, CPTR
734         mov r22, CTR
735         lsl r22
736         rcall seed_getnextkeys  
737
738         /* use pen & paper to understand the following permutation */
739         movw r16, r22
740         movw r22, r18
741         movw r18, r24
742         movw r24, r20
743         movw r20, r22
744         movw r22, r24
745         movw r24, xRPTR 
746
747         rcall seed_f_function
748
749         ld r0, Y
750         eor r0, r18
751         st Y+, r0
752         ld r0, Y
753         eor r0, r19
754         st Y+, r0
755         ld r0, Y
756         eor r0, r20
757         st Y+, r0
758         ld r0, Y
759         eor r0, r21
760         st Y+, r0
761         ld r0, Y
762         eor r0, r22
763         st Y+, r0
764         ld r0, Y
765         eor r0, r23
766         st Y+, r0
767         ld r0, Y
768         eor r0, r24
769         st Y+, r0
770         ld r0, Y
771         eor r0, r25
772         st Y+, r0
773         /* secound half */
774         movw r24, CPTR
775         mov r22, CTR
776         lsl r22
777         inc r22
778         rcall seed_getnextkeys  
779
780         movw r16, r22
781         movw r22, r18
782         movw r18, r24
783         movw r24, r20
784         movw r20, r22
785         movw r22, r24
786         movw r24, xLPTR 
787         
788         rcall seed_f_function
789
790         ld r0, Y
791         eor r0, r18
792         st Y+, r0
793         ld r0, Y
794         eor r0, r19
795         st Y+, r0
796         ld r0, Y
797         eor r0, r20
798         st Y+, r0
799         ld r0, Y
800         eor r0, r21
801         st Y+, r0
802         ld r0, Y
803         eor r0, r22
804         st Y+, r0
805         ld r0, Y
806         eor r0, r23
807         st Y+, r0
808         ld r0, Y
809         eor r0, r24
810         st Y+, r0
811         ld r0, Y
812         eor r0, r25
813         st Y+, r0
814         
815         inc CTR
816         bst CTR, 3
817         brts 3f
818         rjmp 1b
819 3:
820         movw r28, xLPTR
821         movw r30, xRPTR
822         ldi r17, 8
823 4:
824         ld r10, Y
825         ld r11, Z
826         st Z+, r10
827         st Y+, r11
828         dec r17
829         brne 4b
830 5:
831         pop r29
832         pop r28
833         pop_range 9, 17
834         ret
835
836
837
838