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