]> git.cryptolib.org Git - avr-crypto-lib.git/blob - sha256-asm.S
insereated GPLv3 stub
[avr-crypto-lib.git] / sha256-asm.S
1 /* sha256-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 /*\r
20  * Author:      Daniel Otte\r
21  *\r
22  * License: GPL\r
23 */\r
24 ; sha-256 implementation in assembler   \r
25 SHA256_BLOCK_BITS = 512\r
26 SHA256_HASH_BITS = 256\r
27 \r
28 .macro precall\r
29         /* push r18 - r27, r30 - r31*/\r
30         push r0\r
31         push r1\r
32         push r18\r
33         push r19\r
34         push r20\r
35         push r21\r
36         push r22\r
37         push r23\r
38         push r24\r
39         push r25\r
40         push r26\r
41         push r27\r
42         push r30\r
43         push r31\r
44         clr r1\r
45 .endm\r
46 \r
47 .macro postcall\r
48         pop r31\r
49         pop r30\r
50         pop r27\r
51         pop r26\r
52         pop r25\r
53         pop r24\r
54         pop r23\r
55         pop r22\r
56         pop r21\r
57         pop r20\r
58         pop r19\r
59         pop r18\r
60         pop r1\r
61         pop r0\r
62 .endm\r
63 \r
64 \r
65 .macro hexdump length\r
66         push r27\r
67         push r26\r
68         ldi r25, '\r'\r
69         mov r24, r25\r
70         call uart_putc\r
71         ldi r25, '\n'\r
72         mov r24, r25\r
73         call uart_putc\r
74         pop r26\r
75         pop r27\r
76         movw r24, r26\r
77 .if \length > 16\r
78         ldi r22, lo8(16)\r
79         ldi r23, hi8(16)\r
80         push r27\r
81         push r26\r
82         call uart_hexdump\r
83         pop r26\r
84         pop r27\r
85         adiw r26, 16\r
86         hexdump \length-16\r
87 .else\r
88         ldi r22, lo8(\length)\r
89         ldi r23, hi8(\length)\r
90         call uart_hexdump\r
91 .endif\r
92 .endm\r
93 \r
94 /* X points to Block */\r
95 .macro dbg_hexdump length\r
96         precall\r
97         hexdump \length\r
98         postcall\r
99 .endm\r
100 \r
101 .section .text\r
102 \r
103 SPL = 0x3D\r
104 SPH = 0x3E\r
105 SREG = 0x3F\r
106 \r
107 \r
108 ;\r
109 ;sha256_ctx_t is:\r
110 ;\r
111 ; [h0][h1][h2][h3][h4][h5][h6][h7][length]\r
112 ; hn is 32 bit large, length is 64 bit large\r
113 \r
114 ;###########################################################    \r
115 \r
116 .global sha256_ctx2hash\r
117 ; === sha256_ctx2hash ===\r
118 ; this function converts a state into a normal hash (bytestring)\r
119 ;  param1: the 16-bit destination pointer\r
120 ;       given in r25,r24 (r25 is most significant)\r
121 ;  param2: the 16-bit pointer to sha256_ctx structure\r
122 ;       given in r23,r22\r
123 sha256_ctx2hash:\r
124         movw r26, r22\r
125         movw r30, r24\r
126         ldi r21, 8\r
127         sbiw r26, 4\r
128 1:      \r
129         ldi r20, 4\r
130         adiw r26, 8\r
131 2:      \r
132                 ld r0, -X\r
133                 st Z+, r0       \r
134         dec r20\r
135         brne 2b\r
136         \r
137         dec r21\r
138         brne 1b\r
139         \r
140         ret\r
141 \r
142 ;###########################################################    \r
143 \r
144 .global sha256\r
145 ; === sha256 ===\r
146 ; this function calculates SHA-256 hashes from messages in RAM\r
147 ;  param1: the 16-bit hash destination pointer\r
148 ;       given in r25,r24 (r25 is most significant)\r
149 ;  param2: the 16-bit pointer to message\r
150 ;       given in r23,r22\r
151 ;  param3: 32-bit length value (length of message in bits)\r
152 ;   given in r21,r20,r19,r18\r
153 sha256:\r
154 sha256_prolog:\r
155         push r8\r
156         push r9\r
157         push r10\r
158         push r11\r
159         push r12\r
160         push r13\r
161         push r16\r
162         push r17\r
163         in r16, SPL\r
164         in r17, SPH\r
165         subi r16, 8*4+8 \r
166         sbci r17, 0     \r
167         in r0, SREG\r
168         cli\r
169         out SPL, r16\r
170         out SPH, r17\r
171         out SREG, r0\r
172         \r
173         push r25\r
174         push r24\r
175         inc r16\r
176         adc r17, r1\r
177         \r
178         movw r8, r18            /* backup of length*/\r
179         movw r10, r20\r
180         \r
181         movw r12, r22   /* backup pf msg-ptr */\r
182         \r
183         movw r24, r16\r
184         rcall sha256_init\r
185         /* if length >= 512 */\r
186 1:\r
187         tst r11\r
188         brne 4f\r
189         tst r10\r
190         brne 4f\r
191         mov r19, r9\r
192         cpi r19, 0x02\r
193         brlo 4f\r
194         \r
195         movw r24, r16\r
196         movw r22, r12\r
197         rcall sha256_nextBlock\r
198         ldi r19, 0x64\r
199         add r22, r19\r
200         adc r23, r1\r
201         /* length -= 512 */\r
202         ldi r19, 0x02\r
203         sub r9, r19\r
204         sbc r10, r1\r
205         sbc r11, r1\r
206         rjmp 1b\r
207         \r
208 4:\r
209         movw r24, r16\r
210         movw r22, r12\r
211         movw r20, r8\r
212         rcall sha256_lastBlock\r
213         \r
214         pop r24\r
215         pop r25\r
216         movw r22, r16\r
217         rcall sha256_ctx2hash   \r
218         \r
219 sha256_epilog:\r
220         in r30, SPL\r
221         in r31, SPH\r
222         adiw r30, 8*4+8         \r
223         in r0, SREG\r
224         cli\r
225         out SPL, r30\r
226         out SPH, r31\r
227         out SREG, r0\r
228         pop r17\r
229         pop r16\r
230         pop r13\r
231         pop r12\r
232         pop r11\r
233         pop r10\r
234         pop r9\r
235         pop r8\r
236         ret\r
237 \r
238 ;###########################################################    \r
239 \r
240 \r
241 ; block MUST NOT be larger than 64 bytes\r
242 \r
243 .global sha256_lastBlock\r
244 ; === sha256_lastBlock ===\r
245 ; this function does padding & Co. for calculating SHA-256 hashes\r
246 ;  param1: the 16-bit pointer to sha256_ctx structure\r
247 ;       given in r25,r24 (r25 is most significant)\r
248 ;  param2: an 16-bit pointer to 64 byte block to hash\r
249 ;       given in r23,r22\r
250 ;  param3: an 16-bit integer specifing length of block in bits\r
251 ;       given in r21,r20\r
252 sha256_lastBlock_localSpace = (SHA256_BLOCK_BITS/8+1)\r
253 \r
254 \r
255 sha256_lastBlock:\r
256         tst r20\r
257         brne sha256_lastBlock_prolog\r
258         cpi r21, 0x02\r
259         brne sha256_lastBlock_prolog\r
260         push r25\r
261         push r24\r
262         push r23\r
263         push r22\r
264         rcall sha256_nextBlock\r
265         pop r22\r
266         pop r23\r
267         pop r24\r
268         pop r25\r
269         clr r21\r
270         clr r22\r
271 sha256_lastBlock_prolog:\r
272         /* allocate space on stack */\r
273         in r30, SPL\r
274         in r31, SPH\r
275         in r1, SREG\r
276         subi r30, lo8(64)\r
277         sbci r31, hi8(64)\r
278         cli\r
279         out SPL, r30\r
280         out SPH, r31\r
281         out SREG,r1\r
282 \r
283         adiw r30, 1 /* SP points to next free byte on stack */\r
284         mov r18, r20 /* r20 = LSB(length) */\r
285         lsr r18\r
286         lsr r18\r
287         lsr r18\r
288         bst r21, 0      /* may be we should explain this ... */\r
289         bld r18, 5  /* now: r18 == length/8 (aka. length in bytes) */\r
290         \r
291         \r
292         movw r26, r22 /* X points to begin of msg */\r
293         tst r18\r
294         breq sha256_lastBlock_post_copy\r
295         mov r1, r18\r
296 sha256_lastBlock_copy_loop:\r
297         ld r0, X+\r
298         st Z+, r0\r
299         dec r1\r
300         brne sha256_lastBlock_copy_loop\r
301 sha256_lastBlock_post_copy:     \r
302 sha256_lastBlock_insert_stuffing_bit:   \r
303         ldi r19, 0x80\r
304         mov r0,r19      \r
305         ldi r19, 0x07\r
306         and r19, r20 /* if we are in bitmode */\r
307         breq 2f /* no bitmode */\r
308 1:      \r
309         lsr r0\r
310         dec r19\r
311         brne 1b\r
312         ld r19, X\r
313 /* maybe we should do some ANDing here, just for safety */\r
314         or r0, r19\r
315 2:      \r
316         st Z+, r0\r
317         inc r18\r
318 \r
319 /* checking stuff here */\r
320         cpi r18, 64-8+1\r
321         brsh 0f \r
322         rjmp sha256_lastBlock_insert_zeros\r
323 0:\r
324         /* oh shit, we landed here */\r
325         /* first we have to fill it up with zeros */\r
326         ldi r19, 64\r
327         sub r19, r18\r
328         breq 2f\r
329 1:      \r
330         st Z+, r1\r
331         dec r19\r
332         brne 1b \r
333 2:      \r
334         sbiw r30, 63\r
335         sbiw r30,  1\r
336         movw r22, r30\r
337         \r
338         push r31\r
339         push r30\r
340         push r25\r
341         push r24\r
342         push r21\r
343         push r20\r
344         rcall sha256_nextBlock\r
345         pop r20\r
346         pop r21\r
347         pop r24\r
348         pop r25\r
349         pop r30\r
350         pop r31\r
351         \r
352         /* now we should subtract 512 from length */\r
353         movw r26, r24\r
354         adiw r26, 4*8+1 /* we can skip the lowest byte */\r
355         ld r19, X\r
356         subi r19, hi8(512)\r
357         st X+, r19\r
358         ldi r18, 6\r
359 1:\r
360         ld r19, X\r
361         sbci r19, 0\r
362         st X+, r19\r
363         dec r18\r
364         brne 1b\r
365         \r
366 ;       clr r18 /* not neccessary ;-) */\r
367         /* reset Z pointer to begin of block */\r
368 \r
369 sha256_lastBlock_insert_zeros:  \r
370         ldi r19, 64-8\r
371         sub r19, r18\r
372         breq sha256_lastBlock_insert_length\r
373         clr r1\r
374 1:\r
375         st Z+, r1       /* r1 is still zero */\r
376         dec r19\r
377         brne 1b\r
378 \r
379 ;       rjmp sha256_lastBlock_epilog\r
380 sha256_lastBlock_insert_length:\r
381         movw r26, r24   /* X points to state */\r
382         adiw r26, 8*4   /* X points to (state.length) */\r
383         adiw r30, 8             /* Z points one after the last byte of block */\r
384         ld r0, X+\r
385         add r0, r20\r
386         st -Z, r0\r
387         ld r0, X+\r
388         adc r0, r21\r
389         st -Z, r0\r
390         ldi r19, 6\r
391 1:\r
392         ld r0, X+\r
393         adc r0, r1\r
394         st -Z, r0\r
395         dec r19\r
396         brne 1b\r
397 \r
398         sbiw r30, 64-8\r
399         movw r22, r30\r
400         rcall sha256_nextBlock\r
401 \r
402 sha256_lastBlock_epilog:\r
403         in r30, SPL\r
404         in r31, SPH\r
405         in r1, SREG\r
406         adiw r30, 63 ; lo8(64)\r
407         adiw r30,  1  ; hi8(64)\r
408         cli\r
409         out SPL, r30\r
410         out SPH, r31\r
411         out SREG,r1\r
412         clr r1\r
413         clr r0\r
414         ret\r
415 \r
416 /**/\r
417 ;###########################################################    \r
418 \r
419 .global sha256_nextBlock\r
420 ; === sha256_nextBlock ===\r
421 ; this is the core function for calculating SHA-256 hashes\r
422 ;  param1: the 16-bit pointer to sha256_ctx structure\r
423 ;       given in r25,r24 (r25 is most significant)\r
424 ;  param2: an 16-bit pointer to 64 byte block to hash\r
425 ;       given in r23,r22\r
426 sha256_nextBlock_localSpace = (64+8)*4 ; 64 32-bit values for w array and 8 32-bit values for a array (total 288 byte)\r
427 \r
428 Bck1 = 12\r
429 Bck2 = 13\r
430 Bck3 = 14\r
431 Bck4 = 15\r
432 Func1 = 22\r
433 Func2 = 23\r
434 Func3 = 24\r
435 Func4 = 25\r
436 Accu1 = 16\r
437 Accu2 = 17\r
438 Accu3 = 18\r
439 Accu4 = 19\r
440 XAccu1 = 8\r
441 XAccu2 = 9\r
442 XAccu3 = 10\r
443 XAccu4 = 11\r
444 T1      = 4\r
445 T2      = 5\r
446 T3      = 6\r
447 T4      = 7\r
448 LoopC = 1\r
449 /* byteorder: high number <--> high significance */\r
450 sha256_nextBlock:\r
451  ; initial, let's make some space ready for local vars\r
452         push r4 /* replace push & pop by mem ops? */\r
453         push r5\r
454         push r6\r
455         push r7\r
456         push r8\r
457         push r9\r
458         push r10\r
459         push r11\r
460         push r12\r
461         push r13\r
462         push r14\r
463         push r15\r
464         push r16\r
465         push r17\r
466         push r28\r
467         push r29\r
468         in r20, SPL\r
469         in r21, SPH\r
470         movw r18, r20                   ;backup SP\r
471 ;       movw r26, r20                   ; X points to free space on stack \r
472         movw r30, r22                   ; Z points to message\r
473         subi r20, lo8(sha256_nextBlock_localSpace) ;sbiw can do only up to 63\r
474         sbci r21, hi8(sha256_nextBlock_localSpace)\r
475         movw r26, r20                   ; X points to free space on stack \r
476         in r0, SREG\r
477         cli ; we want to be uninterrupted while updating SP\r
478         out SPL, r20\r
479         out SPH, r21\r
480         out SREG, r0\r
481         push r18\r
482         push r19\r
483         push r24\r
484         push r25 /* param1 will be needed later */\r
485  ; now we fill the w array with message (think about endianess)\r
486         adiw r26, 1 ; X++\r
487         ldi r20, 16\r
488 sha256_nextBlock_wcpyloop:      \r
489         ld r23, Z+\r
490         ld r22, Z+\r
491         ld r19, Z+\r
492         ld r18, Z+\r
493         st X+, r18\r
494         st X+, r19\r
495         st X+, r22      \r
496         st X+, r23\r
497         dec r20\r
498         brne sha256_nextBlock_wcpyloop\r
499 /*      for (i=16; i<64; ++i){\r
500                 w[i] = SIGMA_b(w[i-2]) + w[i-7] + SIGMA_a(w[i-15]) + w[i-16];   \r
501         } */\r
502         /* r25,r24,r23,r24 (r21,r20) are function values\r
503            r19,r18,r17,r16 are the accumulator\r
504            r15,r14,r13,rBck1 are backup1\r
505            r11,r10,r9 ,r8  are xor accu   \r
506            r1 is round counter                                                          */\r
507 \r
508         ldi r20, 64-16\r
509         mov LoopC, r20\r
510 sha256_nextBlock_wcalcloop:              \r
511         movw r30, r26 ; cp X to Z\r
512         sbiw r30, 63\r
513         sbiw r30, 1             ; substract 64 = 16*4\r
514         ld Accu1, Z+\r
515         ld Accu2, Z+\r
516         ld Accu3, Z+\r
517         ld Accu4, Z+ /* w[i] = w[i-16] */\r
518         ld Bck1, Z+\r
519         ld Bck2, Z+\r
520         ld Bck3, Z+\r
521         ld Bck4, Z+ /* backup = w[i-15] */\r
522         /* now sigma 0 */\r
523         mov Func1, Bck2\r
524         mov Func2, Bck3\r
525         mov Func3, Bck4\r
526         mov Func4, Bck1  /* prerotated by 8 */\r
527         ldi r20, 1\r
528         rcall bitrotl\r
529         movw XAccu1, Func1\r
530         movw XAccu3, Func3       /* store ROTR(w[i-15],7) in xor accu */\r
531         movw Func1, Bck3\r
532         movw Func3, Bck1 /* prerotated by 16 */\r
533         ldi r20, 2\r
534         rcall bitrotr\r
535         eor XAccu1, Func1  /* xor ROTR(w[i-15], 18)*/\r
536         eor XAccu2, Func2\r
537         eor XAccu3, Func3\r
538         eor XAccu4, Func4\r
539         ldi Func2, 3             /* now shr3 */ /*we can destroy backup now*/\r
540 sigma0_shr:\r
541         lsr Bck4\r
542         ror Bck3\r
543         ror Bck2\r
544         ror Bck1        \r
545         dec Func2\r
546         brne sigma0_shr\r
547         eor XAccu1, Bck1\r
548         eor XAccu2, Bck2\r
549         eor XAccu3, Bck3\r
550         eor XAccu4, Bck4        /* xor SHR(w[i-15], 3)*/ /* xor accu == sigma1(w[i-15]) */\r
551         add Accu1, XAccu1\r
552         adc Accu2, XAccu2\r
553         adc Accu3, XAccu3\r
554         adc Accu4, XAccu4 /* finished with sigma0 */\r
555         ldd Func1, Z+7*4  /* now accu += w[i-7] */\r
556         ldd Func2, Z+7*4+1\r
557         ldd Func3, Z+7*4+2\r
558         ldd Func4, Z+7*4+3\r
559         add Accu1, Func1\r
560         adc Accu2, Func2\r
561         adc Accu3, Func3\r
562         adc Accu4, Func4\r
563         ldd Bck1, Z+12*4 /* now backup = w[i-2]*/\r
564         ldd Bck2, Z+12*4+1\r
565         ldd Bck3, Z+12*4+2\r
566         ldd Bck4, Z+12*4+3\r
567         /* now sigma 1 */\r
568         movw Func1, Bck3\r
569         movw Func3, Bck1 /* prerotated by 16 */\r
570         ldi r20, 1\r
571         rcall bitrotr\r
572         movw XAccu3, Func3\r
573         movw XAccu1, Func1       /* store in ROTR(w[i-2], 17) xor accu */\r
574 ;       movw Func1, Bck3\r
575 ;       movw Func3, Bck1 /* prerotated by 16 */\r
576         ldi r20, 2\r
577         rcall bitrotr\r
578         eor XAccu1, Func1  /* xor ROTR(w[i-2], 19)*/\r
579         eor XAccu2, Func2\r
580         eor XAccu3, Func3\r
581         eor XAccu4, Func4\r
582         ldi Func2, 2     /* now shr10 (dirty trick, skipping a byte) */ /*we can destroy backup now*/\r
583 sigma1_shr:\r
584         lsr Bck4\r
585         ror Bck3\r
586         ror Bck2        \r
587         dec Func2\r
588         brne sigma1_shr\r
589         eor XAccu1, Bck2\r
590         eor XAccu2, Bck3\r
591         eor XAccu3, Bck4  /* xor SHR(w[i-2], 10)*/ /* xor accu == sigma1(w[i-15]) */\r
592         add Accu1, XAccu1\r
593         adc Accu2, XAccu2\r
594         adc Accu3, XAccu3\r
595         adc Accu4, XAccu4 /* finished with sigma0 */\r
596         /* now let's store the shit */\r
597         st X+, Accu1\r
598         st X+, Accu2\r
599         st X+, Accu3\r
600         st X+, Accu4\r
601         dec LoopC\r
602         breq 3f  ; skip if zero\r
603         rjmp sha256_nextBlock_wcalcloop\r
604 3:\r
605         /* we are finished with w array X points one byte post w */\r
606 /* init a array */\r
607         pop r31\r
608         pop r30\r
609         push r30\r
610         push r31\r
611         ldi r25, 8*4 /* 8 32-bit values to copy from ctx to a array */\r
612 init_a_array:   \r
613         ld r1, Z+\r
614         st X+, r1\r
615         dec r25\r
616         brne init_a_array\r
617         \r
618 /* now the real fun begins */\r
619 /* for (i=0; i<64; ++i){\r
620                         t1 = a[7] + SIGMA1(a[4]) + CH(a[4],a[5],a[6]) + k[i] + w[i];\r
621                         t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]);\r
622                         memmove(&(a[1]), &(a[0]), 7*4);         // a[7]=a[6]; a[6]=a[5]; a[5]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; \r
623                         a[4] += t1;\r
624                         a[0] = t1 + t2;\r
625                 } */\r
626         /* Y points to a[0], Z ('cause lpm wants it) points to k[i], X points to w[i] */\r
627         sbiw r26, 8*4  /* X still points at a[7]+1*/\r
628         movw r28, r26\r
629         ldi r30, lo8(sha256_kv)\r
630         ldi r31, hi8(sha256_kv)         \r
631         dec r27  /* X - (64*4 == 256) */\r
632         ldi r25, 64\r
633         mov LoopC, r25\r
634 sha256_main_loop:\r
635         /* now calculate t1 */\r
636          /*CH(x,y,z) = (x&y)^((~x)&z)*/\r
637         ldd T1, Y+5*4\r
638         ldd T2, Y+5*4+1\r
639         ldd T3, Y+5*4+2\r
640         ldd T4, Y+5*4+3 /* y in T */\r
641         ldd Func1, Y+4*4\r
642         ldd Func2, Y+4*4+1\r
643         ldd Func3, Y+4*4+2\r
644         ldd Func4, Y+4*4+3  /* x in Func */\r
645         ldd Bck1, Y+6*4\r
646         ldd Bck2, Y+6*4+1\r
647         ldd Bck3, Y+6*4+2\r
648         ldd Bck4, Y+6*4+3 /* z in Bck */\r
649         and T1, Func1\r
650         and T2, Func2\r
651         and T3, Func3\r
652         and T4, Func4\r
653         com Func1\r
654         com Func2\r
655         com Func3\r
656         com Func4\r
657         and Bck1, Func1\r
658         and Bck2, Func2\r
659         and Bck3, Func3\r
660         and Bck4, Func4\r
661         eor T1, Bck1\r
662         eor T2, Bck2\r
663         eor T3, Bck3\r
664         eor T4, Bck4 /* done, CH(x,y,z) is in T */\r
665         /* now SIGMA1(a[4]) */\r
666         ldd Bck4, Y+4*4         /* think about using it from Func reg above*/\r
667         ldd Bck1, Y+4*4+1       \r
668         ldd Bck2, Y+4*4+2\r
669         ldd Bck3, Y+4*4+3 /* load prerotate by 8-bit */ \r
670         movw Func1, Bck1\r
671         movw Func3, Bck3\r
672         ldi r20, 2 \r
673         rcall bitrotl           /* rotr(x,6) */ \r
674         movw XAccu1, Func1\r
675         movw XAccu3, Func3\r
676         movw Func1, Bck1\r
677         movw Func3, Bck3\r
678         ldi r20, 3 \r
679         rcall bitrotr   /* rotr(x,11) */\r
680         eor XAccu1, Func1\r
681         eor XAccu2, Func2\r
682         eor XAccu3, Func3\r
683         eor XAccu4, Func4\r
684         movw Func1, Bck3 /* this prerotates furteh 16 bits*/\r
685         movw Func3, Bck1 /* so we have now prerotated by 24 bits*/\r
686         ldi r20, 1 \r
687         rcall bitrotr   /* rotr(x,11) */\r
688         eor XAccu1, Func1\r
689         eor XAccu2, Func2\r
690         eor XAccu3, Func3\r
691         eor XAccu4, Func4 /* finished with SIGMA1, add it to T */\r
692         add T1, XAccu1\r
693         adc T2, XAccu2\r
694         adc T3, XAccu3\r
695         adc T4, XAccu4\r
696         /* now we've to add a[7], w[i] and k[i] */\r
697         ldd XAccu1, Y+4*7\r
698         ldd XAccu2, Y+4*7+1\r
699         ldd XAccu3, Y+4*7+2\r
700         ldd XAccu4, Y+4*7+3\r
701         add T1, XAccu1\r
702         adc T2, XAccu2\r
703         adc T3, XAccu3\r
704         adc T4, XAccu4 /* add a[7] */\r
705         ld XAccu1, X+\r
706         ld XAccu2, X+\r
707         ld XAccu3, X+\r
708         ld XAccu4, X+\r
709         add T1, XAccu1\r
710         adc T2, XAccu2\r
711         adc T3, XAccu3\r
712         adc T4, XAccu4 /* add w[i] */\r
713         lpm XAccu1, Z+\r
714         lpm XAccu2, Z+\r
715         lpm XAccu3, Z+\r
716         lpm XAccu4, Z+\r
717         add T1, XAccu1\r
718         adc T2, XAccu2\r
719         adc T3, XAccu3\r
720         adc T4, XAccu4 /* add k[i] */ /* finished with t1 */\r
721         /*now t2 = SIGMA0(a[0]) + MAJ(a[0],a[1],a[2]) */ /*i did to much x86 asm, i always see 4 32bit regs*/\r
722                 /* starting with MAJ(x,y,z) */\r
723         ldd Func1, Y+4*0+0\r
724         ldd Func2, Y+4*0+1\r
725         ldd Func3, Y+4*0+2\r
726         ldd Func4, Y+4*0+3 /* load x=a[0] */\r
727         ldd XAccu1, Y+4*1+0\r
728         ldd XAccu2, Y+4*1+1\r
729         ldd XAccu3, Y+4*1+2\r
730         ldd XAccu4, Y+4*1+3 /* load y=a[1] */\r
731         and XAccu1, Func1\r
732         and XAccu2, Func2\r
733         and XAccu3, Func3\r
734         and XAccu4, Func4       /* XAccu == (x & y) */\r
735         ldd Bck1, Y+4*2+0\r
736         ldd Bck2, Y+4*2+1\r
737         ldd Bck3, Y+4*2+2\r
738         ldd Bck4, Y+4*2+3 /* load z=a[2] */\r
739         and Func1, Bck1\r
740         and Func2, Bck2\r
741         and Func3, Bck3\r
742         and Func4, Bck4\r
743         eor XAccu1, Func1\r
744         eor XAccu2, Func2\r
745         eor XAccu3, Func3\r
746         eor XAccu4, Func4       /* XAccu == (x & y) ^ (x & z) */\r
747         ldd Func1, Y+4*1+0\r
748         ldd Func2, Y+4*1+1\r
749         ldd Func3, Y+4*1+2\r
750         ldd Func4, Y+4*1+3 /* load y=a[1] */\r
751         and Func1, Bck1\r
752         and Func2, Bck2\r
753         and Func3, Bck3\r
754         and Func4, Bck4\r
755         eor XAccu1, Func1\r
756         eor XAccu2, Func2\r
757         eor XAccu3, Func3\r
758         eor XAccu4, Func4       /* XAccu == Maj(x,y,z) == (x & y) ^ (x & z) ^ (y & z) */\r
759         /* SIGMA0(a[0]) */\r
760         ldd Bck1, Y+4*0+0 /* we should combine this with above */\r
761         ldd Bck2, Y+4*0+1\r
762         ldd Bck3, Y+4*0+2\r
763         ldd Bck4, Y+4*0+3\r
764         movw Func1, Bck1\r
765         movw Func3, Bck3\r
766         ldi r20, 2\r
767         rcall bitrotr\r
768         movw Accu1, Func1\r
769         movw Accu3, Func3 /* Accu = shr(a[0], 2) */\r
770         movw Func1, Bck3 \r
771         movw Func3, Bck1 /* prerotate by 16 bits */\r
772         ldi r20, 3\r
773         rcall bitrotl\r
774         eor Accu1, Func1\r
775         eor Accu2, Func2\r
776         eor Accu3, Func3\r
777         eor Accu4, Func4 /* Accu ^= shr(a[0], 13) */\r
778         mov Func1, Bck4\r
779         mov Func2, Bck1\r
780         mov Func3, Bck2\r
781         mov Func4, Bck3  /* prerotate by 24 bits */\r
782         ldi r20, 2\r
783         rcall bitrotl\r
784         eor Accu1, Func1\r
785         eor Accu2, Func2\r
786         eor Accu3, Func3\r
787         eor Accu4, Func4 /* Accu ^= shr(a[0], 22) */\r
788         add Accu1, XAccu1 /* add previous result (MAJ)*/\r
789         adc Accu2, XAccu2\r
790         adc Accu3, XAccu3\r
791         adc Accu4, XAccu4\r
792         /* now we are finished with the computing stuff (t1 in T, t2 in Accu)*/\r
793         /* a[7]=a[6]; a[6]=a[5]; a[5]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; */\r
794 \r
795         ldi r21, 7*4\r
796         adiw r28, 7*4\r
797 a_shift_loop:\r
798         ld  r25, -Y /* warning: this is PREdecrement */\r
799         std Y+4, r25\r
800         dec r21\r
801         brne a_shift_loop\r
802 \r
803         ldd Bck1, Y+4*4+0\r
804         ldd Bck2, Y+4*4+1\r
805         ldd Bck3, Y+4*4+2\r
806         ldd Bck4, Y+4*4+3\r
807         add Bck1, T1\r
808         adc Bck2, T2\r
809         adc Bck3, T3\r
810         adc Bck4, T4\r
811         std Y+4*4+0, Bck1\r
812         std Y+4*4+1, Bck2\r
813         std Y+4*4+2, Bck3\r
814         std Y+4*4+3, Bck4\r
815         add Accu1, T1\r
816         adc Accu2, T2\r
817         adc Accu3, T3\r
818         adc Accu4, T4\r
819         std Y+4*0+0, Accu1\r
820         std Y+4*0+1, Accu2\r
821         std Y+4*0+2, Accu3\r
822         std Y+4*0+3, Accu4 /* a array updated */\r
823         \r
824         \r
825         dec LoopC\r
826         breq update_state\r
827         rjmp sha256_main_loop ;brne sha256_main_loop\r
828 update_state:   \r
829         /* update state */\r
830         /* pointers to state should still exist on the stack ;-) */\r
831         pop r31\r
832         pop r30\r
833         ldi r21, 8\r
834 update_state_loop:\r
835         ldd Accu1, Z+0\r
836         ldd Accu2, Z+1\r
837         ldd Accu3, Z+2\r
838         ldd Accu4, Z+3 \r
839         ld Func1, Y+\r
840         ld Func2, Y+\r
841         ld Func3, Y+\r
842         ld Func4, Y+\r
843         add Accu1, Func1\r
844         adc Accu2, Func2\r
845         adc Accu3, Func3\r
846         adc Accu4, Func4\r
847         st Z+, Accu1\r
848         st Z+, Accu2\r
849         st Z+, Accu3\r
850         st Z+, Accu4\r
851         dec r21\r
852         brne update_state_loop\r
853         /* now we just have to update the length */\r
854         adiw r30, 1 /* since we add 512, we can simply skip the LSB */ \r
855         ldi r21, 2\r
856         ldi r22, 6\r
857         ld r20, Z\r
858         add r20, r21\r
859         st Z+, r20      \r
860         clr r21\r
861 sha256_nextBlock_fix_length:    \r
862         brcc sha256_nextBlock_epilog\r
863         ld r20, Z\r
864         adc r20, r21\r
865         st Z+, r20\r
866         dec r22\r
867         brne sha256_nextBlock_fix_length\r
868         \r
869 ; EPILOG\r
870 sha256_nextBlock_epilog:\r
871 /* now we should clean up the stack */\r
872         \r
873         pop r21\r
874         pop r20\r
875         in r0, SREG\r
876         cli ; we want to be uninterrupted while updating SP\r
877         out SPL, r20\r
878         out SPH, r21\r
879         out SREG, r0\r
880         \r
881         clr r1\r
882         pop r29\r
883         pop r28\r
884         pop r17\r
885         pop r16\r
886         pop r15\r
887         pop r14\r
888         pop r13\r
889         pop r12\r
890         pop r11\r
891         pop r10\r
892         pop r9\r
893         pop r8\r
894         pop r7\r
895         pop r6\r
896         pop r5\r
897         pop r4 \r
898         ret\r
899 \r
900 sha256_kv: ; round-key-vector stored in ProgMem \r
901 .word   0x2f98, 0x428a, 0x4491, 0x7137, 0xfbcf, 0xb5c0, 0xdba5, 0xe9b5, 0xc25b, 0x3956, 0x11f1, 0x59f1, 0x82a4, 0x923f, 0x5ed5, 0xab1c\r
902 .word   0xaa98, 0xd807, 0x5b01, 0x1283, 0x85be, 0x2431, 0x7dc3, 0x550c, 0x5d74, 0x72be, 0xb1fe, 0x80de, 0x06a7, 0x9bdc, 0xf174, 0xc19b\r
903 .word   0x69c1, 0xe49b, 0x4786, 0xefbe, 0x9dc6, 0x0fc1, 0xa1cc, 0x240c, 0x2c6f, 0x2de9, 0x84aa, 0x4a74, 0xa9dc, 0x5cb0, 0x88da, 0x76f9\r
904 .word   0x5152, 0x983e, 0xc66d, 0xa831, 0x27c8, 0xb003, 0x7fc7, 0xbf59, 0x0bf3, 0xc6e0, 0x9147, 0xd5a7, 0x6351, 0x06ca, 0x2967, 0x1429\r
905 .word   0x0a85, 0x27b7, 0x2138, 0x2e1b, 0x6dfc, 0x4d2c, 0x0d13, 0x5338, 0x7354, 0x650a, 0x0abb, 0x766a, 0xc92e, 0x81c2, 0x2c85, 0x9272\r
906 .word   0xe8a1, 0xa2bf, 0x664b, 0xa81a, 0x8b70, 0xc24b, 0x51a3, 0xc76c, 0xe819, 0xd192, 0x0624, 0xd699, 0x3585, 0xf40e, 0xa070, 0x106a\r
907 .word   0xc116, 0x19a4, 0x6c08, 0x1e37, 0x774c, 0x2748, 0xbcb5, 0x34b0, 0x0cb3, 0x391c, 0xaa4a, 0x4ed8, 0xca4f, 0x5b9c, 0x6ff3, 0x682e\r
908 .word   0x82ee, 0x748f, 0x636f, 0x78a5, 0x7814, 0x84c8, 0x0208, 0x8cc7, 0xfffa, 0x90be, 0x6ceb, 0xa450, 0xa3f7, 0xbef9, 0x78f2, 0xc671\r
909 \r
910         \r
911 ;###########################################################    \r
912 \r
913 .global sha256_init \r
914 ;uint32_t sha256_init_vector[]={\r
915 ;       0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,\r
916 ;       0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 };\r
917 ;\r
918 ;void sha256_init(sha256_ctx_t *state){\r
919 ;       state->length=0;\r
920 ;       memcpy(state->h, sha256_init_vector, 8*4);\r
921 ;}\r
922 ; param1: (Func3,r24) 16-bit pointer to sha256_ctx_t struct in ram\r
923 ; modifys: Z(r30,r31), Func1, r22\r
924 sha256_init:\r
925         movw r26, r24 ; (24,25) --> (26,27) load X with param1\r
926         ldi r30, lo8((sha256_init_vector))\r
927         ldi r31, hi8((sha256_init_vector))\r
928         ldi r22, 32\r
929 sha256_init_vloop:      \r
930         lpm r23, Z+ \r
931         st X+, r23\r
932         dec r22\r
933         brne sha256_init_vloop\r
934         ldi r22, 8\r
935         clr r1 ;this should not be needed\r
936 sha256_init_lloop:\r
937         st X+, r1\r
938         dec r22\r
939         brne sha256_init_lloop\r
940         ret\r
941         \r
942 sha256_init_vector:\r
943 .word 0xE667, 0x6A09\r
944 .word 0xAE85, 0xBB67 \r
945 .word 0xF372, 0x3C6E \r
946 .word 0xF53A, 0xA54F \r
947 .word 0x527F, 0x510E \r
948 .word 0x688C, 0x9B05 \r
949 .word 0xD9AB, 0x1F83 \r
950 .word 0xCD19, 0x5BE0\r
951 \r
952 ;###########################################################    \r
953 \r
954 .global rotl32\r
955 ; === ROTL32 ===\r
956 ; function that rotates a 32 bit word to the left\r
957 ;  param1: the 32-bit word to rotate\r
958 ;       given in r25,r24,r23,r22 (r25 is most significant)\r
959 ;  param2: an 8-bit value telling how often to rotate\r
960 ;       given in r20\r
961 ; modifys: r21, r22\r
962 rotl32:\r
963         cpi r20, 8\r
964         brlo bitrotl\r
965         mov r21, r25\r
966         mov r25, r24\r
967         mov r24, r23\r
968         mov r23, r22\r
969         mov r22, r21\r
970         subi r20, 8\r
971         rjmp rotr32\r
972 bitrotl:\r
973         clr r21\r
974         clc\r
975 bitrotl_loop:   \r
976         tst r20\r
977         breq fixrotl\r
978         rol r22\r
979         rol r23\r
980         rol r24\r
981         rol r25\r
982         rol r21\r
983         dec r20\r
984         rjmp bitrotl_loop\r
985 fixrotl:\r
986         or r22, r21\r
987         ret\r
988         \r
989 \r
990 ;###########################################################    \r
991 \r
992 .global rotr32\r
993 ; === ROTR32 ===\r
994 ; function that rotates a 32 bit word to the right\r
995 ;  param1: the 32-bit word to rotate\r
996 ;       given in r25,r24,r23,22 (r25 is most significant)\r
997 ;  param2: an 8-bit value telling how often to rotate\r
998 ;       given in r20\r
999 ; modifys: r21, r22\r
1000 rotr32:\r
1001         cpi r20, 8\r
1002         brlo bitrotr\r
1003         mov r21, r22\r
1004         mov r22, r23\r
1005         mov r23, r24\r
1006         mov r24, r25\r
1007         mov r25, r21\r
1008         subi r20, 8\r
1009         rjmp rotr32\r
1010 bitrotr:\r
1011         clr r21\r
1012         clc\r
1013 bitrotr_loop:   \r
1014         tst r20\r
1015         breq fixrotr\r
1016         ror r25\r
1017         ror r24\r
1018         ror r23\r
1019         ror r22\r
1020         ror r21\r
1021         dec r20\r
1022         rjmp bitrotr_loop\r
1023 fixrotr:\r
1024         or r25, r21\r
1025         ret\r
1026         \r
1027         \r
1028 ;###########################################################    \r
1029         \r
1030 .global change_endian32\r
1031 ; === change_endian32 ===\r
1032 ; function that changes the endianess of a 32-bit word\r
1033 ;  param1: the 32-bit word\r
1034 ;       given in r25,r24,r23,22 (r25 is most significant)\r
1035 ;  modifys: r21, r22\r
1036 change_endian32:\r
1037         movw r20,  r22 ; (r22,r23) --> (r20,r21)\r
1038         mov r22, r25\r
1039         mov r23, r24\r
1040         mov r24, r21\r
1041         mov r25, r20 \r
1042         ret\r
1043 \r