]> git.cryptolib.org Git - avr-crypto-lib.git/blob - noekeon_asm.S
Cast6 (aka Cast-256) now seems to work
[avr-crypto-lib.git] / noekeon_asm.S
1 /* noekeon_asm.S */
2 /*
3     This file is part of the AVR-Crypto-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  * noekeon assembler implementation for avr
21  * author: Daniel Otte
22  * email:  daniel.otte@rub.de
23  * license: GPLv3
24  */
25
26 #include <avr/io.h>
27
28 .macro push_all
29         push r2
30         push r3
31         push r4
32         push r5
33         push r6
34         push r7
35         push r8
36         push r9
37         push r10
38         push r11
39         push r12
40         push r13
41         push r14
42         push r15
43         push r16
44         push r17
45         push r28
46         push r29
47 .endm
48
49 .macro pop_all
50         pop r29
51         pop r28
52         pop r17
53         pop r16
54         pop r15
55         pop r14
56         pop r13
57         pop r12
58         pop r11
59         pop r10
60         pop r9
61         pop r8
62         pop r7
63         pop r6
64         pop r5
65         pop r4
66         pop r3
67         pop r2
68         clr r1
69 .endm
70
71 push_all_func:
72         pop r31
73         pop r30
74         push_all
75         ijmp
76
77 pop_all_func:
78     pop r31
79     pop r30
80     pop_all
81     ijmp
82
83 .macro xchg a b
84         eor \a, \b
85         eor \b, \a
86         eor \a, \b
87 .endm
88
89 .macro op32 op a b
90         \op \a\()_0, \b\()_0
91         \op \a\()_1, \b\()_1
92         \op \a\()_2, \b\()_2
93         \op \a\()_3, \b\()_3
94 .endm
95
96
97 .macro op32_4t op a b c d w x y z
98         \op \a, \w
99         \op \b, \x
100         \op \c, \y
101         \op \d, \z
102 .endm
103
104
105 .macro op32_prefix op p q a b c d w x y z
106         \op \p\()\a, \q\()\w
107         \op \p\()\b, \q\()\x
108         \op \p\()\c, \q\()\y
109         \op \p\()\d, \q\()\z
110 .endm
111
112 ; === bigendian_rotl32 ===
113 ; this function rotates a 32bit bigendian word n bits to the left
114 ;  param1: the 32-bit value
115 ;       given in r25,r24,r23,r22 (r22 is most significant)
116 ;  param2: the 8-bit parameter giving the number of bits to rotate
117 ;       given in r20
118 ;  return: the rotatet 32-bit word
119 ;   given in r25,r24,r23,r22   
120
121 bigendian_rotl32:
122         /* copy high bit of r22 to carry */
123         mov r1, r22
124 2:
125         rol r1
126
127         rol r25
128         rol r24
129         rol r23
130         rol r22
131         
132         dec r20
133         brne 2b
134 bigendian_rotl32_exit:
135         clr r1
136         ret
137         
138         
139 /******************************************************************************/
140
141 ; === bigendian_rotl32 ===
142 ; this function rotates a 32bit bigendian word n bits to the right
143 ;  param1: the 32-bit value
144 ;       given in r25,r24,r23,r22 (r22 is most significant)
145 ;  param2: the 8-bit parameter giving the number of bits to rotate
146 ;       given in r20
147 ;  return: the rotatet 32-bit word
148 ;   given in r25,r24,r23,r22   
149
150 bigendian_rotr32:
151         /* copy high bit of r25 to carry */
152
153         mov r1, r25
154 2:
155         ror r1
156         
157         ror r22
158         ror r23
159         ror r24
160         ror r25
161         dec r20
162         brne 2b
163 bigendian_rotr32_exit:
164         clr r1
165         ret
166
167 /******************************************************************************/
168 /*
169 void theta(uint32_t* k, uint32_t* a){
170         uint32_t temp;
171         temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
172         a[1] ^= temp;
173         a[3] ^= temp;
174         
175         a[0] ^= k[0];
176         a[1] ^= k[1];
177         a[2] ^= k[2];
178         a[3] ^= k[3];
179
180         temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
181         a[0] ^= temp;
182         a[2] ^= temp;   
183 }
184 */
185
186 round_const: .byte    0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, \
187                     0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, \
188                 0xD4
189
190 ;-- a[0]
191 state0_0 =  2
192 state0_1 =  3
193 state0_2 =  4
194 state0_3 =  5
195 ;-- a[1]
196 state1_0 =  6
197 state1_1 =  7
198 state1_2 =  8
199 state1_3 =  9
200 ;-- a[2]
201 state2_0 = 10
202 state2_1 = 11
203 state2_2 = 12
204 state2_3 = 13
205 ;-- a[3]
206 state3_0 = 14
207 state3_1 = 15
208 state3_2 = 16
209 state3_3 = 17
210
211 ; === theta ===
212 ;
213 ;  param1: the state in r2-r17
214 ;  param2: pointer to k in X (r26,r27)
215 ;
216 temp_a = 18
217 temp_b = 19
218 temp_c = 20
219 temp_d = 21
220
221 theta:
222         /* temp = a[0] ^ a[2]; temp ^= temp>>>8 ^ temp<<<8 */
223         op32_prefix mov, temp_, state0_, a,b,c,d, 0,1,2,3
224         op32_prefix eor, temp_, state2_, a,b,c,d, 0,1,2,3
225
226         mov r1, temp_a
227         eor r1, temp_b
228         eor r1, temp_c
229         eor r1, temp_d
230         
231         op32_prefix eor, temp_, r, a,b,c,d, 1,1,1,1
232
233         /* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */
234         /* a[1] ^= temp */
235         eor state1_0, temp_c 
236         eor state1_1, temp_d 
237         eor state1_2, temp_a 
238         eor state1_3, temp_b
239         /* a[3] ^= temp */
240         eor state3_0, temp_c 
241         eor state3_1, temp_d 
242         eor state3_2, temp_a 
243         eor state3_3, temp_b
244         
245         /* state ^ k (X points to K) */
246         ldi r28, 2
247         clr r29 /* Y points to r2 aka state0_0 */
248         ldi temp_a, 16
249 1:      
250         ld r1, X+
251         ld r0, Y
252         eor r1, r0
253         st Y+, r1
254         dec temp_a
255         brne 1b
256         sbiw r26, 16 /* set X back to key */ 
257         
258         mov temp_a, state1_0
259         mov temp_b, state1_1
260         mov temp_c, state1_2
261         mov temp_d, state1_3
262         eor temp_a, state3_0
263         eor temp_b, state3_1
264         eor temp_c, state3_2
265         eor temp_d, state3_3
266         mov r1, temp_a
267         eor r1, temp_b
268         eor r1, temp_c
269         eor r1, temp_d
270         eor temp_a, r1
271         eor temp_b, r1
272         eor temp_c, r1
273         eor temp_d, r1
274         /* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */
275         /* a[0] ^= temp */
276         eor state0_0, temp_c 
277         eor state0_1, temp_d 
278         eor state0_2, temp_a 
279         eor state0_3, temp_b
280         /* a[2] ^= temp */
281         eor state2_0, temp_c 
282         eor state2_1, temp_d 
283         eor state2_2, temp_a 
284         eor state2_3, temp_b
285         
286         clr r1
287         ret
288
289 /******************************************************************************/
290 #ifndef NOEKEON_NO_ENC
291 ; === noekeon_enc ===
292 ;
293 ;  param1: pointer to buffer (r24,r25)
294 ;  param2: pointer to k (r22,r23) 
295 ;
296 .global noekeon_enc
297 noekeon_enc:
298         rcall push_all_func
299         /* load state */
300         movw r26, r22
301         ldi r28, 2
302         clr r29 /* Y points at r2 aka state0_0 */
303         movw r30, r24 /* Z points at state */
304         push r30
305         push r31
306         ldi r22, 16
307         push r22 /* 16 is also the number of rounds and gets pushed here */
308 1:      
309         ld r0, Z+
310         st Y+, r0
311         dec r22
312         brne 1b
313         /* state loaded */
314         push r1 /* push round constan2 (0x00) */
315         ldi r20, 0x80
316         push r20 /* push round constan2 (0x00) */
317         rjmp 3f
318 2:
319         ldi r30, lo8(round_const+15)
320         ldi r31, hi8(round_const+15)
321         sub r30, r22
322         sbci r31, 0
323         clr r1
324         push r1
325         lpm r0, Z
326         push r0
327 3:
328         rcall round /* pops rc2 & rc1 */
329         pop r22
330         dec r22
331         push r22
332         brne 2b
333
334         pop r22
335
336         ldi r22, 0xD4
337         eor state0_3, r22
338         rcall theta
339
340         pop r31
341         pop r30
342         clr r29
343         ldi r28, 2
344         ldi r22, 16
345 1:      
346         ld r0, Y+
347         st Z+, r0
348         dec r22
349         brne 1b
350         
351         rcall pop_all_func
352         ret
353 #endif
354 /******************************************************************************/
355 /******************************************************************************/
356 #ifndef NOEKEON_NO_DEC
357
358 ; === noekeon_dec ===
359 ;
360 ;  param1: pointer to buffer/state (r24,r25)
361 ;  param2: pointer to k  (r22,r23) 
362 ;
363 .global noekeon_dec
364 noekeon_dec:
365         rcall push_all_func
366         /* allocate 16 bytes on the stack */
367         in r30, _SFR_IO_ADDR(SPL)
368         in r31, _SFR_IO_ADDR(SPH)
369         sbiw r30, 16 
370         out  _SFR_IO_ADDR(SPH), r31
371         out  _SFR_IO_ADDR(SPL), r30
372
373         adiw r30, 1
374         /* push state pointer */
375         push r24
376         push r25
377         movw r26, r22 /* move key ptr to X */
378
379         /* set stackkey to zero */
380         ldi r22, 16
381 1:      st Z+, r1
382         dec r22
383         brne 1b
384                 
385         /* copy key to state */
386         clr r29
387         ldi r28, 2
388         ldi r22, 16
389 1:  ld r0, X+
390         st Y+, r0
391         dec r22
392         brne 1b 
393
394         movw r26, r30
395         sbiw r26, 16 /* set X back to begining of stack key */
396         rcall theta
397         
398         /* mov state to stackkey */
399         clr r29
400         ldi r28,  2
401         ldi r22, 16
402 1:      ld r0, Y+
403         st X+, r0       
404         dec r22
405         brne 1b
406         sbiw r26, 16 /* set X back to begining of stack key */
407         
408         /* move data from stateptr to state */
409         pop r31
410         pop r30
411         push r30
412         push r31
413         clr r29
414         ldi r28,  2
415         ldi r22, 16
416         push r22
417 1:      ld r0, Z+
418         st Y+, r0
419         dec r22
420         brne 1b 
421         
422 ;--- snip 8< ----
423         
424         ldi r20, 0xD4
425         push r20 /* push round constant2 (0xD4) */
426         push r22 /* push round constan1 (0x00) */
427         rjmp 3f
428 2:
429         ldi r30, lo8(round_const-1)
430         ldi r31, hi8(round_const-1)
431         clr r1
432         add r30, r22
433         adc r31, r1
434         lpm r0, Z
435         push r0
436         push r1
437 3:
438         rcall round /* pops rc2 & rc1 */
439         pop r22
440         dec r22
441         push r22
442         brne 2b
443 ;----
444         pop r22
445
446         rcall theta
447         ldi r22, 0x80
448         eor state0_3, r22
449         
450 write_state_back:       
451         /* write state back */
452         pop r31 /* pop state pointer */
453         pop r30
454         clr r29
455         ldi r28, 2
456         ldi r22, 16
457 1:      
458         ld r0, Y+
459         st Z+, r0
460         dec r22
461         brne 1b
462         
463         /* remove key from stack */
464         in r30, _SFR_IO_ADDR(SPL)
465         in r31, _SFR_IO_ADDR(SPH)
466         adiw r30, 16 
467         out  _SFR_IO_ADDR(SPH), r31
468         out  _SFR_IO_ADDR(SPL), r30
469         rcall pop_all_func
470         ret
471 #endif
472 /******************************************************************************/
473         
474         
475 round:  
476         pop r24
477         pop r25
478         pop r1
479         eor state0_3, r1
480         rcall theta
481         pop r1
482         eor state0_3, r1
483         push r25
484         push r24
485 pi_gamma_pi:
486         ldi r30, pm_lo8(bigendian_rotl32)
487         ldi r31, pm_hi8(bigendian_rotl32)
488         rcall pi
489         /* pi1 done; now gamma */
490         rcall gamma_1
491         /* a[0] <-> a[3] */
492         xchg state0_0, state3_0
493         xchg state0_1, state3_1
494         xchg state0_2, state3_2
495         xchg state0_3, state3_3
496         /* a[2] ^= a[0] ^ a[1] ^ a[3] */
497         op32 eor, state2, state0
498         op32 eor, state2, state1
499         op32 eor, state2, state3
500
501         rcall gamma_1
502         ldi r30, pm_lo8(bigendian_rotr32)
503         ldi r31, pm_hi8(bigendian_rotr32)
504         rcall pi
505         ret
506         
507 gamma_1:
508         /* a[1] ^= ~(a[3]|a[2])*/
509         mov r1, state3_0
510         or  r1, state2_0
511         com r1
512         eor state1_0, r1
513
514         mov r1, state3_1
515         or  r1, state2_1
516         com r1
517         eor state1_1, r1
518
519         mov r1, state3_2
520         or  r1, state2_2
521         com r1
522         eor state1_2, r1
523         
524         mov r1, state3_3
525         or  r1, state2_3
526         com r1
527         eor state1_3, r1
528         
529         /* a[0] ^= a[2]&a[1] */
530         mov r1, state2_0
531         and r1, state1_0
532         eor state0_0, r1
533         
534         mov r1, state2_1
535         and r1, state1_1
536         eor state0_1, r1
537         
538         mov r1, state2_2
539         and r1, state1_2
540         eor state0_2, r1
541         
542         mov r1, state2_3
543         and r1, state1_3
544         eor state0_3, r1
545         ret
546         
547 pi:     
548         /* a[1] <<<= 1*/
549         mov r22, state1_0
550         mov r23, state1_1
551         mov r24, state1_2
552         mov r25, state1_3
553         ldi r20, 1
554         icall
555         mov state1_0, r22
556         mov state1_1, r23
557         mov state1_2, r24
558         mov state1_3, r25
559         /* a[2] <<<= 5*/
560         mov r22, state2_0
561         mov r23, state2_1
562         mov r24, state2_2
563         mov r25, state2_3
564         ldi r20, 5
565         icall
566         mov state2_0, r22
567         mov state2_1, r23
568         mov state2_2, r24
569         mov state2_3, r25
570         /* a[3] <<<= 2*/
571         mov r22, state3_0
572         mov r23, state3_1
573         mov r24, state3_2
574         mov r25, state3_3
575         ldi r20, 2
576         icall
577         mov state3_0, r22
578         mov state3_1, r23
579         mov state3_2, r24
580         mov state3_3, r25
581         ret
582
583 /******************************************************************************/
584         
585 /*
586 void noekeon_init(void* key, noekeon_ctx_t* ctx){
587         uint8_t nullv[16];
588         
589         memset(nullv, 0, 16);
590         memcpy(ctx, key, 16);
591         noekeon_enc(ctx, nullv);
592 }
593 */
594
595 #ifndef NOEKEON_NO_INIT
596
597 .global noekeon_init
598 noekeon_init:
599 ; === noekeon_init ===
600 ;
601 ;  param1: pointer to key (r24,r25)
602 ;  param2: pointer to context  (r22,r23) 
603 ;
604         in r30, _SFR_IO_ADDR(SPL)
605         in r31, _SFR_IO_ADDR(SPH)
606         sbiw r30, 16 
607         out  _SFR_IO_ADDR(SPH), r31
608         out  _SFR_IO_ADDR(SPL), r30
609
610         movw r26, r22
611         adiw r30, 1
612         movw r22, r30
613         /* set nullv(stack) to zero */
614         ldi r20, 16
615 1:      st Z+, r1
616         dec r20
617         brne 1b
618
619         /* copy key data to ctx */
620         movw r30, r24
621         ldi r20, 16
622 1:      ld r1, Z+
623         st X+, r1
624         dec r20
625         brne 1b
626         clr r1
627         
628         sbiw r26, 16
629         movw r24, r26
630         rcall noekeon_enc
631         
632         in r30, _SFR_IO_ADDR(SPL)
633         in r31, _SFR_IO_ADDR(SPH)
634         adiw r30, 16 
635         out  _SFR_IO_ADDR(SPH), r31
636         out  _SFR_IO_ADDR(SPL), r30     
637         ret
638         
639 #endif
640
641