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