]> git.cryptolib.org Git - avr-crypto-lib.git/blob - sha1-asm.S
insereated GPLv3 stub
[avr-crypto-lib.git] / sha1-asm.S
1 /* sha1-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 ; SHA1 implementation in assembler for AVR\r
25 SHA1_BLOCK_BITS = 512\r
26 SHA1_HASH_BITS = 160\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 .macro delay\r
95 /*      \r
96         push r0\r
97         push r1\r
98         clr r0\r
99 1:      clr r1\r
100 2:      dec r1\r
101         brne 2b\r
102         dec r0\r
103         brne 1b\r
104         pop r1\r
105         pop r0  // */\r
106 .endm\r
107 \r
108 /* X points to Block */\r
109 .macro dbg_hexdump length\r
110 /*      \r
111         precall\r
112         hexdump \length\r
113         postcall\r
114         // */\r
115 .endm\r
116 \r
117 \r
118 \r
119 .section .text\r
120 \r
121 SPL = 0x3D\r
122 SPH = 0x3E\r
123 SREG = 0x3F\r
124 \r
125 \r
126 ;\r
127 ;sha1_ctx_t is:\r
128 ;\r
129 ; [h0][h1][h2][h3][h4][length]\r
130 ; hn is 32 bit large, length is 64 bit large\r
131 \r
132 ;###########################################################    \r
133 \r
134 .global sha1_ctx2hash\r
135 ; === sha1_ctx2hash ===\r
136 ; this function converts a state into a normal hash (bytestring)\r
137 ;  param1: the 16-bit destination pointer\r
138 ;       given in r25,r24 (r25 is most significant)\r
139 ;  param2: the 16-bit pointer to sha1_ctx structure\r
140 ;       given in r23,r22\r
141 sha1_ctx2hash:\r
142         movw r26, r22\r
143         movw r30, r24\r
144         ldi r21, 5\r
145         sbiw r26, 4\r
146 1:      \r
147         ldi r20, 4\r
148         adiw r26, 8\r
149 2:      \r
150                 ld r0, -X\r
151                 st Z+, r0       \r
152         dec r20\r
153         brne 2b\r
154         \r
155         dec r21\r
156         brne 1b\r
157         \r
158         ret\r
159 \r
160 ;###########################################################    \r
161 \r
162 .global sha1\r
163 ; === sha1 ===\r
164 ; this function calculates SHA-1 hashes from messages in RAM\r
165 ;  param1: the 16-bit hash destination pointer\r
166 ;       given in r25,r24 (r25 is most significant)\r
167 ;  param2: the 16-bit pointer to message\r
168 ;       given in r23,r22\r
169 ;  param3: 32-bit length value (length of message in bits)\r
170 ;   given in r21,r20,r19,r18\r
171 sha1:\r
172 sha1_prolog:\r
173         push r8\r
174         push r9\r
175         push r10\r
176         push r11\r
177         push r12\r
178         push r13\r
179         push r16\r
180         push r17\r
181         in r16, SPL\r
182         in r17, SPH\r
183         subi r16, 5*4+8 \r
184         sbci r17, 0     \r
185         in r0, SREG\r
186         cli\r
187         out SPL, r16\r
188         out SPH, r17\r
189         out SREG, r0\r
190         \r
191         push r25\r
192         push r24\r
193         inc r16\r
194         adc r17, r1\r
195         \r
196         movw r8, r18            /* backup of length*/\r
197         movw r10, r20\r
198         \r
199         movw r12, r22   /* backup pf msg-ptr */\r
200         \r
201         movw r24, r16\r
202         rcall sha1_init\r
203         /* if length >= 512 */\r
204 1:\r
205         tst r11\r
206         brne 4f\r
207         tst r10\r
208         brne 4f\r
209         mov r19, r9\r
210         cpi r19, 0x02\r
211         brlo 4f\r
212         \r
213         movw r24, r16\r
214         movw r22, r12\r
215         rcall sha1_nextBlock\r
216         ldi r19, 0x64\r
217         add r22, r19\r
218         adc r23, r1\r
219         /* length -= 512 */\r
220         ldi r19, 0x02\r
221         sub r9, r19\r
222         sbc r10, r1\r
223         sbc r11, r1\r
224         rjmp 1b\r
225         \r
226 4:\r
227         movw r24, r16\r
228         movw r22, r12\r
229         movw r20, r8\r
230         rcall sha1_lastBlock\r
231         \r
232         pop r24\r
233         pop r25\r
234         movw r22, r16\r
235         rcall sha1_ctx2hash     \r
236         \r
237 sha1_epilog:\r
238         in r30, SPL\r
239         in r31, SPH\r
240         adiw r30, 5*4+8         \r
241         in r0, SREG\r
242         cli\r
243         out SPL, r30\r
244         out SPH, r31\r
245         out SREG, r0\r
246         pop r17\r
247         pop r16\r
248         pop r13\r
249         pop r12\r
250         pop r11\r
251         pop r10\r
252         pop r9\r
253         pop r8\r
254         ret\r
255 \r
256 ;###########################################################    \r
257 \r
258 \r
259 ; block MUST NOT be larger than 64 bytes\r
260 \r
261 .global sha1_lastBlock\r
262 ; === sha1_lastBlock ===\r
263 ; this function does padding & Co. for calculating SHA-1 hashes\r
264 ;  param1: the 16-bit pointer to sha1_ctx structure\r
265 ;       given in r25,r24 (r25 is most significant)\r
266 ;  param2: an 16-bit pointer to 64 byte block to hash\r
267 ;       given in r23,r22\r
268 ;  param3: an 16-bit integer specifing length of block in bits\r
269 ;       given in r21,r20\r
270 sha1_lastBlock_localSpace = (SHA1_BLOCK_BITS/8+1)\r
271 \r
272 \r
273 sha1_lastBlock:\r
274         tst r20\r
275         brne sha1_lastBlock_prolog\r
276         cpi r21, 0x02\r
277         brne sha1_lastBlock_prolog\r
278         push r25\r
279         push r24\r
280         push r23\r
281         push r22\r
282         rcall sha1_nextBlock\r
283         pop r22\r
284         pop r23\r
285         pop r24\r
286         pop r25\r
287         clr r21\r
288         clr r22\r
289 sha1_lastBlock_prolog:\r
290         /* allocate space on stack */\r
291         in r30, SPL\r
292         in r31, SPH\r
293         in r1, SREG\r
294         subi r30, lo8(64)\r
295         sbci r31, hi8(64) /* ??? */\r
296         cli\r
297         out SPL, r30\r
298         out SPH, r31\r
299         out SREG,r1\r
300 \r
301         adiw r30, 1 /* SP points to next free byte on stack */\r
302         mov r18, r20 /* r20 = LSB(length) */\r
303         lsr r18\r
304         lsr r18\r
305         lsr r18\r
306         bst r21, 0      /* may be we should explain this ... */\r
307         bld r18, 5  /* now: r18 == length/8 (aka. length in bytes) */\r
308         \r
309         \r
310         movw r26, r22 /* X points to begin of msg */\r
311         tst r18\r
312         breq sha1_lastBlock_post_copy\r
313         mov r1, r18\r
314 sha1_lastBlock_copy_loop:\r
315         ld r0, X+\r
316         st Z+, r0\r
317         dec r1\r
318         brne sha1_lastBlock_copy_loop\r
319 sha1_lastBlock_post_copy:       \r
320 sha1_lastBlock_insert_stuffing_bit:     \r
321         ldi r19, 0x80\r
322         mov r0,r19      \r
323         ldi r19, 0x07\r
324         and r19, r20 /* if we are in bitmode */\r
325         breq 2f /* no bitmode */\r
326 1:      \r
327         lsr r0\r
328         dec r19\r
329         brne 1b\r
330         ld r19, X\r
331 /* maybe we should do some ANDing here, just for safety */\r
332         or r0, r19\r
333 2:      \r
334         st Z+, r0\r
335         inc r18\r
336 \r
337 /* checking stuff here */\r
338         cpi r18, 64-8+1\r
339         brsh 0f \r
340         rjmp sha1_lastBlock_insert_zeros\r
341 0:\r
342         /* oh shit, we landed here */\r
343         /* first we have to fill it up with zeros */\r
344         ldi r19, 64\r
345         sub r19, r18\r
346         breq 2f\r
347 1:      \r
348         st Z+, r1\r
349         dec r19\r
350         brne 1b \r
351 2:      \r
352         sbiw r30, 63\r
353         sbiw r30,  1\r
354         movw r22, r30\r
355         \r
356         push r31\r
357         push r30\r
358         push r25\r
359         push r24\r
360         push r21\r
361         push r20\r
362         rcall sha1_nextBlock\r
363         pop r20\r
364         pop r21\r
365         pop r24\r
366         pop r25\r
367         pop r30\r
368         pop r31\r
369         \r
370         /* now we should subtract 512 from length */\r
371         movw r26, r24\r
372         adiw r26, 4*5+1 /* we can skip the lowest byte */\r
373         ld r19, X\r
374         subi r19, hi8(512)\r
375         st X+, r19\r
376         ldi r18, 6\r
377 1:\r
378         ld r19, X\r
379         sbci r19, 0\r
380         st X+, r19\r
381         dec r18\r
382         brne 1b\r
383         \r
384 ;       clr r18 /* not neccessary ;-) */\r
385         /* reset Z pointer to begin of block */\r
386 \r
387 sha1_lastBlock_insert_zeros:    \r
388         ldi r19, 64-8\r
389         sub r19, r18\r
390         breq sha1_lastBlock_insert_length\r
391         clr r1\r
392 1:\r
393         st Z+, r1       /* r1 is still zero */\r
394         dec r19\r
395         brne 1b\r
396 \r
397 ;       rjmp sha1_lastBlock_epilog\r
398 sha1_lastBlock_insert_length:\r
399         movw r26, r24   /* X points to state */\r
400         adiw r26, 5*4   /* X points to (state.length) */\r
401         adiw r30, 8             /* Z points one after the last byte of block */\r
402         ld r0, X+\r
403         add r0, r20\r
404         st -Z, r0\r
405         ld r0, X+\r
406         adc r0, r21\r
407         st -Z, r0\r
408         ldi r19, 6\r
409 1:\r
410         ld r0, X+\r
411         adc r0, r1\r
412         st -Z, r0\r
413         dec r19\r
414         brne 1b\r
415 \r
416         sbiw r30, 64-8\r
417         movw r22, r30\r
418         rcall sha1_nextBlock\r
419 \r
420 sha1_lastBlock_epilog:\r
421         in r30, SPL\r
422         in r31, SPH\r
423         in r1, SREG\r
424         adiw r30, 63 ; lo8(64)\r
425         adiw r30,  1  ; hi8(64)\r
426         cli\r
427         out SPL, r30\r
428         out SPH, r31\r
429         out SREG,r1\r
430         clr r1\r
431         clr r0\r
432         ret\r
433 \r
434 /**/\r
435 ;###########################################################    \r
436 \r
437 .global sha1_nextBlock\r
438 ; === sha1_nextBlock ===\r
439 ; this is the core function for calculating SHA-1 hashes\r
440 ;  param1: the 16-bit pointer to sha1_ctx structure\r
441 ;       given in r25,r24 (r25 is most significant)\r
442 ;  param2: an 16-bit pointer to 64 byte block to hash\r
443 ;       given in r23,r22\r
444 sha1_nextBlock_localSpace = (16+5+1)*4 ; 16 32-bit values for w array and 5 32-bit values for a array (total 84 byte)\r
445 \r
446 xtmp = 0\r
447 xNULL = 1\r
448 W1 = 10\r
449 W2 = 11\r
450 T1      = 12\r
451 T2      = 13\r
452 T3      = 14\r
453 T4      = 15\r
454 LoopC = 16\r
455 S         = 17\r
456 tmp1 = 18\r
457 tmp2 = 19\r
458 tmp3 = 20\r
459 tmp4 = 21\r
460 F1 = 22\r
461 F2 = 23\r
462 F3 = 24\r
463 F4 = 25\r
464 \r
465 /* byteorder: high number <--> high significance */\r
466 sha1_nextBlock:\r
467  ; initial, let's make some space ready for local vars\r
468                          /* replace push & pop by mem ops? */\r
469         push r10\r
470         push r11\r
471         push r12\r
472         push r13\r
473         push r14\r
474         push r15\r
475         push r16\r
476         push r17\r
477         push r28\r
478         push r29\r
479         in r20, SPL\r
480         in r21, SPH\r
481         movw r18, r20                   ;backup SP\r
482 ;       movw r26, r20                   ; X points to free space on stack /* maybe removeable? */ \r
483         movw r30, r22                   ; Z points to message\r
484         subi r20, lo8(sha1_nextBlock_localSpace) ;sbiw can do only up to 63\r
485         sbci r21, hi8(sha1_nextBlock_localSpace)\r
486         movw r26, r20                   ; X points to free space on stack \r
487         in r0, SREG\r
488         cli ; we want to be uninterrupted while updating SP\r
489         out SPL, r20\r
490         out SPH, r21\r
491         out SREG, r0\r
492         \r
493         push r18\r
494         push r19 /* push old SP on new stack */\r
495         push r24\r
496         push r25 /* param1 will be needed later */\r
497         \r
498         /* load a[] with state */\r
499         movw 28, r24 /* load pointer to state in Y */\r
500         adiw r26, 1 ; X++\r
501 \r
502         ldi LoopC, 5*4  \r
503 1:      ld tmp1, Y+\r
504         st X+, tmp1\r
505         dec LoopC\r
506         brne 1b\r
507 \r
508         movw W1, r26 /* save pointer to w[0] */\r
509         /* load w[] with endian fixed message */\r
510                 /* we might also use the changeendian32() function at bottom */\r
511         movw r30, r22 /* mv param2 (ponter to msg) to Z */      \r
512         ldi LoopC, 16\r
513 1:\r
514         ldd tmp1, Z+3\r
515         st X+, tmp1\r
516         ldd tmp1, Z+2\r
517         st X+, tmp1\r
518         ldd tmp1, Z+1\r
519         st X+, tmp1\r
520         ld tmp1, Z\r
521         st X+, tmp1\r
522         adiw r30, 4\r
523         dec LoopC\r
524         brne 1b\r
525         \r
526         ;clr LoopC /* LoopC is named t in FIPS 180-2 */ \r
527         clr xtmp\r
528 sha1_nextBlock_mainloop:\r
529         mov S, LoopC\r
530         lsl S\r
531         lsl S\r
532         andi S, 0x3C /* S is a bytepointer so *4 */\r
533         /* load w[s] */\r
534         movw r26, W1\r
535         add r26, S /* X points at w[s] */\r
536         adc r27, xNULL\r
537         ld T1, X+\r
538         ld T2, X+\r
539         ld T3, X+\r
540         ld T4, X+\r
541 \r
542         /**/\r
543         push r26\r
544         push r27\r
545         push T4\r
546         push T3\r
547         push T2\r
548         push T1\r
549         in r26, SPL\r
550         in r27, SPH\r
551         adiw r26, 1\r
552         dbg_hexdump 4\r
553         pop T1\r
554         pop T2\r
555         pop T3\r
556         pop T4\r
557         pop r27\r
558         pop r26\r
559         /**/\r
560 \r
561         cpi LoopC, 16\r
562         brlt sha1_nextBlock_mainloop_core\r
563         /* update w[s] */\r
564         ldi tmp1, 2*4\r
565         rcall 1f\r
566         ldi tmp1, 8*4\r
567         rcall 1f\r
568         ldi tmp1, 13*4\r
569         rcall 1f\r
570         rjmp 2f\r
571 1:              /* this might be "outsourced" to save the jump above */\r
572         add tmp1, S\r
573         andi tmp1, 0x3f\r
574         movw r26, W1\r
575         add r26, tmp1\r
576         adc r27, xNULL\r
577         ld tmp2, X+\r
578         eor T1, tmp2\r
579         ld tmp2, X+\r
580         eor T2, tmp2\r
581         ld tmp2, X+\r
582         eor T3, tmp2\r
583         ld tmp2, X+\r
584         eor T4, tmp2\r
585         ret\r
586 2:      /* now we just hav to do a ROTL(T) and save T back */\r
587         mov tmp2, T4\r
588         rol tmp2\r
589         rol T1\r
590         rol T2\r
591         rol T3\r
592         rol T4\r
593         movw r26, W1\r
594         add r26, S\r
595         adc r27, xNULL\r
596         st X+, T1\r
597         st X+, T2\r
598         st X+, T3\r
599         st X+, T4\r
600         \r
601 sha1_nextBlock_mainloop_core:   /* ther core function; T=ROTL5(a) ....*/        \r
602                                                                 /* T already contains w[s] */\r
603         movw r26, W1\r
604         sbiw r26, 4*1           /* X points at a[4] aka e */\r
605         ld tmp1, X+ \r
606         add T1, tmp1\r
607         ld tmp1, X+ \r
608         adc T2, tmp1\r
609         ld tmp1, X+ \r
610         adc T3, tmp1\r
611         ld tmp1, X+ \r
612         adc T4, tmp1            /* T = w[s]+e */\r
613         sbiw r26, 4*5           /* X points at a[0] aka a */\r
614         ld F1, X+ \r
615         ld F2, X+ \r
616         ld F3, X+ \r
617         ld F4, X+ \r
618         mov tmp1, F4            /* X points at a[1] aka b */\r
619         ldi tmp2, 5\r
620 1:\r
621         rol tmp1\r
622         rol F1\r
623         rol F2\r
624         rol F3\r
625         rol F4\r
626         dec tmp2\r
627         brne 1b\r
628         \r
629         add T1, F1\r
630         adc T2, F2\r
631         adc T3, F3\r
632         adc T4, F4 /* T = ROTL(a,5) + e + w[s] */\r
633         \r
634         /* now we have to do this fucking conditional stuff */\r
635         ldi r30, lo8(sha1_nextBlock_xTable)\r
636         ldi r31, hi8(sha1_nextBlock_xTable)\r
637         add r30, xtmp\r
638         adc r31, xNULL\r
639         lpm tmp1, Z\r
640         cp tmp1, LoopC\r
641         brne 1f\r
642         inc xtmp\r
643 1:      ldi r30, lo8(sha1_nextBlock_KTable)\r
644         ldi r31, hi8(sha1_nextBlock_KTable)\r
645         lsl xtmp\r
646         lsl xtmp\r
647         add r30, xtmp\r
648         adc r31, xNULL\r
649         lsr xtmp\r
650         lsr xtmp\r
651          \r
652         lpm tmp1, Z+\r
653         add T1, tmp1\r
654         lpm tmp1, Z+\r
655         adc T2, tmp1\r
656         lpm tmp1, Z+\r
657         adc T3, tmp1\r
658         lpm tmp1, Z+\r
659         adc T4, tmp1\r
660                         /* T = ROTL(a,5) + e + kt + w[s] */\r
661         \r
662         /* wo Z-4 gerade auf kt zeigt ... */\r
663         movw r28, r26 /* copy X in Y */\r
664         adiw r30, 3*4 /* now Z points to the rigth locatin in our jump-vector-table */\r
665         lsr r31\r
666         ror r30\r
667                 \r
668         icall\r
669         mov F1, tmp1\r
670         icall\r
671         mov F2, tmp1\r
672         icall\r
673         mov F3, tmp1\r
674         icall\r
675         \r
676         add T1, F1\r
677         adc T2, F2\r
678         adc T3, F3\r
679         adc T4, tmp1 /* T = ROTL5(a) + f_t(b,c,d) + e + k_t + w[s] */\r
680                                  /* X points still at a[1] aka b, Y points at a[2] aka c */     \r
681         /* update a[] */\r
682 sha1_nextBlock_update_a:\r
683         /*first we move all vars in a[] "one up" e=d, d=c, c=b, b=a*/\r
684         //adiw r28, 3*4  /* Y should point at a[4] aka e */\r
685         movw r28, W1\r
686         sbiw r28, 4\r
687         \r
688         ldi tmp2, 4*4 \r
689 1:      \r
690         ld tmp1, -Y\r
691         std Y+4, tmp1\r
692         dec tmp2\r
693         brne 1b\r
694         /* Y points at a[0] aka a*/\r
695         \r
696         movw r28, W1\r
697         sbiw r28, 5*4\r
698         /* store T in a[0] aka a */\r
699         st Y+, T1\r
700         st Y+, T2\r
701         st Y+, T3\r
702         st Y+, T4\r
703         /* Y points at a[1] aka b*/\r
704         \r
705         /* rotate c */\r
706         ldd T1, Y+1*4\r
707         ldd T2, Y+1*4+1\r
708         ldd T3, Y+1*4+2\r
709         ldd T4, Y+1*4+3\r
710         mov tmp1, T1\r
711         ldi tmp2, 2\r
712 1:      ror tmp1\r
713         ror T4\r
714         ror T3\r
715         ror T2\r
716         ror T1\r
717         dec tmp2\r
718         brne 1b\r
719         std Y+1*4+0, T1\r
720         std Y+1*4+1, T2\r
721         std Y+1*4+2, T3\r
722         std Y+1*4+3, T4\r
723         \r
724         push r27\r
725         push r26\r
726         movw r26, W1\r
727         sbiw r26, 4*5\r
728         dbg_hexdump 4*5\r
729         pop r26\r
730         pop r27\r
731         \r
732         inc LoopC\r
733         cpi LoopC, 80\r
734         brge 1f\r
735         jmp sha1_nextBlock_mainloop\r
736 /**************************************/\r
737 1:      \r
738    /* littel patch */\r
739         sbiw r28, 4\r
740 \r
741 /* add a[] to state and inc length */   \r
742         pop r27\r
743         pop r26         /* now X points to state (and Y still at a[0]) */\r
744         ldi tmp4, 5\r
745 1:      clc\r
746         ldi tmp3, 4\r
747 2:      ld tmp1, X\r
748         ld tmp2, Y+\r
749         adc tmp1, tmp2\r
750         st X+, tmp1\r
751         dec tmp3\r
752         brne 2b\r
753         dec tmp4\r
754         brne 1b\r
755         \r
756         /* now length += 512 */\r
757         adiw r26, 1 /* we skip the least significant byte */\r
758         ld tmp1, X\r
759         ldi tmp2, hi8(512) /* 2 */\r
760         add tmp1, tmp2\r
761         st X+, tmp1\r
762         ldi tmp2, 6\r
763 1:\r
764         ld tmp1, X\r
765         adc tmp1, xNULL\r
766         st X+, tmp1\r
767         dec tmp2\r
768         brne 1b\r
769         \r
770 ; EPILOG\r
771 sha1_nextBlock_epilog:\r
772 /* now we should clean up the stack */\r
773         pop r21\r
774         pop r20\r
775         in r0, SREG\r
776         cli ; we want to be uninterrupted while updating SP\r
777         out SPL, r20\r
778         out SPH, r21\r
779         out SREG, r0\r
780         \r
781         clr r1\r
782         pop r29\r
783         pop r28\r
784         pop r17\r
785         pop r16\r
786         pop r15\r
787         pop r14\r
788         pop r13\r
789         pop r12\r
790         pop r11\r
791         pop r10\r
792         ret\r
793 \r
794 sha1_nextBlock_xTable:\r
795 .byte 20,40,60,0\r
796 sha1_nextBlock_KTable:\r
797 .int    0x5a827999 \r
798 .int    0x6ed9eba1 \r
799 .int    0x8f1bbcdc \r
800 .int    0xca62c1d6\r
801 sha1_nextBlock_JumpTable:\r
802 jmp sha1_nextBlock_Ch   \r
803 jmp sha1_nextBlock_Parity\r
804 jmp sha1_nextBlock_Maj\r
805 jmp sha1_nextBlock_Parity\r
806 \r
807          /* X and Y still point at a[1] aka b ; return value in tmp1 */\r
808 sha1_nextBlock_Ch:\r
809         ld tmp1, Y+\r
810         mov tmp2, tmp1\r
811         com tmp2\r
812         ldd tmp3, Y+3   /* load from c */\r
813         and tmp1, tmp3\r
814         ldd tmp3, Y+7   /* load from d */\r
815         and tmp2, tmp3\r
816         eor tmp1, tmp2\r
817         /**\r
818         precall\r
819         ldi r24, lo8(ch_str)\r
820         ldi r25, hi8(ch_str)\r
821         call uart_putstr_P\r
822         postcall\r
823         /**/\r
824         ret\r
825         \r
826 sha1_nextBlock_Maj:\r
827         ld tmp1, Y+\r
828         mov tmp2, tmp1\r
829         ldd tmp3, Y+3   /* load from c */\r
830         and tmp1, tmp3\r
831         ldd tmp4, Y+7   /* load from d */\r
832         and tmp2, tmp4\r
833         eor tmp1, tmp2\r
834         and tmp3, tmp4\r
835         eor tmp1, tmp3\r
836         /**\r
837         precall\r
838         ldi r24, lo8(maj_str)\r
839         ldi r25, hi8(maj_str)\r
840         call uart_putstr_P\r
841         postcall\r
842         /**/\r
843         ret\r
844 \r
845 sha1_nextBlock_Parity:\r
846         ld tmp1, Y+\r
847         ldd tmp2, Y+3   /* load from c */\r
848         eor tmp1, tmp2\r
849         ldd tmp2, Y+7   /* load from d */\r
850         eor tmp1, tmp2\r
851         \r
852         /**\r
853         precall\r
854         ldi r24, lo8(parity_str)\r
855         ldi r25, hi8(parity_str)\r
856         call uart_putstr_P\r
857         postcall\r
858         /**/\r
859         ret\r
860 /*      \r
861 ch_str:                 .asciz "\r\nCh"\r
862 maj_str:                .asciz "\r\nMaj"\r
863 parity_str:     .asciz "\r\nParity"\r
864 */\r
865 ;###########################################################    \r
866 \r
867 .global sha1_init \r
868 ;void sha1_init(sha1_ctx_t *state){\r
869 ;       DEBUG_S("\r\nSHA1_INIT");\r
870 ;       state->h[0] = 0x67452301;\r
871 ;       state->h[1] = 0xefcdab89;\r
872 ;       state->h[2] = 0x98badcfe;\r
873 ;       state->h[3] = 0x10325476;\r
874 ;       state->h[4] = 0xc3d2e1f0;\r
875 ;       state->length = 0;\r
876 ;}\r
877 ; param1: (Func3,r24) 16-bit pointer to sha1_ctx_t struct in ram\r
878 ; modifys: Z(r30,r31), Func1, r22\r
879 sha1_init:\r
880         movw r26, r24 ; (24,25) --> (26,27) load X with param1\r
881         ldi r30, lo8((sha1_init_vector))\r
882         ldi r31, hi8((sha1_init_vector))\r
883         ldi r22, 5*4 /* bytes to copy */\r
884 sha1_init_vloop:        \r
885         lpm r23, Z+ \r
886         st X+, r23\r
887         dec r22\r
888         brne sha1_init_vloop\r
889         ldi r22, 8\r
890         clr r1 /* this should not be needed */\r
891 sha1_init_lloop:\r
892         st X+, r1\r
893         dec r22\r
894         brne sha1_init_lloop\r
895         ret\r
896         \r
897 sha1_init_vector:\r
898 .int 0x67452301;\r
899 .int 0xefcdab89;\r
900 .int 0x98badcfe;\r
901 .int 0x10325476;\r
902 .int 0xc3d2e1f0;\r
903 /*\r
904 ;###########################################################    \r
905 \r
906 .global rotl32\r
907 ; === ROTL32 ===\r
908 ; function that rotates a 32 bit word to the left\r
909 ;  param1: the 32-bit word to rotate\r
910 ;       given in r25,r24,r23,r22 (r25 is most significant)\r
911 ;  param2: an 8-bit value telling how often to rotate\r
912 ;       given in r20\r
913 ; modifys: r21, r22\r
914 rotl32:\r
915         cpi r20, 8\r
916         brlo bitrotl\r
917         mov r21, r25\r
918         mov r25, r24\r
919         mov r24, r23\r
920         mov r23, r22\r
921         mov r22, r21\r
922         subi r20, 8\r
923         rjmp rotr32\r
924 bitrotl:\r
925         clr r21\r
926         clc\r
927 bitrotl_loop:   \r
928         tst r20\r
929         breq fixrotl\r
930         rol r22\r
931         rol r23\r
932         rol r24\r
933         rol r25\r
934         rol r21\r
935         dec r20\r
936         rjmp bitrotl_loop\r
937 fixrotl:\r
938         or r22, r21\r
939         ret\r
940         \r
941 \r
942 ;###########################################################    \r
943 \r
944 .global rotr32\r
945 ; === ROTR32 ===\r
946 ; function that rotates a 32 bit word to the right\r
947 ;  param1: the 32-bit word to rotate\r
948 ;       given in r25,r24,r23,22 (r25 is most significant)\r
949 ;  param2: an 8-bit value telling how often to rotate\r
950 ;       given in r20\r
951 ; modifys: r21, r22\r
952 rotr32:\r
953         cpi r20, 8\r
954         brlo bitrotr\r
955         mov r21, r22\r
956         mov r22, r23\r
957         mov r23, r24\r
958         mov r24, r25\r
959         mov r25, r21\r
960         subi r20, 8\r
961         rjmp rotr32\r
962 bitrotr:\r
963         clr r21\r
964         clc\r
965 bitrotr_loop:   \r
966         tst r20\r
967         breq fixrotr\r
968         ror r25\r
969         ror r24\r
970         ror r23\r
971         ror r22\r
972         ror r21\r
973         dec r20\r
974         rjmp bitrotr_loop\r
975 fixrotr:\r
976         or r25, r21\r
977         ret\r
978         \r
979         \r
980 ;###########################################################    \r
981         \r
982 .global change_endian32\r
983 ; === change_endian32 ===\r
984 ; function that changes the endianess of a 32-bit word\r
985 ;  param1: the 32-bit word\r
986 ;       given in r25,r24,r23,22 (r25 is most significant)\r
987 ;  modifys: r21, r22\r
988 change_endian32:\r
989         movw r20,  r22 ; (r22,r23) --> (r20,r21)\r
990         mov r22, r25\r
991         mov r23, r24\r
992         mov r24, r21\r
993         mov r25, r20 \r
994         ret\r
995 */\r