]> git.cryptolib.org Git - avr-crypto-lib.git/blob - keccak/keccak-asm.S
357c8bd028fd36d6a1baa56358c42978ff22157c
[avr-crypto-lib.git] / keccak / keccak-asm.S
1 /* keccac-asm.S */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2012  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  * \file     keccak-asm.S
21  * \email    daniel.otte@rub.de
22  * \author   Daniel Otte
23  * \date     2012-12-16
24  * \license  GPLv3 or later
25  *
26  */
27
28 .nolist
29 #include "avr-asm-macros.S"
30 .list
31
32 .equ __zero_reg__, 1
33
34 .global rho_pi_idx_table
35 rho_pi_idx_table:
36         .irp i, 0, 1, 2, 3, 4
37                 .irp j, 0, 1, 2, 3, 4
38                         .byte (((2 * \j + 3 * \i) % 5) * 5 + \i) * 8
39                 .endr
40         .endr
41
42 .align 2
43 /*
44         void keccak_theta (uint64_t *a, uint64_t *b){
45         // uint64_t b[5][5];
46                 for(i = 0; i < 5; ++i){
47                         b[i][0] = a[0][i] ^ a[1][i] ^ a[2][i] ^ a[3][i] ^ a[4][i];
48                 }
49         }
50 */
51
52 /*********************************************
53  * theta_2a
54  *********************************************
55         input:
56                 r24:r25 = a ; uint64_t a[5][5]
57                 X = b       ; uint64_t *b
58         output:
59                 a[0..4][0] ^= b
60                 r20 = 0
61                 r21 = XX
62                 r22 = XX
63                 r24:r25 += 8
64                 X += 8
65                 Z = r24:r25 + 7 + 4 * 40
66 */
67 theta_2a:
68         ldi r20, 8
69 10:
70         movw ZL, r24
71         ld  r21, X+
72         .irp r, 0, 1, 2, 3, 4
73                 ld  r22, Z
74                 eor r22, r21
75                 st  Z, r22
76         .if \r != 4
77                 adiw ZL, 40
78         .endif
79         .endr
80         adiw r24, 1
81         dec r20
82         brne 10b
83         ret
84
85 /*********************************************
86  * theta_2b
87  *********************************************
88         input:
89                 r24:r25 = a+1 ; uint64_t a[5][5]
90                 X = b       ; uint64_t *b
91         output:
92                 a[0..4][0] ^= rol(b,1)
93                 r19 = XX
94                 r20 = 0
95                 r21 = XX
96                 r22 = XX
97                 r24:r25 += 8
98                 X += 8
99                 Z = r24:r25 + 7 + 4 * 40
100 */
101 theta_2b:
102         ldi r20, 7
103         ld r19, X+
104         lsl r19
105         rol __zero_reg__
106 10:
107         movw ZL, r24
108         ld  r21, X+
109         ror __zero_reg__
110         rol r21
111         rol __zero_reg__
112         .irp r, 0, 1, 2, 3, 4
113                 ld  r22, Z
114                 eor r22, r21
115                 st  Z, r22
116         .if \r != 4
117                 adiw ZL, 40
118         .endif
119         .endr
120         adiw r24, 1
121         dec r20
122         brne 10b
123         add r19, __zero_reg__
124         sbiw r24, 8
125         movw ZL, r24
126         .irp r, 0, 1, 2, 3, 4
127                 ld  r22, Z
128                 eor r22, r19
129                 st  Z, r22
130         .if \r != 4
131                 adiw ZL, 40
132         .endif
133         .endr
134         adiw r24, 9
135         clr __zero_reg__
136         ret
137
138 ;       a[i][j] =  b[i][j] ^ ((~(b[i][(j + 1) % 5])) & (b[i][(j + 2) % 5]));
139
140 /*********************************************
141  * chi_step
142  *********************************************
143         input:
144                 Y = a; uint8t *a;
145                 X = b; uint8t *b;
146                 Z = c; uint8t *c;
147         output:
148                 a[0..7] ^= ~b[0..7] & c[0..7]
149                 X += 8
150                 Y += 8
151                 Z += 8
152                 r16 = 0
153                 trash r21, r22, r23
154 */
155 chi_step:
156         ldi r16, 8
157 10:
158         ld r21, Y
159         ld r22, X+
160         ld r23, Z+
161         com r22
162         and r22, r23
163         eor r21, r22
164         st Y+, r21
165         dec r16
166         brne 10b
167         ret
168
169 .global keccak_f1600
170 keccak_f1600:
171         push_range 2, 9
172         push r16
173         push_range 28, 29
174
175         stack_alloc_large 200, r26, r27
176         adiw XL, 1
177
178         clr r9
179 5:
180         movw r30, r24 ; Z = a
181
182         ldi r19, 5
183 10:
184         ldi r20, 8
185 20:
186         ld  r22, Z
187         adiw ZL, 40
188         ld  r21, Z
189         eor r22, r21
190         adiw ZL, 40
191         ld  r21, Z
192         eor r22, r21
193         adiw ZL, 40
194         ld  r21, Z
195         eor r22, r21
196         adiw ZL, 40
197         ld  r21, Z
198         eor r22, r21
199         adiw r24, 1
200         movw r30, r24
201         st X+, r22
202         dec r20
203         brne 20b
204
205         adiw XL, 8 * 4
206         dec r19
207         brne 10b
208 /*
209         for(i = 0; i < 5; ++i){
210                 for(j = 0; j < 5; ++j){
211                         a[j][i] ^= b[(4 + i) % 5][0];
212                 }
213         }
214
215 */
216 /* a[0..4][0]{0..7} ^= b[4][0]{0..7} */
217         sbiw XL, 5 * 8
218         sbiw r24, 40
219         rcall theta_2a
220 /* a[0..4][1]{0..7} ^= b[0][0]{0..7} */
221         subi XL, lo8(4 * 5 * 8 + 8)
222         sbci XH, hi8(4 * 5 * 8 + 8)
223         rcall theta_2a
224 /* a[0..4][2]{0..7} ^= b[1][0]{0..7} */
225         adiw XL, 4 * 8
226         rcall theta_2a
227 /* a[0..4][3]{0..7} ^= b[2][0]{0..7} */
228         adiw XL, 4 * 8
229         rcall theta_2a
230 /* a[0..4][4]{0..7} ^= b[3][0]{0..7} */
231         adiw XL, 4 * 8
232         rcall theta_2a
233 /*
234         for(i = 0; i < 5; ++i){
235         for(j = 0; j < 5; ++j){
236             a[j][i] ^= rotate64_1bit_left(b[(i + 1) % 5][0]);
237         }
238     }
239 */
240 /* a[0..4][0]{0..7} ^= rol(b[1][0]{0..7}) */
241         subi r24, lo8(5 * 8 - 1)
242         sbci r25, hi8(5 * 8 - 1)
243         subi XL, lo8(2 * 5 * 8 + 8)
244         sbci XH, hi8(2 * 5 * 8 + 8)
245         rcall theta_2b
246 /* a[0..4][1]{0..7} ^= rol(b[2][0]{0..7}) */
247         adiw XL, 4 * 8
248         rcall theta_2b
249 /* a[0..4][21]{0..7} ^= rol(b[3][0]{0..7}) */
250         adiw XL, 4 * 8
251         rcall theta_2b
252 /* a[0..4][3]{0..7} ^= rol(b[4][0]{0..7}) */
253         adiw XL, 4 * 8
254         rcall theta_2b
255 /* a[0..4][4]{0..7} ^= rol(b[0][0]{0..7}) */
256         subi XL, lo8(4 * 5 * 8 + 8)
257         sbci XH, hi8(4 * 5 * 8 + 8)
258         rcall theta_2b
259
260 ;       ret
261 /*
262   rho & pi
263         for(i = 0; i < 5; ++i){
264                 for(j = 0; j < 5; ++j){
265                         b[(2 * i + 3 * j) % 5][j] =
266               rotate64left_code(a[j][i], pgm_read_byte(&(keccak_rotate_codes[i][j])));
267                 }
268         }
269
270    -- or --
271
272         const uint8_t* rot_code = (const uint8_t*)keccak_rotate_codes;
273     const uint8_t* idx_idx = (const uint8_t*)rho_pi_idx_table;
274     uint64_t *a_tmp = (uint64_t*)a;
275         for(i = 0; i < 25; ++i){
276                     *((uint64_t*)(((uint8_t*)b) + pgm_read_byte(idx_idx++))) =
277                 rotate64left_code(*a_tmp++, pgm_read_byte(rot_code++));
278
279         }
280
281 */
282
283 .equ B_REG_L, 6
284 .equ B_REG_H, 7
285
286         ldi r18, lo8(keccak_rotate_codes)
287         ldi r19, hi8(keccak_rotate_codes)
288         movw r2, r18
289         ldi r18, lo8(rho_pi_idx_table)
290         ldi r19, hi8(rho_pi_idx_table)
291         movw r4, r18
292         ldi r16, 25
293         mov r8, r16
294
295         sbiw r24, 5 * 8 + 1
296         movw YL, r24
297         sbiw XL, 8
298         movw B_REG_L, XL
299
300 10:
301         ld r18, Y+
302         ld r19, Y+
303         ld r20, Y+
304         ld r21, Y+
305         ld r22, Y+
306         ld r23, Y+
307         ld r24, Y+
308         ld r25, Y+
309         movw ZL, r2
310         lpm r16, Z+
311         movw r2, ZL
312         call rotate64left_code
313         movw ZL, r4
314         lpm r16, Z+
315         movw r4, ZL
316         movw XL, B_REG_L
317         add XL, r16
318         adc XH, __zero_reg__
319         st X+, r18
320         st X+, r19
321         st X+, r20
322         st X+, r21
323         st X+, r22
324         st X+, r23
325         st X+, r24
326         st X+, r25
327
328         dec r8
329         brne 10b
330 /*
331         -- chi --
332         for(i = 0; i < 5; ++i){
333         a[i][0] ^= ((~(b[i][1])) & (b[i][2]));
334         a[i][1] ^= ((~(b[i][2])) & (b[i][3]));
335         a[i][2] ^= ((~(b[i][3])) & (b[i][4]));
336         a[i][3] ^= ((~(b[i][4])) & (b[i][0]));
337         a[i][4] ^= ((~(b[i][0])) & (b[i][1]));
338
339         }
340 */
341         ; memcpy(a, b, 200)
342         ; X points at b + 32 + 8 = b + 40 = b[1][0] has to point to b[0][0]
343         ldi r16, 200
344         sbiw XL, 5 * 8
345         movw ZL, XL
346         subi YL, lo8(5 * 5 * 8)
347         sbci YH, hi8(5 * 5 * 8)
348         movw r2, YL
349 10:
350         ld r22, X+
351         st Y+, r22
352         dec r16
353         brne 10b
354
355         ; Z points at b
356         movw XL, ZL
357         movw r4, ZL
358         adiw XL, 8
359         adiw ZL, 16
360         movw YL, r2
361         ldi r18, 5
362 10:
363         rcall chi_step
364         rcall chi_step
365         rcall chi_step
366         sbiw ZL, 5 * 8
367         rcall chi_step
368         sbiw XL, 5 * 8
369         rcall chi_step
370         adiw XL, 5 * 8
371         adiw ZL, 5 * 8
372         dec r18
373         brne 10b
374
375         /* -- iota -- */
376         ldi r30, lo8(keccak_rc_comp)
377         ldi r31, hi8(keccak_rc_comp)
378         add r30, r9
379         adc r31, __zero_reg__
380         lpm r20, Z+
381         movw YL, r2
382         ldi r21, 0x80
383         bst r20, 6
384         brtc 10f
385         ldd r22, Y+7
386         eor r22, r21
387         std Y+7, r22
388 10:
389         bst r20, 5
390         brtc 10f
391         ldd r22, Y+3
392         eor r22, r21
393         std Y+3, r22
394 10:
395         bst r20, 4
396         brtc 10f
397         ldd r22, Y+1
398         eor r22, r21
399         std Y+1, r22
400 10:
401         andi r20, 0x8f
402         ld r22, Y
403         eor r22, r20
404         st Y, r22
405
406         inc r9
407         mov r16, r9
408         cpi r16, 24
409         breq 20f
410         movw r24, YL
411         movw r26, r4
412         rjmp 5b
413 20:
414
415         stack_free_large3 200
416
417         pop_range 28, 29
418         pop r16
419         pop_range 2, 9
420
421         ret