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