]> git.cryptolib.org Git - avr-crypto-lib.git/blob - serpent-asm.S
1005fd368b56ac1ceed0735ba90d3e172668cd52
[avr-crypto-lib.git] / serpent-asm.S
1 /* serpent_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 /* 
21  * File:        serpent_sboxes.S
22  * Author:      Daniel Otte
23  * Date:        2008-08-07
24  * License:     GPLv3 or later
25  * Description: Implementation of the serpent sbox function.
26  * 
27  */
28  
29 #include <avr/io.h>
30
31 /*******************************************************************************
32 *  MACRO SECTION                                                               *
33 *******************************************************************************/
34
35 .macro push_ p1:req, p2:vararg
36         push \p1
37 .ifnb \p2       
38         push_ \p2
39 .endif
40 .endm
41
42 .macro pop_ p1:req, p2:vararg
43         pop \p1
44 .ifnb \p2       
45         pop_ \p2
46 .endif
47 .endm
48
49 .macro push_range from:req, to:req
50         push \from
51 .if     \to-\from
52         push_range "(\from+1)",\to
53 .endif          
54 .endm
55
56 .macro pop_range from:req, to:req
57         pop \to
58 .if     \to-\from
59         pop_range \from,"(\to-1)"       
60 .endif
61 .endm
62
63 .macro stack_alloc size:req, reg1=r30, reg2=r31
64         in r0, _SFR_IO_ADDR(SREG)
65         cli
66         in \reg1, _SFR_IO_ADDR(SPL)
67         in \reg2, _SFR_IO_ADDR(SPH)
68         sbiw \reg1, \size 
69         out _SFR_IO_ADDR(SPH), \reg2
70         out _SFR_IO_ADDR(SPL), \reg1
71         out _SFR_IO_ADDR(SREG), r0
72 .endm
73
74 .macro stack_free size:req, reg1=r30, reg2=r31
75         in r0, _SFR_IO_ADDR(SREG)
76         cli
77         in \reg1, _SFR_IO_ADDR(SPL)
78         in \reg2, _SFR_IO_ADDR(SPH)
79         adiw \reg1, \size 
80         out _SFR_IO_ADDR(SPH), \reg2
81         out _SFR_IO_ADDR(SPL), \reg1
82         out _SFR_IO_ADDR(SREG), r0
83 .endm
84
85 /*******************************************************************************
86 * END of MACRO SECTION                                                         *
87 *******************************************************************************/
88
89 /*
90 static void serpent_lt(uint8_t *b){
91         X0 = rotl32(X0, 13);
92         X2 = rotl32(X2,  3);
93         X1 ^= X0 ^ X2;
94         X3 ^= X2 ^ (X0 << 3);
95         X1 = rotl32(X1, 1);
96         X3 = rotl32(X3, 7);
97         X0 ^= X1 ^ X3;
98         X2 ^= X3 ^ (X1 << 7);
99         X0 = rotl32(X0, 5);
100         X2 = rotr32(X2, 10);
101 }
102 */
103
104 #if 0
105 A0 =  4
106 A1 =  5
107 A2 =  6
108 A3 =  7
109 B0 =  8
110 B1 =  9
111 B2 = 10
112 B3 = 11
113 C0 = 12
114 C1 = 13
115 C2 = 14
116 C3 = 15
117 D0 = 16
118 D1 = 17
119 D2 = 18
120 D3 = 19
121 T0 = 20
122 T1 = 21
123 T2 = 22
124 T3 = 23
125
126 .global serpent_lt
127 serpent_lt:
128         push_range 4, 17
129         movw r26, r24
130         ld A2, X+
131         ld A3, X+
132         ld A0, X+
133         ld A1, X+
134         ldi r20, 3
135         mov r0, A0
136 1:      
137         lsr r0
138         ror A3
139         ror A2
140         ror A1
141         ror A0
142         dec r20
143         brne 1b
144         ld B0, X+
145         ld B1, X+
146         ld B2, X+
147         ld B3, X+
148         
149         ld C2, X+
150         ld C3, X+
151         ld C0, X+
152         ld C1, X+
153         ldi r20, 3
154         mov r0, C0
155 1:      
156         lsr r0
157         ror C3
158         ror C2
159         ror C1
160         ror C0
161         dec r20
162         brne 1b
163
164         ld D0, X+
165         ld D1, X+
166         ld D2, X+
167         ld D3, X+
168         /* X1 ^= X0 ^ X2; */
169         eor B0, A0
170         eor B0, C0
171         eor B1, A1
172         eor B1, C1
173         eor B2, A2
174         eor B2, C2
175         eor B3, A3
176         eor B3, C3
177         /* X3 ^= X2 ^ (X0 << 3); */
178         mov T0, A0
179         mov T1, A1
180         mov T2, A2
181         mov T3, A3
182         ldi r24, 3
183 1:
184         lsl T0
185         rol T1
186         rol T2
187         rol T3
188         dec r24
189         brne 1b
190         eor C0, B0
191         eor C0, T0
192         eor C1, B1
193         eor C1, T1
194         eor C2, B2
195         eor C2, T2
196         eor C3, B3
197         eor C3, T3
198         /*      X1 = rotl32(X1, 1); */
199         mov r0, B3
200         lsl r0
201         rol B0
202         rol B1
203         rol B2
204         rol B3
205         /* X3 = rotl32(X3, 7); */
206         mov r0, D3
207         mov D3, D2
208         mov D2, D1
209         mov D1, D0
210         mov D0, r0
211         lsr r0
212         ror D3
213         ror D2
214         ror D1
215         ror D0
216         /*      X0 ^= X1 ^ X3; */
217         eor A0, B0
218         eor A0, D0
219         eor A1, B1
220         eor A1, D1
221         eor A2, B2
222         eor A2, D2
223         eor A3, B3
224         eor A3, D3
225         /*  X2 ^= X3 ^ (X1 << 7); */
226         mov T1, B0
227         mov T2, B1
228         mov T3, B2
229         clr T0
230         mov r0, B3
231         lsr r0
232         ror T2
233         ror T1
234         ror T0 
235         eor C0, D0
236         eor C0, T0
237         eor C1, D1
238         eor C1, T1
239         eor C2, D2
240         eor C2, T2
241         eor C3, D3
242         eor C3, T3
243         /*      X0 = rotl32(X0, 5); */
244         ldi r24, 5
245         mov r0, A3
246 1:      
247         lsl r0
248         rol A0
249         rol A1
250         rol A2
251         rol A3
252         dec r24
253         brne 1b
254         /* X2 = rotr32(X2, 10); */
255         mov r0, C0
256         mov C0, C1
257         mov C1, C2
258         mov C2, C3      
259         mov C3, r0
260         ldi r24, 2
261 1:
262         lsr r0
263         ror C2
264         ror C1
265         ror C0
266         ror C3  
267         dec r24
268         brne 1b
269         
270         clr r31
271         ldi r30, D3+1
272         ldi r24, 16
273 1:
274         ld r0, -Z
275         st -X, r0       
276         dec r24
277         brne 1b
278         
279         pop_range 4, 17
280         ret
281
282 #endif
283 T0 = 22
284 T1 = 23
285 T2 = 24
286 T3 = 25
287 TT = 21
288 /* rotate the data word (4 byte) pointed to by X by r20 bits to the right */
289 memrotr32:
290         ld T0, X+
291         ld T1, X+
292         ld T2, X+
293         ld T3, X+
294         mov TT, T0
295 1:
296         lsr TT
297         ror T3
298         ror T2
299         ror T1
300         ror T0
301         dec r20
302         brne 1b
303         st -X, T3
304         st -X, T2
305         st -X, T1
306         st -X, T0
307         ret
308         
309 /* rotate the data word (4 byte) pointed to by X by r20 bits to the left */
310 memrotl32:
311         ld T0, X+
312         ld T1, X+
313         ld T2, X+
314         ld T3, X+
315         mov TT, T3
316 1:
317         lsl TT
318         rol T0
319         rol T1
320         rol T2
321         rol T3
322         dec r20
323         brne 1b
324         st -X, T3
325         st -X, T2
326         st -X, T1
327         st -X, T0
328         ret
329
330 /* xor the dataword (4 byte) pointed by Z into X */     
331 memeor32:
332   ldi T2, 4
333 1:  
334   ld T0, X              
335   ld T1, Z+
336   eor T0, T1
337   st X+, T0
338   dec T2
339   brne 1b
340   ret
341
342 .global serpent_lt
343 serpent_lt:
344          /* X0 := X0 <<< 13 */
345         movw r26, r24
346         ldi r20, 7
347         rcall memrotl32
348         ldi r20, 6
349         rcall memrotl32
350         /* X2 := X2 <<< 3 */
351         adiw r26, 8
352         ldi r20, 3
353         rcall memrotl32
354         /* X1 ^= X2 */
355         movw r30, r26
356         sbiw r26, 4
357         rcall memeor32
358         /* X1 ^= X0 */
359         sbiw r26, 4
360         sbiw r30, 12
361         rcall memeor32
362         /* X3 ^= X2 */
363         movw r30, r26
364         adiw r26, 4
365         rcall memeor32
366         /* T := X0 */
367         sbiw r26, 16
368         ld r18, X+
369         ld r19, X+
370         ld r20, X+
371         ld r21, X+
372         /* T := T<<3 */
373         ldi r22, 3
374 1:
375         lsl r18
376         rol r19
377         rol r20
378         rol r21
379         dec r22
380         brne 1b
381         clr r31 
382         /* X3 ^= T */
383         adiw r26, 8
384         ldi r30, 18
385         rcall memeor32
386         /* X1 := X1<<<1 */
387         sbiw r26, 12
388         ldi r20, 1
389         rcall memrotl32
390         /* X3 := X3<<<7 */
391         adiw r26, 8
392         ldi r20, 7
393         rcall memrotl32
394         /* X0 ^= X3 */
395         movw r30, r26
396         sbiw r26, 12
397         rcall memeor32
398         /* X0 ^= X1 */
399         movw r30, r26
400         sbiw r26, 4
401         rcall memeor32
402         /* X2 ^= X3 */
403         adiw r26, 4
404         adiw r30, 4
405         rcall memeor32
406         /* T := X1<<<8 */
407         sbiw r26, 8
408         ld r19, X+
409         ld r20, X+
410         ld r21, X+
411         ld r18, X+
412         /* T := T>>>1; T&=0xfffffff8 */
413         lsr r18
414         ror r21
415         ror r20
416         ror r19
417         clr r18
418         ror r18
419         clr r31
420         ldi r30, 18
421         /* X2 ^= T */
422         rcall memeor32
423         /* X0 := X0 <<< 5 */
424         sbiw r26, 12
425         ldi r20, 5
426         rcall memrotl32
427         /* X3 := X3 >>> 10 */
428         adiw r26, 8
429         ldi r20, 7
430         rcall memrotr32
431         ldi r20, 3
432         rcall memrotr32
433         ret
434
435 .global serpent_inv_lt
436 serpent_inv_lt:
437          /* X0 := X0 >>> 5 */
438         movw r26, r24
439         ldi r20, 5
440         rcall memrotr32
441         /* X2 := X2 <<< 10 */
442         adiw r26, 8
443         ldi r20, 7
444         rcall memrotl32
445         ldi r20, 3
446         rcall memrotl32
447         /* X2 ^= X3 */
448         movw r30, r26
449         adiw r30, 4
450         rcall memeor32
451         sbiw r26, 4
452         sbiw r30, 12
453         /* T := X1<<7 */
454         ld r19, Z+
455         ld r20, Z+
456         ld r21, Z+
457         ld r18, Z+
458         lsr r18
459         ror r21
460         ror r20
461         ror r19
462         clr r18
463         ror r18
464     clr r31
465     /* X2 ^= T */
466     ldi r30, 18
467     rcall memeor32
468     /* X0 ^= X1 */
469     sbiw r26, 12
470     movw r30, r26
471     adiw r30, 4
472     rcall memeor32
473     /* X0 ^= X3 */
474     sbiw r26, 4
475     adiw r30, 4
476     rcall memeor32
477     /* X1 := X1>>>1 */
478     ldi r20, 1
479         rcall memrotr32
480         /* X3 := X3>>>7 */
481         adiw r26, 8
482         ldi r20, 7
483         rcall memrotr32
484         /* X3 ^= X2 */
485         sbiw r30, 8
486         rcall memeor32
487         sbiw r26, 4
488         /* T:= X0<<3 */
489         sbiw r30, 12
490         ld r18, Z+
491         ld r19, Z+
492         ld r20, Z+
493         ld r21, Z+
494         ldi r24, 3
495 1:
496         lsl r18
497         rol r19
498         rol r20
499         rol r21
500         dec r24
501         brne 1b
502         /* X3 ^= T */
503         clr r31
504         ldi r30, 18
505         rcall memeor32
506         /* X1 ^= X0 */
507         sbiw r26, 12
508         movw r30, r26
509         sbiw r30, 4
510         rcall memeor32
511         /* X1 ^= X2 */
512         movw r26, r30
513         adiw r30, 4
514         rcall memeor32
515         /* X2 := X2 >>> 3 */
516         ldi r20, 3
517         rcall memrotr32
518         /* X0 := X0 >>> 13 */
519         sbiw r26, 8
520         ldi r20, 7
521         rcall memrotr32
522         ldi r20, 6
523         rcall memrotr32
524         ret
525
526 /*
527 #define GOLDEN_RATIO 0x9e3779b9l
528
529 static uint32_t serpent_gen_w(uint32_t * b, uint8_t i){
530         uint32_t ret;
531         ret = b[0] ^ b[3] ^ b[5] ^ b[7] ^ GOLDEN_RATIO ^ (uint32_t)i;
532         ret = rotl32(ret, 11);
533         return ret;
534 }
535 */
536 /*
537  * param b is passed in r24:r25
538  * param i is passed in r22
539  * return value is returned in r22.r23.r24.r25
540  */
541  /* trashes:
542   *  r20-r25, r30-r31
543   */
544 .global serpent_gen_w
545 serpent_gen_w:
546         movw r30, r24
547         /* ^i^b[0]*/
548     ld r21, Z+
549     eor r22, r21
550     ld r23, Z+
551     ld r24, Z+
552     ld r25, Z+
553     /* ^b[3]^b[5]^[b7] */
554     adiw r30, 4
555     ldi r20, 3
556 1:    
557     adiw r30, 4
558     ld r21, Z+
559     eor r22, r21
560     ld r21, Z+
561     eor r23, r21
562     ld r21, Z+
563     eor r24, r21
564     ld r21, Z+
565     eor r25, r21
566         dec r20
567         brne 1b
568         /* ^0x9e3779b9l */
569         ldi r21, 0xb9
570         eor r22, r21
571         ldi r21, 0x79
572         eor r23, r21
573         ldi r21, 0x37
574         eor r24, r21
575         ldi r21, 0x9e
576         eor r25, r21
577         /* <<<11 */
578         mov r21, r25
579         mov r25, r24
580         mov r24, r23
581         mov r23, r22
582         mov r22, r21
583         mov r21, r25
584         ldi r20, 3
585 1:
586         lsl r21
587         rol r22
588         rol r23
589         rol r24
590         rol r25
591         dec r20
592         brne 1b
593         ret
594
595 /*
596  * void serpent_init(const void* key, uint16_t keysize_b, serpent_ctx_t* ctx)
597  */
598 /*
599  * param key     is passed in r24:r25
600  * param keysize is passed in r22:r23
601  * param ctx     is passed in r20:r21
602  */
603 .global serpent_init
604 serpent_init:
605     stack_alloc 32
606     adiw r30, 1
607         push_ r30, r31
608     movw r26, r22
609     adiw r26, 7
610     tst r27
611     breq 1f
612         ldi r26, 32
613         rjmp 2f
614 1:
615         lsr r26
616         lsr r26
617         lsr r26
618 2:      
619         mov r22, r26
620         bst r22, 5 /* store in T if we have to do the "append 1 thing"*/
621         ldi r27, 32
622 3:      /* set buffer to zero */
623         st Z+, r1
624         dec r27
625         brne 3b
626         
627         movw r26, r24 /* X points to the key */
628         sbiw r30, 32
629         tst r22
630         breq 5f /* if keylength_b==0 */
631 4:      /* copy keybytes to buffer */
632         ld r19, X+
633         st Z+, r19
634         dec r22
635         brne 4b
636 5:
637         brts 7f /* if keylength_b == 256 */
638         ldi r18, 0x01
639         andi r22, 0x07
640         brne 6f
641         st Z, r18
642         rjmp 7f
643 6:      /* shift the one to the right position */
644         lsl r18
645         dec r22
646         brne 6b
647         or r18, r19
648         st -Z, r18
649 7: /* post "appending 1 thing" buffer is ready for subkey generation */
650         movw r26, r20  /* X points to the context */
651         
652         pop_ r19, r18 /* r18:r19 points to the buffer */
653         push r16
654         clr r16
655 8:
656         movw r24, r18
657         mov  r22, r16
658         rcall serpent_gen_w
659         movw r30, r18
660         ldi r20, 7*4
661 1: /* the memmove */
662         ldd r0, Z+4
663         st Z+, r0
664         dec r20
665         brne 1b
666   /* store new word in buffer and context */    
667         st Z+, r22
668         st Z+, r23
669         st Z+, r24
670         st Z+, r25
671         st X+, r22
672         st X+, r23
673         st X+, r24
674         st X+, r25
675         
676         inc r16
677         cpi r16, 132
678         brne 8b 
679         
680         push_ r28, r29
681         movw r28, r26
682         subi r28, lo8(132*4)
683         sbci r29, hi8(132*4)
684         ldi r16, 33
685 2:
686         movw r24, r28
687         adiw r28, 16
688         ldi r22, 2
689         add r22, r16
690         rcall sbox128
691         dec r16
692         brne 2b
693         pop_ r29, r28, r16
694         stack_free 32
695         ret
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711