]> git.cryptolib.org Git - avr-crypto-lib.git/blob - sha1-asm.S
884adbc2ae71e8b8972ced2e5b1b008304e6cf86
[avr-crypto-lib.git] / sha1-asm.S
1 /*\r
2  * Author:      Daniel Otte\r
3  *\r
4  * License: GPL\r
5 */\r
6 ; SHA1 implementation in assembler for AVR\r
7 SHA1_BLOCK_BITS = 512\r
8 SHA1_HASH_BITS = 160\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 .macro delay\r
77 /*      \r
78         push r0\r
79         push r1\r
80         clr r0\r
81 1:      clr r1\r
82 2:      dec r1\r
83         brne 2b\r
84         dec r0\r
85         brne 1b\r
86         pop r1\r
87         pop r0  // */\r
88 .endm\r
89 \r
90 /* X points to Block */\r
91 .macro dbg_hexdump length\r
92 /*      \r
93         precall\r
94         hexdump \length\r
95         postcall\r
96         // */\r
97 .endm\r
98 \r
99 \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 ;sha1_ctx_t is:\r
110 ;\r
111 ; [h0][h1][h2][h3][h4][length]\r
112 ; hn is 32 bit large, length is 64 bit large\r
113 \r
114 ;###########################################################    \r
115 \r
116 .global sha1_ctx2hash\r
117 ; === sha1_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 sha1_ctx structure\r
122 ;       given in r23,r22\r
123 sha1_ctx2hash:\r
124         movw r26, r22\r
125         movw r30, r24\r
126         ldi r21, 5\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 sha1\r
145 ; === sha1 ===\r
146 ; this function calculates SHA-1 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 sha1:\r
154 sha1_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, 5*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 sha1_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 sha1_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 sha1_lastBlock\r
213         \r
214         pop r24\r
215         pop r25\r
216         movw r22, r16\r
217         rcall sha1_ctx2hash     \r
218         \r
219 sha1_epilog:\r
220         in r30, SPL\r
221         in r31, SPH\r
222         adiw r30, 5*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 sha1_lastBlock\r
244 ; === sha1_lastBlock ===\r
245 ; this function does padding & Co. for calculating SHA-1 hashes\r
246 ;  param1: the 16-bit pointer to sha1_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 sha1_lastBlock_localSpace = (SHA1_BLOCK_BITS/8+1)\r
253 \r
254 \r
255 sha1_lastBlock:\r
256         tst r20\r
257         brne sha1_lastBlock_prolog\r
258         cpi r21, 0x02\r
259         brne sha1_lastBlock_prolog\r
260         push r25\r
261         push r24\r
262         push r23\r
263         push r22\r
264         rcall sha1_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 sha1_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 sha1_lastBlock_post_copy\r
295         mov r1, r18\r
296 sha1_lastBlock_copy_loop:\r
297         ld r0, X+\r
298         st Z+, r0\r
299         dec r1\r
300         brne sha1_lastBlock_copy_loop\r
301 sha1_lastBlock_post_copy:       \r
302 sha1_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 sha1_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 sha1_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*5+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 sha1_lastBlock_insert_zeros:    \r
370         ldi r19, 64-8\r
371         sub r19, r18\r
372         breq sha1_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 sha1_lastBlock_epilog\r
380 sha1_lastBlock_insert_length:\r
381         movw r26, r24   /* X points to state */\r
382         adiw r26, 5*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 sha1_nextBlock\r
401 \r
402 sha1_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 sha1_nextBlock\r
420 ; === sha1_nextBlock ===\r
421 ; this is the core function for calculating SHA-1 hashes\r
422 ;  param1: the 16-bit pointer to sha1_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 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
427 \r
428 xtmp = 0\r
429 xNULL = 1\r
430 W1 = 10\r
431 W2 = 11\r
432 T1      = 12\r
433 T2      = 13\r
434 T3      = 14\r
435 T4      = 15\r
436 LoopC = 16\r
437 S         = 17\r
438 tmp1 = 18\r
439 tmp2 = 19\r
440 tmp3 = 20\r
441 tmp4 = 21\r
442 F1 = 22\r
443 F2 = 23\r
444 F3 = 24\r
445 F4 = 25\r
446 \r
447 /* byteorder: high number <--> high significance */\r
448 sha1_nextBlock:\r
449  ; initial, let's make some space ready for local vars\r
450                          /* replace push & pop by mem ops? */\r
451         push r10\r
452         push r11\r
453         push r12\r
454         push r13\r
455         push r14\r
456         push r15\r
457         push r16\r
458         push r17\r
459         push r28\r
460         push r29\r
461         in r20, SPL\r
462         in r21, SPH\r
463         movw r18, r20                   ;backup SP\r
464 ;       movw r26, r20                   ; X points to free space on stack /* maybe removeable? */ \r
465         movw r30, r22                   ; Z points to message\r
466         subi r20, lo8(sha1_nextBlock_localSpace) ;sbiw can do only up to 63\r
467         sbci r21, hi8(sha1_nextBlock_localSpace)\r
468         movw r26, r20                   ; X points to free space on stack \r
469         in r0, SREG\r
470         cli ; we want to be uninterrupted while updating SP\r
471         out SPL, r20\r
472         out SPH, r21\r
473         out SREG, r0\r
474         \r
475         push r18\r
476         push r19 /* push old SP on new stack */\r
477         push r24\r
478         push r25 /* param1 will be needed later */\r
479         \r
480         /* load a[] with state */\r
481         movw 28, r24 /* load pointer to state in Y */\r
482         adiw r26, 1 ; X++\r
483 \r
484         ldi LoopC, 5*4  \r
485 1:      ld tmp1, Y+\r
486         st X+, tmp1\r
487         dec LoopC\r
488         brne 1b\r
489 \r
490         movw W1, r26 /* save pointer to w[0] */\r
491         /* load w[] with endian fixed message */\r
492                 /* we might also use the changeendian32() function at bottom */\r
493         movw r30, r22 /* mv param2 (ponter to msg) to Z */      \r
494         ldi LoopC, 16\r
495 1:\r
496         ldd tmp1, Z+3\r
497         st X+, tmp1\r
498         ldd tmp1, Z+2\r
499         st X+, tmp1\r
500         ldd tmp1, Z+1\r
501         st X+, tmp1\r
502         ld tmp1, Z\r
503         st X+, tmp1\r
504         adiw r30, 4\r
505         dec LoopC\r
506         brne 1b\r
507         \r
508         ;clr LoopC /* LoopC is named t in FIPS 180-2 */ \r
509         clr xtmp\r
510 sha1_nextBlock_mainloop:\r
511         mov S, LoopC\r
512         lsl S\r
513         lsl S\r
514         andi S, 0x3C /* S is a bytepointer so *4 */\r
515         /* load w[s] */\r
516         movw r26, W1\r
517         add r26, S /* X points at w[s] */\r
518         adc r27, xNULL\r
519         ld T1, X+\r
520         ld T2, X+\r
521         ld T3, X+\r
522         ld T4, X+\r
523 \r
524         /**/\r
525         push r26\r
526         push r27\r
527         push T4\r
528         push T3\r
529         push T2\r
530         push T1\r
531         in r26, SPL\r
532         in r27, SPH\r
533         adiw r26, 1\r
534         dbg_hexdump 4\r
535         pop T1\r
536         pop T2\r
537         pop T3\r
538         pop T4\r
539         pop r27\r
540         pop r26\r
541         /**/\r
542 \r
543         cpi LoopC, 16\r
544         brlt sha1_nextBlock_mainloop_core\r
545         /* update w[s] */\r
546         ldi tmp1, 2*4\r
547         rcall 1f\r
548         ldi tmp1, 8*4\r
549         rcall 1f\r
550         ldi tmp1, 13*4\r
551         rcall 1f\r
552         rjmp 2f\r
553 1:              /* this might be "outsourced" to save the jump above */\r
554         add tmp1, S\r
555         andi tmp1, 0x3f\r
556         movw r26, W1\r
557         add r26, tmp1\r
558         adc r27, xNULL\r
559         ld tmp2, X+\r
560         eor T1, tmp2\r
561         ld tmp2, X+\r
562         eor T2, tmp2\r
563         ld tmp2, X+\r
564         eor T3, tmp2\r
565         ld tmp2, X+\r
566         eor T4, tmp2\r
567         ret\r
568 2:      /* now we just hav to do a ROTL(T) and save T back */\r
569         mov tmp2, T4\r
570         rol tmp2\r
571         rol T1\r
572         rol T2\r
573         rol T3\r
574         rol T4\r
575         movw r26, W1\r
576         add r26, S\r
577         adc r27, xNULL\r
578         st X+, T1\r
579         st X+, T2\r
580         st X+, T3\r
581         st X+, T4\r
582         \r
583 sha1_nextBlock_mainloop_core:   /* ther core function; T=ROTL5(a) ....*/        \r
584                                                                 /* T already contains w[s] */\r
585         movw r26, W1\r
586         sbiw r26, 4*1           /* X points at a[4] aka e */\r
587         ld tmp1, X+ \r
588         add T1, tmp1\r
589         ld tmp1, X+ \r
590         adc T2, tmp1\r
591         ld tmp1, X+ \r
592         adc T3, tmp1\r
593         ld tmp1, X+ \r
594         adc T4, tmp1            /* T = w[s]+e */\r
595         sbiw r26, 4*5           /* X points at a[0] aka a */\r
596         ld F1, X+ \r
597         ld F2, X+ \r
598         ld F3, X+ \r
599         ld F4, X+ \r
600         mov tmp1, F4            /* X points at a[1] aka b */\r
601         ldi tmp2, 5\r
602 1:\r
603         rol tmp1\r
604         rol F1\r
605         rol F2\r
606         rol F3\r
607         rol F4\r
608         dec tmp2\r
609         brne 1b\r
610         \r
611         add T1, F1\r
612         adc T2, F2\r
613         adc T3, F3\r
614         adc T4, F4 /* T = ROTL(a,5) + e + w[s] */\r
615         \r
616         /* now we have to do this fucking conditional stuff */\r
617         ldi r30, lo8(sha1_nextBlock_xTable)\r
618         ldi r31, hi8(sha1_nextBlock_xTable)\r
619         add r30, xtmp\r
620         adc r31, xNULL\r
621         lpm tmp1, Z\r
622         cp tmp1, LoopC\r
623         brne 1f\r
624         inc xtmp\r
625 1:      ldi r30, lo8(sha1_nextBlock_KTable)\r
626         ldi r31, hi8(sha1_nextBlock_KTable)\r
627         lsl xtmp\r
628         lsl xtmp\r
629         add r30, xtmp\r
630         adc r31, xNULL\r
631         lsr xtmp\r
632         lsr xtmp\r
633          \r
634         lpm tmp1, Z+\r
635         add T1, tmp1\r
636         lpm tmp1, Z+\r
637         adc T2, tmp1\r
638         lpm tmp1, Z+\r
639         adc T3, tmp1\r
640         lpm tmp1, Z+\r
641         adc T4, tmp1\r
642                         /* T = ROTL(a,5) + e + kt + w[s] */\r
643         \r
644         /* wo Z-4 gerade auf kt zeigt ... */\r
645         movw r28, r26 /* copy X in Y */\r
646         adiw r30, 3*4 /* now Z points to the rigth locatin in our jump-vector-table */\r
647         lsr r31\r
648         ror r30\r
649                 \r
650         icall\r
651         mov F1, tmp1\r
652         icall\r
653         mov F2, tmp1\r
654         icall\r
655         mov F3, tmp1\r
656         icall\r
657         \r
658         add T1, F1\r
659         adc T2, F2\r
660         adc T3, F3\r
661         adc T4, tmp1 /* T = ROTL5(a) + f_t(b,c,d) + e + k_t + w[s] */\r
662                                  /* X points still at a[1] aka b, Y points at a[2] aka c */     \r
663         /* update a[] */\r
664 sha1_nextBlock_update_a:\r
665         /*first we move all vars in a[] "one up" e=d, d=c, c=b, b=a*/\r
666         //adiw r28, 3*4  /* Y should point at a[4] aka e */\r
667         movw r28, W1\r
668         sbiw r28, 4\r
669         \r
670         ldi tmp2, 4*4 \r
671 1:      \r
672         ld tmp1, -Y\r
673         std Y+4, tmp1\r
674         dec tmp2\r
675         brne 1b\r
676         /* Y points at a[0] aka a*/\r
677         \r
678         movw r28, W1\r
679         sbiw r28, 5*4\r
680         /* store T in a[0] aka a */\r
681         st Y+, T1\r
682         st Y+, T2\r
683         st Y+, T3\r
684         st Y+, T4\r
685         /* Y points at a[1] aka b*/\r
686         \r
687         /* rotate c */\r
688         ldd T1, Y+1*4\r
689         ldd T2, Y+1*4+1\r
690         ldd T3, Y+1*4+2\r
691         ldd T4, Y+1*4+3\r
692         mov tmp1, T1\r
693         ldi tmp2, 2\r
694 1:      ror tmp1\r
695         ror T4\r
696         ror T3\r
697         ror T2\r
698         ror T1\r
699         dec tmp2\r
700         brne 1b\r
701         std Y+1*4+0, T1\r
702         std Y+1*4+1, T2\r
703         std Y+1*4+2, T3\r
704         std Y+1*4+3, T4\r
705         \r
706         push r27\r
707         push r26\r
708         movw r26, W1\r
709         sbiw r26, 4*5\r
710         dbg_hexdump 4*5\r
711         pop r26\r
712         pop r27\r
713         \r
714         inc LoopC\r
715         cpi LoopC, 80\r
716         brge 1f\r
717         jmp sha1_nextBlock_mainloop\r
718 /**************************************/\r
719 1:      \r
720    /* littel patch */\r
721         sbiw r28, 4\r
722 \r
723 /* add a[] to state and inc length */   \r
724         pop r27\r
725         pop r26         /* now X points to state (and Y still at a[0]) */\r
726         ldi tmp4, 5\r
727 1:      clc\r
728         ldi tmp3, 4\r
729 2:      ld tmp1, X\r
730         ld tmp2, Y+\r
731         adc tmp1, tmp2\r
732         st X+, tmp1\r
733         dec tmp3\r
734         brne 2b\r
735         dec tmp4\r
736         brne 1b\r
737         \r
738         /* now length += 512 */\r
739         adiw r26, 1 /* we skip the least significant byte */\r
740         ld tmp1, X\r
741         ldi tmp2, hi8(512) /* 2 */\r
742         add tmp1, tmp2\r
743         st X+, tmp1\r
744         ldi tmp2, 6\r
745 1:\r
746         ld tmp1, X\r
747         adc tmp1, xNULL\r
748         st X+, tmp1\r
749         dec tmp2\r
750         brne 1b\r
751         \r
752 ; EPILOG\r
753 sha1_nextBlock_epilog:\r
754 /* now we should clean up the stack */\r
755         pop r21\r
756         pop r20\r
757         in r0, SREG\r
758         cli ; we want to be uninterrupted while updating SP\r
759         out SPL, r20\r
760         out SPH, r21\r
761         out SREG, r0\r
762         \r
763         clr r1\r
764         pop r29\r
765         pop r28\r
766         pop r17\r
767         pop r16\r
768         pop r15\r
769         pop r14\r
770         pop r13\r
771         pop r12\r
772         pop r11\r
773         pop r10\r
774         ret\r
775 \r
776 sha1_nextBlock_xTable:\r
777 .byte 20,40,60,0\r
778 sha1_nextBlock_KTable:\r
779 .int    0x5a827999 \r
780 .int    0x6ed9eba1 \r
781 .int    0x8f1bbcdc \r
782 .int    0xca62c1d6\r
783 sha1_nextBlock_JumpTable:\r
784 jmp sha1_nextBlock_Ch   \r
785 jmp sha1_nextBlock_Parity\r
786 jmp sha1_nextBlock_Maj\r
787 jmp sha1_nextBlock_Parity\r
788 \r
789          /* X and Y still point at a[1] aka b ; return value in tmp1 */\r
790 sha1_nextBlock_Ch:\r
791         ld tmp1, Y+\r
792         mov tmp2, tmp1\r
793         com tmp2\r
794         ldd tmp3, Y+3   /* load from c */\r
795         and tmp1, tmp3\r
796         ldd tmp3, Y+7   /* load from d */\r
797         and tmp2, tmp3\r
798         eor tmp1, tmp2\r
799         /**\r
800         precall\r
801         ldi r24, lo8(ch_str)\r
802         ldi r25, hi8(ch_str)\r
803         call uart_putstr_P\r
804         postcall\r
805         /**/\r
806         ret\r
807         \r
808 sha1_nextBlock_Maj:\r
809         ld tmp1, Y+\r
810         mov tmp2, tmp1\r
811         ldd tmp3, Y+3   /* load from c */\r
812         and tmp1, tmp3\r
813         ldd tmp4, Y+7   /* load from d */\r
814         and tmp2, tmp4\r
815         eor tmp1, tmp2\r
816         and tmp3, tmp4\r
817         eor tmp1, tmp3\r
818         /**\r
819         precall\r
820         ldi r24, lo8(maj_str)\r
821         ldi r25, hi8(maj_str)\r
822         call uart_putstr_P\r
823         postcall\r
824         /**/\r
825         ret\r
826 \r
827 sha1_nextBlock_Parity:\r
828         ld tmp1, Y+\r
829         ldd tmp2, Y+3   /* load from c */\r
830         eor tmp1, tmp2\r
831         ldd tmp2, Y+7   /* load from d */\r
832         eor tmp1, tmp2\r
833         \r
834         /**\r
835         precall\r
836         ldi r24, lo8(parity_str)\r
837         ldi r25, hi8(parity_str)\r
838         call uart_putstr_P\r
839         postcall\r
840         /**/\r
841         ret\r
842 /*      \r
843 ch_str:                 .asciz "\r\nCh"\r
844 maj_str:                .asciz "\r\nMaj"\r
845 parity_str:     .asciz "\r\nParity"\r
846 */\r
847 ;###########################################################    \r
848 \r
849 .global sha1_init \r
850 ;void sha1_init(sha1_ctx_t *state){\r
851 ;       DEBUG_S("\r\nSHA1_INIT");\r
852 ;       state->h[0] = 0x67452301;\r
853 ;       state->h[1] = 0xefcdab89;\r
854 ;       state->h[2] = 0x98badcfe;\r
855 ;       state->h[3] = 0x10325476;\r
856 ;       state->h[4] = 0xc3d2e1f0;\r
857 ;       state->length = 0;\r
858 ;}\r
859 ; param1: (Func3,r24) 16-bit pointer to sha1_ctx_t struct in ram\r
860 ; modifys: Z(r30,r31), Func1, r22\r
861 sha1_init:\r
862         movw r26, r24 ; (24,25) --> (26,27) load X with param1\r
863         ldi r30, lo8((sha1_init_vector))\r
864         ldi r31, hi8((sha1_init_vector))\r
865         ldi r22, 5*4 /* bytes to copy */\r
866 sha1_init_vloop:        \r
867         lpm r23, Z+ \r
868         st X+, r23\r
869         dec r22\r
870         brne sha1_init_vloop\r
871         ldi r22, 8\r
872         clr r1 /* this should not be needed */\r
873 sha1_init_lloop:\r
874         st X+, r1\r
875         dec r22\r
876         brne sha1_init_lloop\r
877         ret\r
878         \r
879 sha1_init_vector:\r
880 .int 0x67452301;\r
881 .int 0xefcdab89;\r
882 .int 0x98badcfe;\r
883 .int 0x10325476;\r
884 .int 0xc3d2e1f0;\r
885 /*\r
886 ;###########################################################    \r
887 \r
888 .global rotl32\r
889 ; === ROTL32 ===\r
890 ; function that rotates a 32 bit word to the left\r
891 ;  param1: the 32-bit word to rotate\r
892 ;       given in r25,r24,r23,r22 (r25 is most significant)\r
893 ;  param2: an 8-bit value telling how often to rotate\r
894 ;       given in r20\r
895 ; modifys: r21, r22\r
896 rotl32:\r
897         cpi r20, 8\r
898         brlo bitrotl\r
899         mov r21, r25\r
900         mov r25, r24\r
901         mov r24, r23\r
902         mov r23, r22\r
903         mov r22, r21\r
904         subi r20, 8\r
905         rjmp rotr32\r
906 bitrotl:\r
907         clr r21\r
908         clc\r
909 bitrotl_loop:   \r
910         tst r20\r
911         breq fixrotl\r
912         rol r22\r
913         rol r23\r
914         rol r24\r
915         rol r25\r
916         rol r21\r
917         dec r20\r
918         rjmp bitrotl_loop\r
919 fixrotl:\r
920         or r22, r21\r
921         ret\r
922         \r
923 \r
924 ;###########################################################    \r
925 \r
926 .global rotr32\r
927 ; === ROTR32 ===\r
928 ; function that rotates a 32 bit word to the right\r
929 ;  param1: the 32-bit word to rotate\r
930 ;       given in r25,r24,r23,22 (r25 is most significant)\r
931 ;  param2: an 8-bit value telling how often to rotate\r
932 ;       given in r20\r
933 ; modifys: r21, r22\r
934 rotr32:\r
935         cpi r20, 8\r
936         brlo bitrotr\r
937         mov r21, r22\r
938         mov r22, r23\r
939         mov r23, r24\r
940         mov r24, r25\r
941         mov r25, r21\r
942         subi r20, 8\r
943         rjmp rotr32\r
944 bitrotr:\r
945         clr r21\r
946         clc\r
947 bitrotr_loop:   \r
948         tst r20\r
949         breq fixrotr\r
950         ror r25\r
951         ror r24\r
952         ror r23\r
953         ror r22\r
954         ror r21\r
955         dec r20\r
956         rjmp bitrotr_loop\r
957 fixrotr:\r
958         or r25, r21\r
959         ret\r
960         \r
961         \r
962 ;###########################################################    \r
963         \r
964 .global change_endian32\r
965 ; === change_endian32 ===\r
966 ; function that changes the endianess of a 32-bit word\r
967 ;  param1: the 32-bit word\r
968 ;       given in r25,r24,r23,22 (r25 is most significant)\r
969 ;  modifys: r21, r22\r
970 change_endian32:\r
971         movw r20,  r22 ; (r22,r23) --> (r20,r21)\r
972         mov r22, r25\r
973         mov r23, r24\r
974         mov r24, r21\r
975         mov r25, r20 \r
976         ret\r
977 */\r