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