3 This file is part of the AVR-Crypto-Lib.
4 Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
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.
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.
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/>.
22 * License: GPLv3 or later
24 ; SHA1 implementation in assembler for AVR
29 /* push r18 - r27, r30 - r31*/
108 /* X points to Block */
109 .macro dbg_hexdump length
129 ; [h0][h1][h2][h3][h4][length]
130 ; hn is 32 bit large, length is 64 bit large
132 ;###########################################################
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
160 ;###########################################################
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
169 ; param3: 32-bit length value (length of message in bits)
170 ; given in r21,r20,r19,r18
196 movw r8, r18 /* backup of length*/
199 movw r12, r22 /* backup pf msg-ptr */
203 /* if length >= 512 */
256 ;###########################################################
259 ; block MUST NOT be larger than 64 bytes
261 .global sha1_lastBlock
262 ; === sha1_lastBlock ===
263 ; this function does padding & Co. for calculating SHA-1 hashes
264 ; param1: the 16-bit pointer to sha1_ctx structure
265 ; given in r25,r24 (r25 is most significant)
266 ; param2: an 16-bit pointer to 64 byte block to hash
268 ; param3: an 16-bit integer specifing length of block in bits
270 sha1_lastBlock_localSpace = (SHA1_BLOCK_BITS/8+1)
275 brne sha1_lastBlock_prolog
277 brne sha1_lastBlock_prolog
289 sha1_lastBlock_prolog:
290 /* allocate space on stack */
295 sbci r31, hi8(64) /* ??? */
301 adiw r30, 1 /* SP points to next free byte on stack */
302 mov r18, r20 /* r20 = LSB(length) */
306 bst r21, 0 /* may be we should explain this ... */
307 bld r18, 5 /* now: r18 == length/8 (aka. length in bytes) */
310 movw r26, r22 /* X points to begin of msg */
312 breq sha1_lastBlock_post_copy
314 sha1_lastBlock_copy_loop:
318 brne sha1_lastBlock_copy_loop
319 sha1_lastBlock_post_copy:
320 sha1_lastBlock_insert_stuffing_bit:
324 and r19, r20 /* if we are in bitmode */
325 breq 2f /* no bitmode */
331 /* maybe we should do some ANDing here, just for safety */
337 /* checking stuff here */
340 rjmp sha1_lastBlock_insert_zeros
342 /* oh shit, we landed here */
343 /* first we have to fill it up with zeros */
370 /* now we should subtract 512 from length */
372 adiw r26, 4*5+1 /* we can skip the lowest byte */
384 ; clr r18 /* not neccessary ;-) */
385 /* reset Z pointer to begin of block */
387 sha1_lastBlock_insert_zeros:
390 breq sha1_lastBlock_insert_length
393 st Z+, r1 /* r1 is still zero */
397 ; rjmp sha1_lastBlock_epilog
398 sha1_lastBlock_insert_length:
399 movw r26, r24 /* X points to state */
400 adiw r26, 5*4 /* X points to (state.length) */
401 adiw r30, 8 /* Z points one after the last byte of block */
420 sha1_lastBlock_epilog:
424 adiw r30, 63 ; lo8(64)
425 adiw r30, 1 ; hi8(64)
435 ;###########################################################
437 .global sha1_nextBlock
438 ; === sha1_nextBlock ===
439 ; this is the core function for calculating SHA-1 hashes
440 ; param1: the 16-bit pointer to sha1_ctx structure
441 ; given in r25,r24 (r25 is most significant)
442 ; param2: an 16-bit pointer to 64 byte block to hash
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)
465 /* byteorder: high number <--> high significance */
467 ; initial, let's make some space ready for local vars
468 /* replace push & pop by mem ops? */
481 movw r18, r20 ;backup SP
482 ; movw r26, r20 ; X points to free space on stack /* maybe removeable? */
483 movw r30, r22 ; Z points to message
484 subi r20, lo8(sha1_nextBlock_localSpace) ;sbiw can do only up to 63
485 sbci r21, hi8(sha1_nextBlock_localSpace)
486 movw r26, r20 ; X points to free space on stack
488 cli ; we want to be uninterrupted while updating SP
494 push r19 /* push old SP on new stack */
496 push r25 /* param1 will be needed later */
498 /* load a[] with state */
499 movw 28, r24 /* load pointer to state in Y */
508 movw W1, r26 /* save pointer to w[0] */
509 /* load w[] with endian fixed message */
510 /* we might also use the changeendian32() function at bottom */
511 movw r30, r22 /* mv param2 (ponter to msg) to Z */
526 ;clr LoopC /* LoopC is named t in FIPS 180-2 */
528 sha1_nextBlock_mainloop:
532 andi S, 0x3C /* S is a bytepointer so *4 */
535 add r26, S /* X points at w[s] */
562 brlt sha1_nextBlock_mainloop_core
571 1: /* this might be "outsourced" to save the jump above */
586 2: /* now we just hav to do a ROTL(T) and save T back */
601 sha1_nextBlock_mainloop_core: /* ther core function; T=ROTL5(a) ....*/
602 /* T already contains w[s] */
604 sbiw r26, 4*1 /* X points at a[4] aka e */
612 adc T4, tmp1 /* T = w[s]+e */
613 sbiw r26, 4*5 /* X points at a[0] aka a */
618 mov tmp1, F4 /* X points at a[1] aka b */
632 adc T4, F4 /* T = ROTL(a,5) + e + w[s] */
634 /* now we have to do this fucking conditional stuff */
635 ldi r30, lo8(sha1_nextBlock_xTable)
636 ldi r31, hi8(sha1_nextBlock_xTable)
643 1: ldi r30, lo8(sha1_nextBlock_KTable)
644 ldi r31, hi8(sha1_nextBlock_KTable)
660 /* T = ROTL(a,5) + e + kt + w[s] */
662 /* Z-4 is just pointing to kt ... */
663 movw r28, r26 /* copy X in Y */
664 adiw r30, 3*4 /* now Z points to the rigth locatin in our jump-vector-table */
679 adc T4, tmp1 /* T = ROTL5(a) + f_t(b,c,d) + e + k_t + w[s] */
680 /* X points still at a[1] aka b, Y points at a[2] aka c */
682 sha1_nextBlock_update_a:
683 /*first we move all vars in a[] "one up" e=d, d=c, c=b, b=a*/
684 //adiw r28, 3*4 /* Y should point at a[4] aka e */
694 /* Y points at a[0] aka a*/
698 /* store T in a[0] aka a */
703 /* Y points at a[1] aka b*/
735 rjmp sha1_nextBlock_mainloop
736 /**************************************/
741 /* add a[] to state and inc length */
743 pop r26 /* now X points to state (and Y still at a[0]) */
756 /* now length += 512 */
757 adiw r26, 1 /* we skip the least significant byte */
759 ldi tmp2, hi8(512) /* 2 */
771 sha1_nextBlock_epilog:
772 /* now we should clean up the stack */
776 cli ; we want to be uninterrupted while updating SP
794 sha1_nextBlock_xTable:
796 sha1_nextBlock_KTable:
801 sha1_nextBlock_JumpTable:
802 rjmp sha1_nextBlock_Ch
804 rjmp sha1_nextBlock_Parity
806 rjmp sha1_nextBlock_Maj
808 rjmp sha1_nextBlock_Parity
810 /* X and Y still point at a[1] aka b ; return value in tmp1 */
815 ldd tmp3, Y+3 /* load from c */
817 ldd tmp3, Y+7 /* load from d */
825 ldd tmp3, Y+3 /* load from c */
827 ldd tmp4, Y+7 /* load from d */
834 sha1_nextBlock_Parity:
836 ldd tmp2, Y+3 /* load from c */
838 ldd tmp2, Y+7 /* load from d */
842 ch_str: .asciz "\r\nCh"
843 maj_str: .asciz "\r\nMaj"
844 parity_str: .asciz "\r\nParity"
846 ;###########################################################
849 ;void sha1_init(sha1_ctx_t *state){
850 ; DEBUG_S("\r\nSHA1_INIT");
851 ; state->h[0] = 0x67452301;
852 ; state->h[1] = 0xefcdab89;
853 ; state->h[2] = 0x98badcfe;
854 ; state->h[3] = 0x10325476;
855 ; state->h[4] = 0xc3d2e1f0;
858 ; param1: (Func3,r24) 16-bit pointer to sha1_ctx_t struct in ram
859 ; modifys: Z(r30,r31), Func1, r22
861 movw r26, r24 ; (24,25) --> (26,27) load X with param1
862 ldi r30, lo8((sha1_init_vector))
863 ldi r31, hi8((sha1_init_vector))
864 ldi r22, 5*4 /* bytes to copy */