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