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