]> git.cryptolib.org Git - avr-crypto-lib.git/blob - serpent-asm.S
56c5dd038888d6d5fa05b8d5f6896d0616cb41b7
[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 serpent_lt:
127         push_range 4, 17
128         movw r26, r24
129         ld A2, X+
130         ld A3, X+
131         ld A0, X+
132         ld A1, X+
133         ldi r20, 3
134         mov r0, A0
135 1:      
136         lsr r0
137         ror A3
138         ror A2
139         ror A1
140         ror A0
141         dec r20
142         brne 1b
143         ld B0, X+
144         ld B1, X+
145         ld B2, X+
146         ld B3, X+
147         
148         ld C2, X+
149         ld C3, X+
150         ld C0, X+
151         ld C1, X+
152         ldi r20, 3
153         mov r0, C0
154 1:      
155         lsr r0
156         ror C3
157         ror C2
158         ror C1
159         ror C0
160         dec r20
161         brne 1b
162
163         ld D0, X+
164         ld D1, X+
165         ld D2, X+
166         ld D3, X+
167         /* X1 ^= X0 ^ X2; */
168         eor B0, A0
169         eor B0, C0
170         eor B1, A1
171         eor B1, C1
172         eor B2, A2
173         eor B2, C2
174         eor B3, A3
175         eor B3, C3
176         /* X3 ^= X2 ^ (X0 << 3); */
177         mov T0, A0
178         mov T1, A1
179         mov T2, A2
180         mov T3, A3
181         ldi r24, 3
182 1:
183         lsl T0
184         rol T1
185         rol T2
186         rol T3
187         dec r24
188         brne 1b
189         eor C0, B0
190         eor C0, T0
191         eor C1, B1
192         eor C1, T1
193         eor C2, B2
194         eor C2, T2
195         eor C3, B3
196         eor C3, T3
197         /*      X1 = rotl32(X1, 1); */
198         mov r0, B3
199         lsl r0
200         rol B0
201         rol B1
202         rol B2
203         rol B3
204         /* X3 = rotl32(X3, 7); */
205         mov r0, D3
206         mov D3, D2
207         mov D2, D1
208         mov D1, D0
209         mov D0, r0
210         lsr r0
211         ror D3
212         ror D2
213         ror D1
214         ror D0
215         /*      X0 ^= X1 ^ X3; */
216         eor A0, B0
217         eor A0, D0
218         eor A1, B1
219         eor A1, D1
220         eor A2, B2
221         eor A2, D2
222         eor A3, B3
223         eor A3, D3
224         /*  X2 ^= X3 ^ (X1 << 7); */
225         mov T1, B0
226         mov T2, B1
227         mov T3, B2
228         clr T0
229         mov r0, B3
230         lsr r0
231         ror T2
232         ror T1
233         ror T0 
234         eor C0, D0
235         eor C0, T0
236         eor C1, D1
237         eor C1, T1
238         eor C2, D2
239         eor C2, T2
240         eor C3, D3
241         eor C3, T3
242         /*      X0 = rotl32(X0, 5); */
243         ldi r24, 5
244         mov r0, A3
245 1:      
246         lsl r0
247         rol A0
248         rol A1
249         rol A2
250         rol A3
251         dec r24
252         brne 1b
253         /* X2 = rotr32(X2, 10); */
254         mov r0, C0
255         mov C0, C1
256         mov C1, C2
257         mov C2, C3      
258         mov C3, r0
259         ldi r24, 2
260 1:
261         lsr r0
262         ror C2
263         ror C1
264         ror C0
265         ror C3  
266         dec r24
267         brne 1b
268         
269         clr r31
270         ldi r30, D3+1
271         ldi r24, 16
272 1:
273         ld r0, -Z
274         st -X, r0       
275         dec r24
276         brne 1b
277         
278         pop_range 4, 17
279         ret
280 #endif
281
282 T0 = 22
283 T1 = 23
284 T2 = 24
285 T3 = 25
286 TT = 21
287 /* rotate the data word (4 byte) pointed to by X by r20 bits to the right */
288 memrotr32:
289         ld T0, X+
290         ld T1, X+
291         ld T2, X+
292         ld T3, X+
293         mov TT, T0
294 1:
295         lsr TT
296         ror T3
297         ror T2
298         ror T1
299         ror T0
300         dec r20
301         brne 1b
302         st -X, T3
303         st -X, T2
304         st -X, T1
305         st -X, T0
306         ret
307         
308 /* rotate the data word (4 byte) pointed to by X by r20 bits to the left */
309 memrotl32:
310         ld T0, X+
311         ld T1, X+
312         ld T2, X+
313         ld T3, X+
314         mov TT, T3
315 1:
316         lsl TT
317         rol T0
318         rol T1
319         rol T2
320         rol T3
321         dec r20
322         brne 1b
323         st -X, T3
324         st -X, T2
325         st -X, T1
326         st -X, T0
327         ret
328
329 /* xor the dataword (4 byte) pointed by Z into X */     
330 memeor32:
331   ldi T2, 4
332 1:  
333   ld T0, X              
334   ld T1, Z+
335   eor T0, T1
336   st X+, T0
337   dec T2
338   brne 1b
339   ret
340
341 serpent_lt:
342          /* X0 := X0 <<< 13 */
343         movw r26, r24
344         ldi r20, 7
345         rcall memrotl32
346         ldi r20, 6
347         rcall memrotl32
348         /* X2 := X2 <<< 3 */
349         adiw r26, 8
350         ldi r20, 3
351         rcall memrotl32
352         /* X1 ^= X2 */
353         movw r30, r26
354         sbiw r26, 4
355         rcall memeor32
356         /* X1 ^= X0 */
357         sbiw r26, 4
358         sbiw r30, 12
359         rcall memeor32
360         /* X3 ^= X2 */
361         movw r30, r26
362         adiw r26, 4
363         rcall memeor32
364         /* T := X0 */
365         sbiw r26, 16
366         ld r18, X+
367         ld r19, X+
368         ld r20, X+
369         ld r21, X+
370         /* T := T<<3 */
371         ldi r22, 3
372 1:
373         lsl r18
374         rol r19
375         rol r20
376         rol r21
377         dec r22
378         brne 1b
379         clr r31 
380         /* X3 ^= T */
381         adiw r26, 8
382         ldi r30, 18
383         rcall memeor32
384         /* X1 := X1<<<1 */
385         sbiw r26, 12
386         ldi r20, 1
387         rcall memrotl32
388         /* X3 := X3<<<7 */
389         adiw r26, 8
390         ldi r20, 7
391         rcall memrotl32
392         /* X0 ^= X3 */
393         movw r30, r26
394         sbiw r26, 12
395         rcall memeor32
396         /* X0 ^= X1 */
397         movw r30, r26
398         sbiw r26, 4
399         rcall memeor32
400         /* X2 ^= X3 */
401         adiw r26, 4
402         adiw r30, 4
403         rcall memeor32
404         /* T := X1<<<8 */
405         sbiw r26, 8
406         ld r19, X+
407         ld r20, X+
408         ld r21, X+
409         ld r18, X+
410         /* T := T>>>1; T&=0xfffffff8 */
411         lsr r18
412         ror r21
413         ror r20
414         ror r19
415         clr r18
416         ror r18
417         clr r31
418         ldi r30, 18
419         /* X2 ^= T */
420         rcall memeor32
421         /* X0 := X0 <<< 5 */
422         sbiw r26, 12
423         ldi r20, 5
424         rcall memrotl32
425         /* X3 := X3 >>> 10 */
426         adiw r26, 8
427         ldi r20, 7
428         rcall memrotr32
429         ldi r20, 3
430         rcall memrotr32
431         ret
432
433 serpent_inv_lt:
434          /* X0 := X0 >>> 5 */
435         movw r26, r24
436         ldi r20, 5
437         rcall memrotr32
438         /* X2 := X2 <<< 10 */
439         adiw r26, 8
440         ldi r20, 7
441         rcall memrotl32
442         ldi r20, 3
443         rcall memrotl32
444         /* X2 ^= X3 */
445         movw r30, r26
446         adiw r30, 4
447         rcall memeor32
448         sbiw r26, 4
449         sbiw r30, 12
450         /* T := X1<<7 */
451         ld r19, Z+
452         ld r20, Z+
453         ld r21, Z+
454         ld r18, Z+
455         lsr r18
456         ror r21
457         ror r20
458         ror r19
459         clr r18
460         ror r18
461     clr r31
462     /* X2 ^= T */
463     ldi r30, 18
464     rcall memeor32
465     /* X0 ^= X1 */
466     sbiw r26, 12
467     movw r30, r26
468     adiw r30, 4
469     rcall memeor32
470     /* X0 ^= X3 */
471     sbiw r26, 4
472     adiw r30, 4
473     rcall memeor32
474     /* X1 := X1>>>1 */
475     ldi r20, 1
476         rcall memrotr32
477         /* X3 := X3>>>7 */
478         adiw r26, 8
479         ldi r20, 7
480         rcall memrotr32
481         /* X3 ^= X2 */
482         sbiw r30, 8
483         rcall memeor32
484         sbiw r26, 4
485         /* T:= X0<<3 */
486         sbiw r30, 12
487         ld r18, Z+
488         ld r19, Z+
489         ld r20, Z+
490         ld r21, Z+
491         ldi r24, 3
492 1:
493         lsl r18
494         rol r19
495         rol r20
496         rol r21
497         dec r24
498         brne 1b
499         /* X3 ^= T */
500         clr r31
501         ldi r30, 18
502         rcall memeor32
503         /* X1 ^= X0 */
504         sbiw r26, 12
505         movw r30, r26
506         sbiw r30, 4
507         rcall memeor32
508         /* X1 ^= X2 */
509         movw r26, r30
510         adiw r30, 4
511         rcall memeor32
512         /* X2 := X2 >>> 3 */
513         ldi r20, 3
514         rcall memrotr32
515         /* X0 := X0 >>> 13 */
516         sbiw r26, 8
517         ldi r20, 7
518         rcall memrotr32
519         ldi r20, 6
520         rcall memrotr32
521         ret
522
523 /*
524 #define GOLDEN_RATIO 0x9e3779b9l
525
526 static uint32_t serpent_gen_w(uint32_t * b, uint8_t i){
527         uint32_t ret;
528         ret = b[0] ^ b[3] ^ b[5] ^ b[7] ^ GOLDEN_RATIO ^ (uint32_t)i;
529         ret = rotl32(ret, 11);
530         return ret;
531 }
532 */
533 /*
534  * param b is passed in r24:r25
535  * param i is passed in r22
536  * return value is returned in r22.r23.r24.r25
537  */
538  /* trashes:
539   *  r20-r25, r30-r31
540   */
541 serpent_gen_w:
542         movw r30, r24
543         /* ^i^b[0]*/
544     ld r21, Z+
545     eor r22, r21
546     ld r23, Z+
547     ld r24, Z+
548     ld r25, Z+
549     /* ^b[3]^b[5]^[b7] */
550     adiw r30, 4
551     ldi r20, 3
552 1:    
553     adiw r30, 4
554     ld r21, Z+
555     eor r22, r21
556     ld r21, Z+
557     eor r23, r21
558     ld r21, Z+
559     eor r24, r21
560     ld r21, Z+
561     eor r25, r21
562         dec r20
563         brne 1b
564         /* ^0x9e3779b9l */
565         ldi r21, 0xb9
566         eor r22, r21
567         ldi r21, 0x79
568         eor r23, r21
569         ldi r21, 0x37
570         eor r24, r21
571         ldi r21, 0x9e
572         eor r25, r21
573         /* <<<11 */
574         mov r21, r25
575         mov r25, r24
576         mov r24, r23
577         mov r23, r22
578         mov r22, r21
579         mov r21, r25
580         ldi r20, 3
581 1:
582         lsl r21
583         rol r22
584         rol r23
585         rol r24
586         rol r25
587         dec r20
588         brne 1b
589         ret
590
591 /*
592  * void serpent_init(const void* key, uint16_t keysize_b, serpent_ctx_t* ctx)
593  */
594 /*
595  * param key     is passed in r24:r25
596  * param keysize is passed in r22:r23
597  * param ctx     is passed in r20:r21
598  */
599 .global serpent_init
600 serpent_init:
601     stack_alloc 32
602     adiw r30, 1
603         push_ r30, r31
604     movw r26, r22
605     adiw r26, 7
606     tst r27
607     breq 1f
608         ldi r26, 32
609         rjmp 2f
610 1:
611         lsr r26
612         lsr r26
613         lsr r26
614 2:      
615         mov r22, r26
616         bst r22, 5 /* store in T if we have to do the "append 1 thing"*/
617         ldi r27, 32
618 3:      /* set buffer to zero */
619         st Z+, r1
620         dec r27
621         brne 3b
622         
623         movw r26, r24 /* X points to the key */
624         sbiw r30, 32
625         tst r22
626         breq 5f /* if keylength_b==0 */
627 4:      /* copy keybytes to buffer */
628         ld r19, X+
629         st Z+, r19
630         dec r22
631         brne 4b
632 5:
633         brts 7f /* if keylength_b == 256 */
634         ldi r18, 0x01
635         andi r22, 0x07
636         brne 6f
637         st Z, r18
638         rjmp 7f
639 6:      /* shift the one to the right position */
640         lsl r18
641         dec r22
642         brne 6b
643         or r18, r19
644         st -Z, r18
645 7: /* post "appending 1 thing" buffer is ready for subkey generation */
646         movw r26, r20  /* X points to the context */
647         
648         pop_ r19, r18 /* r18:r19 points to the buffer */
649         push r16
650         clr r16
651 8:
652         movw r24, r18
653         mov  r22, r16
654         rcall serpent_gen_w
655         movw r30, r18
656         ldi r20, 7*4
657 1: /* the memmove */
658         ldd r0, Z+4
659         st Z+, r0
660         dec r20
661         brne 1b
662   /* store new word in buffer and context */    
663         st Z+, r22
664         st Z+, r23
665         st Z+, r24
666         st Z+, r25
667         st X+, r22
668         st X+, r23
669         st X+, r24
670         st X+, r25
671         
672         inc r16
673         cpi r16, 132
674         brne 8b 
675         
676         push_ r28, r29
677         movw r28, r26
678         subi r28, lo8(132*4)
679         sbci r29, hi8(132*4)
680         ldi r16, 33
681 2:
682         movw r24, r28
683         adiw r28, 16
684         ldi r22, 2
685         add r22, r16
686         rcall sbox128
687         dec r16
688         brne 2b
689         pop_ r29, r28, r16
690         stack_free 32
691         ret
692
693 /*
694  * void serpent_enc(void* buffer, const serpent_ctx_t* ctx){
695  */
696 /*
697  * param buffer is passed in r24:r25
698  * param ctx    is passed in r22:r23
699  */
700 .global serpent_enc
701 serpent_enc:
702
703         push_ r12, r13, r14, r15, r16 
704         clr r16
705         movw r14, r24
706         movw r12, r22
707 1:
708         movw r24, r14
709         movw r22, r12
710         ldi r20, 16
711         add r12, r20
712         adc r13, r1
713         clr r21
714         rcall memxor
715         movw r24, r14
716         mov r22, r16
717         rcall sbox128
718         movw r24, r14
719         rcall serpent_lt
720         
721         inc r16
722         cpi r16, 31
723         brne 1b
724         
725         movw r24, r14
726         movw r22, r12
727         ldi r20, 16
728         add r12, r20
729         adc r13, r1
730         clr r21
731         rcall memxor
732         movw r24, r14
733         mov r22, r16
734         rcall sbox128
735         
736         inc r16
737         movw r24, r14
738         movw r22, r12
739         ldi r20, 16
740         clr r21
741         pop_ r16, r15, r14, r13, r12
742         rjmp memxor
743
744 /*
745  * void serpent_dec(void* buffer, const serpent_ctx_t* ctx){
746  */
747 /*
748  * param buffer is passed in r24:r25
749  * param ctx    is passed in r22:r23
750  */
751 .global serpent_dec
752 serpent_dec:
753         push_ r12, r13, r14, r15, r16 
754         movw r14, r24
755 //      ldi r16, lo8(32*16)
756 //      add r22, r16
757         ldi r16, hi8(32*16)
758         add r23, r16
759         movw r12, r22
760         ldi r20, 16
761         clr r21
762         rcall memxor
763         
764         movw r24, r14
765         ldi r22, 31
766         rcall inv_sbox128
767         
768         movw r24, r14
769         ldi r20, 16
770         sub r12, r20
771         sbc r13, r1
772         movw r22, r12
773         clr r21
774         rcall memxor
775         ldi r16, 31
776 1:
777         dec r16
778         movw r24, r14
779         rcall serpent_inv_lt
780         movw r24, r14
781         mov r22, r16
782         rcall inv_sbox128
783         movw r24, r14
784         ldi r20, 16
785         sub r12, r20
786         sbc r13, r1
787         movw r22, r12
788         clr r21
789         rcall memxor
790         
791         tst r16
792         brne 1b
793         pop_ r16, r15, r14, r13, r12
794         ret     
795         
796         
797         
798
799
800
801
802
803
804
805
806
807
808
809
810
811