]> git.cryptolib.org Git - avr-crypto-lib.git/blob - sha1-asm.S
+RC5 +size-statistics tool +small modification to nessie_bc_test (optional free(...
[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         clc\r
648         ror r31\r
649         ror r30\r
650                 \r
651         icall\r
652         mov F1, tmp1\r
653         icall\r
654         mov F2, tmp1\r
655         icall\r
656         mov F3, tmp1\r
657         icall\r
658         \r
659         add T1, F1\r
660         adc T2, F2\r
661         adc T3, F3\r
662         adc T4, tmp1 /* T = ROTL5(a) + f_t(b,c,d) + e + k_t + w[s] */\r
663                                  /* X points still at a[1] aka b, Y points at a[2] aka c */     \r
664         /* update a[] */\r
665 sha1_nextBlock_update_a:\r
666         /*first we move all vars in a[] "one up" e=d, d=c, c=b, b=a*/\r
667         //adiw r28, 3*4  /* Y should point at a[4] aka e */\r
668         movw r28, W1\r
669         sbiw r28, 4\r
670         \r
671         ldi tmp2, 4*4 \r
672 1:      \r
673         ld tmp1, -Y\r
674         std Y+4, tmp1\r
675         dec tmp2\r
676         brne 1b\r
677         /* Y points at a[0] aka a*/\r
678         \r
679         movw r28, W1\r
680         sbiw r28, 5*4\r
681         /* store T in a[0] aka a */\r
682         st Y+, T1\r
683         st Y+, T2\r
684         st Y+, T3\r
685         st Y+, T4\r
686         /* Y points at a[1] aka b*/\r
687         \r
688         /* rotate c */\r
689         ldd T1, Y+1*4\r
690         ldd T2, Y+1*4+1\r
691         ldd T3, Y+1*4+2\r
692         ldd T4, Y+1*4+3\r
693         mov tmp1, T1\r
694         ldi tmp2, 2\r
695 1:      ror tmp1\r
696         ror T4\r
697         ror T3\r
698         ror T2\r
699         ror T1\r
700         dec tmp2\r
701         brne 1b\r
702         std Y+1*4+0, T1\r
703         std Y+1*4+1, T2\r
704         std Y+1*4+2, T3\r
705         std Y+1*4+3, T4\r
706         \r
707         push r27\r
708         push r26\r
709         movw r26, W1\r
710         sbiw r26, 4*5\r
711         dbg_hexdump 4*5\r
712         pop r26\r
713         pop r27\r
714         \r
715         inc LoopC\r
716         cpi LoopC, 80\r
717         brge 1f\r
718         jmp sha1_nextBlock_mainloop\r
719 /**************************************/\r
720 1:      \r
721    /* littel patch */\r
722         sbiw r28, 4\r
723 \r
724 /* add a[] to state and inc length */   \r
725         pop r27\r
726         pop r26         /* now X points to state (and Y still at a[0]) */\r
727         ldi tmp4, 5\r
728 1:      clc\r
729         ldi tmp3, 4\r
730 2:      ld tmp1, X\r
731         ld tmp2, Y+\r
732         adc tmp1, tmp2\r
733         st X+, tmp1\r
734         dec tmp3\r
735         brne 2b\r
736         dec tmp4\r
737         brne 1b\r
738         \r
739         /* now length += 512 */\r
740         adiw r26, 1 /* we skip the least significant byte */\r
741         ld tmp1, X\r
742         ldi tmp2, hi8(512) /* 2 */\r
743         add tmp1, tmp2\r
744         st X+, tmp1\r
745         ldi tmp2, 6\r
746 1:\r
747         ld tmp1, X\r
748         adc tmp1, xNULL\r
749         st X+, tmp1\r
750         dec tmp2\r
751         brne 1b\r
752         \r
753 ; EPILOG\r
754 sha1_nextBlock_epilog:\r
755 /* now we should clean up the stack */\r
756         pop r21\r
757         pop r20\r
758         in r0, SREG\r
759         cli ; we want to be uninterrupted while updating SP\r
760         out SPL, r20\r
761         out SPH, r21\r
762         out SREG, r0\r
763         \r
764         clr r1\r
765         pop r29\r
766         pop r28\r
767         pop r17\r
768         pop r16\r
769         pop r15\r
770         pop r14\r
771         pop r13\r
772         pop r12\r
773         pop r11\r
774         pop r10\r
775         ret\r
776 \r
777 sha1_nextBlock_xTable:\r
778 .byte 20,40,60,0\r
779 sha1_nextBlock_KTable:\r
780 .int    0x5a827999 \r
781 .int    0x6ed9eba1 \r
782 .int    0x8f1bbcdc \r
783 .int    0xca62c1d6\r
784 sha1_nextBlock_JumpTable:\r
785 jmp sha1_nextBlock_Ch   \r
786 jmp sha1_nextBlock_Parity\r
787 jmp sha1_nextBlock_Maj\r
788 jmp sha1_nextBlock_Parity\r
789 \r
790          /* X and Y still point at a[1] aka b ; return value in tmp1 */\r
791 sha1_nextBlock_Ch:\r
792         ld tmp1, Y+\r
793         mov tmp2, tmp1\r
794         com tmp2\r
795         ldd tmp3, Y+3   /* load from c */\r
796         and tmp1, tmp3\r
797         ldd tmp3, Y+7   /* load from d */\r
798         and tmp2, tmp3\r
799         eor tmp1, tmp2\r
800         /**\r
801         precall\r
802         ldi r24, lo8(ch_str)\r
803         ldi r25, hi8(ch_str)\r
804         call uart_putstr_P\r
805         postcall\r
806         /**/\r
807         ret\r
808         \r
809 sha1_nextBlock_Maj:\r
810         ld tmp1, Y+\r
811         mov tmp2, tmp1\r
812         ldd tmp3, Y+3   /* load from c */\r
813         and tmp1, tmp3\r
814         ldd tmp4, Y+7   /* load from d */\r
815         and tmp2, tmp4\r
816         eor tmp1, tmp2\r
817         and tmp3, tmp4\r
818         eor tmp1, tmp3\r
819         /**\r
820         precall\r
821         ldi r24, lo8(maj_str)\r
822         ldi r25, hi8(maj_str)\r
823         call uart_putstr_P\r
824         postcall\r
825         /**/\r
826         ret\r
827 \r
828 sha1_nextBlock_Parity:\r
829         ld tmp1, Y+\r
830         ldd tmp2, Y+3   /* load from c */\r
831         eor tmp1, tmp2\r
832         ldd tmp2, Y+7   /* load from d */\r
833         eor tmp1, tmp2\r
834         \r
835         /**\r
836         precall\r
837         ldi r24, lo8(parity_str)\r
838         ldi r25, hi8(parity_str)\r
839         call uart_putstr_P\r
840         postcall\r
841         /**/\r
842         ret\r
843 /*      \r
844 ch_str:                 .asciz "\r\nCh"\r
845 maj_str:                .asciz "\r\nMaj"\r
846 parity_str:     .asciz "\r\nParity"\r
847 */\r
848 ;###########################################################    \r
849 \r
850 .global sha1_init \r
851 ;void sha1_init(sha1_ctx_t *state){\r
852 ;       DEBUG_S("\r\nSHA1_INIT");\r
853 ;       state->h[0] = 0x67452301;\r
854 ;       state->h[1] = 0xefcdab89;\r
855 ;       state->h[2] = 0x98badcfe;\r
856 ;       state->h[3] = 0x10325476;\r
857 ;       state->h[4] = 0xc3d2e1f0;\r
858 ;       state->length = 0;\r
859 ;}\r
860 ; param1: (Func3,r24) 16-bit pointer to sha1_ctx_t struct in ram\r
861 ; modifys: Z(r30,r31), Func1, r22\r
862 sha1_init:\r
863         movw r26, r24 ; (24,25) --> (26,27) load X with param1\r
864         ldi r30, lo8((sha1_init_vector))\r
865         ldi r31, hi8((sha1_init_vector))\r
866         ldi r22, 5*4 /* bytes to copy */\r
867 sha1_init_vloop:        \r
868         lpm r23, Z+ \r
869         st X+, r23\r
870         dec r22\r
871         brne sha1_init_vloop\r
872         ldi r22, 8\r
873         clr r1 /* this should not be needed */\r
874 sha1_init_lloop:\r
875         st X+, r1\r
876         dec r22\r
877         brne sha1_init_lloop\r
878         ret\r
879         \r
880 sha1_init_vector:\r
881 .int 0x67452301;\r
882 .int 0xefcdab89;\r
883 .int 0x98badcfe;\r
884 .int 0x10325476;\r
885 .int 0xc3d2e1f0;\r
886 /*\r
887 ;###########################################################    \r
888 \r
889 .global rotl32\r
890 ; === ROTL32 ===\r
891 ; function that rotates a 32 bit word to the left\r
892 ;  param1: the 32-bit word to rotate\r
893 ;       given in r25,r24,r23,r22 (r25 is most significant)\r
894 ;  param2: an 8-bit value telling how often to rotate\r
895 ;       given in r20\r
896 ; modifys: r21, r22\r
897 rotl32:\r
898         cpi r20, 8\r
899         brlo bitrotl\r
900         mov r21, r25\r
901         mov r25, r24\r
902         mov r24, r23\r
903         mov r23, r22\r
904         mov r22, r21\r
905         subi r20, 8\r
906         rjmp rotr32\r
907 bitrotl:\r
908         clr r21\r
909         clc\r
910 bitrotl_loop:   \r
911         tst r20\r
912         breq fixrotl\r
913         rol r22\r
914         rol r23\r
915         rol r24\r
916         rol r25\r
917         rol r21\r
918         dec r20\r
919         rjmp bitrotl_loop\r
920 fixrotl:\r
921         or r22, r21\r
922         ret\r
923         \r
924 \r
925 ;###########################################################    \r
926 \r
927 .global rotr32\r
928 ; === ROTR32 ===\r
929 ; function that rotates a 32 bit word to the right\r
930 ;  param1: the 32-bit word to rotate\r
931 ;       given in r25,r24,r23,22 (r25 is most significant)\r
932 ;  param2: an 8-bit value telling how often to rotate\r
933 ;       given in r20\r
934 ; modifys: r21, r22\r
935 rotr32:\r
936         cpi r20, 8\r
937         brlo bitrotr\r
938         mov r21, r22\r
939         mov r22, r23\r
940         mov r23, r24\r
941         mov r24, r25\r
942         mov r25, r21\r
943         subi r20, 8\r
944         rjmp rotr32\r
945 bitrotr:\r
946         clr r21\r
947         clc\r
948 bitrotr_loop:   \r
949         tst r20\r
950         breq fixrotr\r
951         ror r25\r
952         ror r24\r
953         ror r23\r
954         ror r22\r
955         ror r21\r
956         dec r20\r
957         rjmp bitrotr_loop\r
958 fixrotr:\r
959         or r25, r21\r
960         ret\r
961         \r
962         \r
963 ;###########################################################    \r
964         \r
965 .global change_endian32\r
966 ; === change_endian32 ===\r
967 ; function that changes the endianess of a 32-bit word\r
968 ;  param1: the 32-bit word\r
969 ;       given in r25,r24,r23,22 (r25 is most significant)\r
970 ;  modifys: r21, r22\r
971 change_endian32:\r
972         movw r20,  r22 ; (r22,r23) --> (r20,r21)\r
973         mov r22, r25\r
974         mov r23, r24\r
975         mov r24, r21\r
976         mov r25, r20 \r
977         ret\r
978 */\r