]> git.cryptolib.org Git - avr-crypto-lib.git/blob - md5-asm.S
changing hmac API + bug fixes
[avr-crypto-lib.git] / md5-asm.S
1 /* md5-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  * License: GPLv3 or later
22  * Date:    2008-11-15
23 */
24
25
26 #include "avr-asm-macros.S"
27
28 ;###########################################################    
29 ; S-BOX
30
31 T_table:
32 .hword  0xa478, 0xd76a, 0xb756, 0xe8c7, 0x70db, 0x2420, 0xceee, 0xc1bd, 0x0faf, 0xf57c 
33 .hword  0xc62a, 0x4787, 0x4613, 0xa830, 0x9501, 0xfd46, 0x98d8, 0x6980, 0xf7af, 0x8b44 
34 .hword  0x5bb1, 0xffff, 0xd7be, 0x895c, 0x1122, 0x6b90, 0x7193, 0xfd98, 0x438e, 0xa679 
35 .hword  0x0821, 0x49b4, 0x2562, 0xf61e, 0xb340, 0xc040, 0x5a51, 0x265e, 0xc7aa, 0xe9b6 
36 .hword  0x105d, 0xd62f, 0x1453, 0x0244, 0xe681, 0xd8a1, 0xfbc8, 0xe7d3, 0xcde6, 0x21e1 
37 .hword  0x07d6, 0xc337, 0x0d87, 0xf4d5, 0x14ed, 0x455a, 0xe905, 0xa9e3, 0xa3f8, 0xfcef 
38 .hword  0x02d9, 0x676f, 0x4c8a, 0x8d2a, 0x3942, 0xfffa, 0xf681, 0x8771, 0x6122, 0x6d9d 
39 .hword  0x380c, 0xfde5, 0xea44, 0xa4be, 0xcfa9, 0x4bde, 0x4b60, 0xf6bb, 0xbc70, 0xbebf 
40 .hword  0x7ec6, 0x289b, 0x27fa, 0xeaa1, 0x3085, 0xd4ef, 0x1d05, 0x0488, 0xd039, 0xd9d4 
41 .hword  0x99e5, 0xe6db, 0x7cf8, 0x1fa2, 0x5665, 0xc4ac, 0x2244, 0xf429, 0xff97, 0x432a 
42 .hword  0x23a7, 0xab94, 0xa039, 0xfc93, 0x59c3, 0x655b, 0xcc92, 0x8f0c, 0xf47d, 0xffef 
43 .hword  0x5dd1, 0x8584, 0x7e4f, 0x6fa8, 0xe6e0, 0xfe2c, 0x4314, 0xa301, 0x11a1, 0x4e08 
44 .hword  0x7e82, 0xf753, 0xf235, 0xbd3a, 0xd2bb, 0x2ad7, 0xd391, 0xeb86
45
46
47 #define MD5_init_fast
48
49 .global md5_init 
50 #ifndef MD5_init_fast
51 ;###########################################################    
52 ;void md5_init(md5_ctx_t *state)
53 ; param1: (r24,r25) 16-bit pointer to sha256_ctx_t struct in ram
54 ; modifys: Z(r30,r31), X(r25,r26)
55 ; size = 9+5*4 WORDS = 29 WORDS = 58 Bytes
56 md5_init:
57         movw r26, r24 ; (24,25) --> (26,27) load X with param1
58         ldi r30, lo8(md5_init_vector)
59         ldi r31, hi8(md5_init_vector)
60         ldi r24, 16+4
61 md5_init_vloop: 
62         lpm r0, Z+ 
63         st X+, r0
64         dec r24
65         brne md5_init_vloop
66         ret
67         
68 md5_init_vector:
69 .hword 0x2301, 0x6745
70 .hword 0xAB89, 0xEFCD 
71 .hword 0xDCFE, 0x98BA 
72 .hword 0x5476, 0x1032 
73 .hword 0x0000, 0x0000
74
75 #else
76 ;###########################################################    
77 .global md5_init_fast 
78 ;void md5_init(md5_ctx_t *state)
79 ; param1: (r24,r25) 16-bit pointer to sha256_ctx_t struct in ram
80 ; modifys: r23, r22
81 ; cycles = 1+16*3+4*2+4 = 1+48+12 = 61
82 ; size = 1+16*2+4+1 WORDS = 38 WORDS = 76 Bytes
83 md5_init:
84 md5_init_fast:
85         movw r26, r24
86         ldi r24, 0x01
87         st X+, r24
88         ldi r24, 0x23
89         st X+, r24
90         ldi r24, 0x45
91         st X+, r24
92         ldi r24, 0x67
93         st X+, r24
94         ldi r24, 0x89
95         st X+, r24
96         ldi r24, 0xAB
97         st X+, r24
98         ldi r24, 0xCD
99         st X+, r24
100         ldi r24, 0xEF
101         st X+, r24
102         ldi r24, 0xFE
103         st X+, r24
104         ldi r24, 0xDC
105         st X+, r24
106         ldi r24, 0xBA
107         st X+, r24
108         ldi r24, 0x98
109         st X+, r24
110         ldi r24, 0x76
111         st X+, r24
112         ldi r24, 0x54
113         st X+, r24
114         ldi r24, 0x32
115         st X+, r24
116         ldi r24, 0x10
117         st X+, r24
118         st X+, r1
119         st X+, r1
120         st X+, r1
121         st X+, r1
122         ret
123 #endif
124 ;###########################################################    
125
126 /*
127 static 
128 uint32_t md5_F(uint32_t x, uint32_t y, uint32_t z){
129         return ((x&y)|((~x)&z));
130 }
131 */
132 ; x: r22-r25
133 ; y: r18-r21
134 ; z: r14-r17
135 md5_F:
136         and r18, r22
137         and r19, r23
138         and r20, r24
139         and r21, r25
140         com r22
141         com r23
142         com r24
143         com r25
144         and r22, r14
145         and r23, r15
146         and r24, r16
147         and r25, r17
148         or  r22, r18
149         or  r23, r19
150         or  r24, r20
151         or  r25, r21
152         rjmp md5_core_F_exit
153         
154 /*
155 static
156 uint32_t md5_G(uint32_t x, uint32_t y, uint32_t z){
157         return ((x&z)|((~z)&y));
158 }
159 */
160
161 ; x: r22-r25
162 ; y: r18-r21
163 ; z: r14-r17
164 md5_G:
165         and r22, r14
166         and r23, r15
167         and r24, r16
168         and r25, r17
169         com r14
170         com r15
171         com r16
172         com r17
173         and r18, r14
174         and r19, r15
175         and r20, r16
176         and r21, r17
177         or  r22, r18
178         or  r23, r19
179         or  r24, r20
180         or  r25, r21
181         rjmp md5_core_F_exit
182 /*
183 static
184 uint32_t md5_H(uint32_t x, uint32_t y, uint32_t z){
185         return (x^y^z);
186 }
187 */
188 ; x: r22-r25
189 ; y: r18-r21
190 ; z: r14-r17
191 md5_H:
192         eor r22, r18
193         eor r22, r14
194         eor r23, r19
195         eor r23, r15
196         eor r24, r20
197         eor r24, r16
198         eor r25, r21
199         eor r25, r17
200         rjmp md5_core_F_exit
201 /*
202 static
203 uint32_t md5_I(uint32_t x, uint32_t y, uint32_t z){
204         return (y ^ (x | (~z)));
205 }
206 */
207
208 jump_table:
209         rjmp md5_F
210         rjmp md5_G
211         rjmp md5_H
212 ;       rjmp md5_I
213
214 ; x: r22-r25
215 ; y: r18-r21
216 ; z: r14-r17
217 md5_I:
218         com r14
219         com r15
220         com r16
221         com r17
222         or  r22, r14
223         or  r23, r15
224         or  r24, r16
225         or  r25, r17
226         eor r22, r18
227         eor r23, r19
228         eor r24, r20
229         eor r25, r21
230         rjmp md5_core_F_exit
231
232 as_table:
233 ;     (as+0)&3  (as+3)&3  (as+1)&3  (as+2)&3
234 ;                  Z         X         Y
235 ;     AS_SAVE0  AS_SAVE1  AS_SAVE2  AS_SAVE3 
236 .byte   1*4,      0*4,      2*4,      3*4    ;as=1
237 .byte   2*4,      1*4,      3*4,      0*4    ;as=2
238 .byte   3*4,      2*4,      0*4,      1*4    ;as=3
239 .byte   0*4,      3*4,      1*4,      2*4    ;as=4
240
241 ;###########################################################    
242 .global md5_core
243 md5_core:
244         mov r21, r20
245         mov r20, r18
246         mov r19, r16
247         mov r18, r14
248 ;       rjmp md5_core_asm
249 /*
250 void md5_core(uint32_t* a, void* block, uint8_t as, uint8_t s, uint8_t i, uint8_t fi){
251         uint32_t t;
252         md5_func_t* funcs[]={md5_F, md5_G, md5_H, md5_I};
253         as &= 0x3;
254         / * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). * /
255         t = a[as] + funcs[fi](a[(as+1)&3], a[(as+2)&3], a[(as+3)&3]) + *((uint32_t*)block) + md5_T[i] ;
256         a[as]=a[(as+1)&3] + ROTL32(t, s);
257 }
258 */
259 ; a:     r24-r25
260 ; block: r22-r23
261 ; as:    r21
262 ; s:     r20
263 ; i:     r19
264 ; fi:    r18
265 P_A0 = 24
266 P_A1 = 25
267 P_B0 = 22
268 P_B1 = 23
269 P_AS = 21
270 P_S  = 20
271 P_I  = 19
272 P_FI = 18
273
274 ; x: r22-r25
275 ; y: r18-r21
276 ; z: r14-r17
277
278
279 AS_SAVE0  =  4
280 AS_SAVE1  =  5
281 AS_SAVE2  =  6
282 AS_SAVE3  =  7
283 FI_SAVE   =  8
284 S_SAVE    =  9
285 ACCU0     = 10
286 ACCU1     = 11
287 ACCU2     = 12
288 ACCU3     = 13
289 ARG_X0    = 22
290 ARG_X1    = 23
291 ARG_X2    = 24
292 ARG_X3    = 25
293 ARG_Y0    = 18
294 ARG_Y1    = 19
295 ARG_Y2    = 20
296 ARG_Y3    = 21
297 ARG_Z0    = 14
298 ARG_Z1    = 15
299 ARG_Z2    = 16
300 ARG_Z3    = 17
301
302
303 md5_core_asm:
304         push r16
305         push r17
306         push_range 4, 8
307         ldi r30, lo8(T_table)
308         ldi r31, hi8(T_table)
309         lsl P_I
310         rol r1
311         lsl P_I
312         rol r1
313         add r30, P_I
314         adc r31, r1
315         clr r1
316         mov FI_SAVE, r18
317         /* loading T[i] into ACCU */    
318         lpm ACCU0, Z+   
319         lpm ACCU1, Z+   
320         lpm ACCU2, Z+   
321         lpm ACCU3, Z
322         /* add *block to ACCU */
323         movw r30, P_B0
324         ld r0, Z+
325         add ACCU0, r0
326         ld r0, Z+
327         adc ACCU1, r0
328         ld r0, Z+
329         adc ACCU2, r0
330         ld r0, Z+
331         adc ACCU3, r0
332         /* add a[as+0&3] to ACCU */
333         ldi r30, lo8(as_table)
334         ldi r31, hi8(as_table)
335         dec P_AS
336         andi P_AS, 0x03
337         lsl P_AS
338         lsl P_AS
339         add r30, r21
340         adc r31, r1       ; Z points to the correct row in as_table
341         lpm AS_SAVE0, Z+
342         lpm AS_SAVE1, Z+
343         lpm AS_SAVE2, Z+
344         lpm AS_SAVE3, Z
345         movw r26, r24     ; X points to a[0]
346         add r26, AS_SAVE0
347         adc r27, r1       ; X points at a[as&3]
348         ld r0, X+
349         add ACCU0, r0
350         ld r0, X+
351         adc ACCU1, r0
352         ld r0, X+
353         adc ACCU2, r0
354         ld r0, X+
355         adc ACCU3, r0
356         mov S_SAVE, r20
357
358         movw r28, r24
359         /* loading z value */
360         movw r26, r28
361         add r26, AS_SAVE1
362         adc r27, r1
363         ld ARG_Z0, X+
364         ld ARG_Z1, X+
365         ld ARG_Z2, X+
366         ld ARG_Z3, X
367
368         /* loading x value */
369         movw r26, r28   
370         add r26, AS_SAVE2
371         adc r27, r1
372         ld ARG_X0, X+
373         ld ARG_X1, X+
374         ld ARG_X2, X+
375         ld ARG_X3, X
376
377         /* loading y value */
378         movw r26, r28
379         add r26, AS_SAVE3
380         adc r27, r1
381         ldi r30, pm_lo8(jump_table)
382         ldi r31, pm_hi8(jump_table)
383         add r30, FI_SAVE
384         adc r31, r1    ; Z points to the correct entry in our jump table
385         ld ARG_Y0, X+
386         ld ARG_Y1, X+
387         ld ARG_Y2, X+
388         ld ARG_Y3, X
389
390         ijmp /* calls the function pointed by Z */
391 md5_core_F_exit:                
392
393         /* add ACCU to result of f() */
394         add r22, ACCU0
395         adc r23, ACCU1
396         adc r24, ACCU2
397         adc r25, ACCU3
398
399         /* rotate */
400         mov r20, S_SAVE
401 rotl32:
402         cpi r20, 8
403         brlo bitrotl
404         mov r21, r25
405         mov r25, r24
406         mov r24, r23
407         mov r23, r22
408         mov r22, r21
409         subi r20, 8
410         rjmp rotl32
411 bitrotl:
412         mov r21, r25
413 bitrotl_loop:   
414         tst r20
415         breq fixrotl
416 bitrotl_loop2:  
417         lsl r21
418         rol r22
419         rol r23
420         rol r24
421         rol r25
422         dec r20
423         brne bitrotl_loop2
424 fixrotl:
425
426         /* add a[(as+1)&3]  */
427         movw r26, r28
428         add r26, AS_SAVE2
429         adc r27, r1
430         ld r0, X+
431         add r22, r0
432         ld r0, X+
433         adc r23, r0
434         ld r0, X+
435         adc r24, r0
436         ld r0, X
437         adc r25, r0
438
439         /* store result */
440         movw r26, r28
441         add r26, AS_SAVE0
442         adc r27, r1
443         st X+, r22
444         st X+, r23
445         st X+, r24
446         st X , r25      
447 md5_core_exit:
448         pop_range 4, 8
449         pop r17
450         pop r16
451         ret
452
453 ;###################################################################
454 /*
455 void md5_nextBlock(md5_ctx_t *state, void* block){
456         uint32_t        a[4];
457         uint8_t         m,n,i=0;
458
459         a[0]=state->a[0];
460         a[1]=state->a[1];
461         a[2]=state->a[2];
462         a[3]=state->a[3];
463         
464         / * round 1 * /
465         uint8_t s1t[]={7,12,17,22}; // 1,-1   1,4   2,-1   3,-2
466         for(m=0;m<4;++m){
467                 for(n=0;n<4;++n){
468                         md5_core(a, &(((uint32_t*)block)[m*4+n]), 4-n, s1t[n],i++,0);
469                 }
470         }
471         / * round 2 * /
472         uint8_t s2t[]={5,9,14,20}; // 1,-3   1,1   2,-2   2,4
473         for(m=0;m<4;++m){
474                 for(n=0;n<4;++n){
475                         md5_core(a, &(((uint32_t*)block)[(1+m*4+n*5)&0xf]), 4-n, s2t[n],i++,1);
476                 }
477         }
478         / * round 3 * /
479         uint8_t s3t[]={4,11,16,23}; // 0,4   1,3   2,0   3,-1
480         for(m=0;m<4;++m){
481                 for(n=0;n<4;++n){
482                         md5_core(a, &(((uint32_t*)block)[(5-m*4+n*3)&0xf]), 4-n, s3t[n],i++,2);
483                 }
484         }
485         / * round 4 * /
486         uint8_t s4t[]={6,10,15,21}; // 1,-2   1,2   2,-1   3,-3
487         for(m=0;m<4;++m){
488                 for(n=0;n<4;++n){
489                         md5_core(a, &(((uint32_t*)block)[(0-m*4+n*7)&0xf]), 4-n, s4t[n],i++,3);
490                 }
491         }
492         state->a[0] += a[0];
493         state->a[1] += a[1];
494         state->a[2] += a[2];
495         state->a[3] += a[3];
496         state->counter++;
497 }
498 */
499
500 shift_table_1:  .byte  7,12,17,22
501 shift_table_2:  .byte  5, 9,14,20
502 shift_table_3:  .byte  4,11,16,23
503 shift_table_4:  .byte  6,10,15,21
504
505 index_table_r2:
506 ;(1+m*4+n*5)&0xf:
507         .byte 0x04, 0x18, 0x2c, 0x00 
508         .byte 0x14, 0x28, 0x3c, 0x10 
509         .byte 0x24, 0x38, 0x0c, 0x20 
510         .byte 0x34, 0x08, 0x1c, 0x30 
511
512 index_table_r3:
513 ;(5-m*4+n*3)&0xf:
514         .byte 0x14, 0x20, 0x2c, 0x38 
515         .byte 0x04, 0x10, 0x1c, 0x28 
516         .byte 0x34, 0x00, 0x0c, 0x18 
517         .byte 0x24, 0x30, 0x3c, 0x08 
518
519 index_table_r4:
520 ;(0-m*4+n*7)&0xf:
521         .byte 0x00, 0x1c, 0x38, 0x14 
522         .byte 0x30, 0x0c, 0x28, 0x04 
523         .byte 0x20, 0x3c, 0x18, 0x34 
524         .byte 0x10, 0x2c, 0x08, 0x24
525
526 APTR_REG = 2
527 BPTR_REG = 4
528 N_REG = 6
529 M_REG = 7
530 I_REG = 8
531 .global md5_nextBlock
532 md5_nextBlock:
533         stack_alloc 16
534         push_range 2, 17
535         push r28
536         push r29
537         push r24
538         push r25
539         adiw r30, 1 /* Z now points to the beginning of the allocated memory */
540         movw r2, r30
541         movw r4, r22
542         movw r26, r24
543         ldi r20, 16
544 1:
545         ld r0, X+
546         st Z+, r0
547         dec r20
548         brne 1b
549         /* state now copied to stack memory */
550         clr I_REG       
551         /* Round 1 */
552         clr M_REG
553         ldi r17, 4
554 1:
555         clr N_REG       
556         ldi r16, 4
557 2:
558         movw r24, APTR_REG
559         movw r22, BPTR_REG 
560         mov r0, M_REG
561         lsl r0
562         lsl r0
563         add r0, N_REG
564         lsl r0
565         lsl r0
566         add r22, r0
567         adc r23, r1
568         mov r21, r16    
569         ldi r30, lo8(shift_table_1)
570         ldi r31, hi8(shift_table_1)
571         add r30, N_REG
572         adc r31, r1
573         lpm r20, Z
574         mov r19, I_REG
575         ldi r18, 0
576         rcall md5_core_asm
577         inc I_REG
578         inc N_REG
579         dec r16
580         brne 2b
581         inc M_REG
582         dec r17
583         brne 1b
584         
585         /* Round 2 */
586         clr M_REG
587         ldi r17, 4
588 1:
589         clr N_REG       
590         ldi r16, 4
591 2:
592         movw r24, APTR_REG
593         movw r22, BPTR_REG 
594         ldi r30, lo8(index_table_r2)
595         ldi r31, hi8(index_table_r2)
596         mov r0, M_REG
597         lsl r0
598         lsl r0
599         add r0, N_REG
600         add r30, r0
601         adc r31, r1
602         lpm r0, Z       
603         add r22, r0
604         adc r23, r1
605         mov r21, r16    
606         ldi r30, lo8(shift_table_2)
607         ldi r31, hi8(shift_table_2)
608         add r30, N_REG
609         adc r31, r1
610         lpm r20, Z
611         mov r19, I_REG
612         ldi r18, 1
613         rcall md5_core_asm
614         inc I_REG
615         inc N_REG
616         dec r16
617         brne 2b
618         inc M_REG
619         dec r17
620         brne 1b
621
622         /* Round 3 */
623         clr M_REG
624         ldi r17, 4
625 1:
626         clr N_REG       
627         ldi r16, 4
628 2:
629         movw r24, APTR_REG
630         movw r22, BPTR_REG 
631         ldi r30, lo8(index_table_r3)
632         ldi r31, hi8(index_table_r3)
633         mov r0, M_REG
634         lsl r0
635         lsl r0
636         add r0, N_REG
637         add r30, r0
638         adc r31, r1
639         lpm r0, Z       
640         add r22, r0
641         adc r23, r1
642         mov r21, r16    
643         ldi r30, lo8(shift_table_3)
644         ldi r31, hi8(shift_table_3)
645         add r30, N_REG
646         adc r31, r1
647         lpm r20, Z
648         mov r19, I_REG
649         ldi r18, 2
650         rcall md5_core_asm
651         inc I_REG
652         inc N_REG
653         dec r16
654         brne 2b
655         inc M_REG
656         dec r17
657         brne 1b
658
659         /* Round 4 */
660         clr M_REG
661         ldi r17, 4
662 1:
663         clr N_REG       
664         ldi r16, 4
665 2:
666         movw r24, APTR_REG
667         movw r22, BPTR_REG 
668         ldi r30, lo8(index_table_r4)
669         ldi r31, hi8(index_table_r4)
670         mov r0, M_REG
671         lsl r0
672         lsl r0
673         add r0, N_REG
674         add r30, r0
675         adc r31, r1
676         lpm r0, Z       
677         add r22, r0
678         adc r23, r1
679         mov r21, r16    
680         ldi r30, lo8(shift_table_4)
681         ldi r31, hi8(shift_table_4)
682         add r30, N_REG
683         adc r31, r1
684         lpm r20, Z
685         mov r19, I_REG
686         ldi r18, 3
687         rcall md5_core_asm
688         inc I_REG
689         inc N_REG
690         dec r16
691         brne 2b
692         inc M_REG
693         dec r17
694         brne 1b
695
696
697         pop r27
698         pop r26 /* X now points to the context */
699         movw r30, APTR_REG
700         ldi r16, 4
701 1:
702         ld r0, X
703         ld r2, Z+
704         add r0, r2
705         st X+, r0       
706         ld r0, X
707         ld r2, Z+
708         adc r0, r2
709         st X+, r0       
710         ld r0, X
711         ld r2, Z+
712         adc r0, r2
713         st X+, r0       
714         ld r0, X
715         ld r2, Z+
716         adc r0, r2
717         st X+, r0       
718         dec r16
719         brne 1b
720
721         ld r0, X
722         inc r0
723         st X+, r0       
724         brne 2f
725         ld r0, X
726         inc r0
727         st X+, r0       
728         brne 2f
729         ld r0, X
730         inc r0
731         st X+, r0       
732         brne 2f 
733         ld r0, X
734         inc r0
735         st X+, r0       
736 2:                      
737
738         pop r29
739         pop r28
740         pop_range 2, 17
741         stack_free 16
742         ret
743
744 ;###############################################################################
745 /*
746 void md5_lastBlock(md5_ctx_t *state, const void* block, uint16_t length_b){
747         uint16_t l;
748         uint8_t b[64];
749         while (length_b >= 512){
750                 md5_nextBlock(state, block);
751                 length_b -= 512;
752                 block = ((uint8_t*)block) + 512/8;
753         }
754         memset(b, 0, 64);
755         memcpy(b, block, length_b/8);
756         / * insert padding one * /
757         l=length_b/8;
758         if(length_b%8){
759                 uint8_t t;
760                 t = ((uint8_t*)block)[l];
761                 t |= (0x80>>(length_b%8));
762                 b[l]=t;
763         }else{
764                 b[l]=0x80;
765         }
766         / * insert length value * /
767         if(l+sizeof(uint64_t) >= 512/8){
768                 md5_nextBlock(state, b);
769                 state->counter--;
770                 memset(b, 0, 64-8);
771         }
772         *((uint64_t*)&b[64-sizeof(uint64_t)]) = (state->counter * 512) + length_b;
773         md5_nextBlock(state, b);
774 }
775 */
776 ; state_ptr : r24,r25
777 ; block_ptr : r22,r23
778 ; length_b  : r20,r21
779 .global md5_lastBlock
780 md5_lastBlock:
781         stack_alloc_large 64
782         push_range 12, 17
783         push r30
784         push r31
785         movw r16, r20 /* length_b  */ 
786         movw r14, r22 /* block_ptr */
787         movw r12, r24 /* state_ptr */
788         ldi r18, 64
789 2:
790         cpi r17, 2 /* hi8(512) */       
791         brlo 2f
792 1:
793         movw r24, r12
794         movw r22, r14
795         rcall md5_nextBlock
796         add r14, r18
797         adc r15, r1
798         subi r17, 2
799         rjmp 2b
800 2:
801         pop r31
802         pop r30
803
804         adiw r30, 1 /* adjust Z to point to buffer */
805         movw r26, r14
806         movw r24, r16
807         adiw r24, 7
808
809         lsr r25
810         ror r24
811         lsr r25
812         ror r24
813         lsr r24 /* r24 now holds how many bytes are to copy */
814     ldi r18, 64
815         sub r18, r24 /* r18 will hold the amount of used bytes in buffer */
816         tst r24
817 4:
818         breq 5f
819         ld r0, X+
820         st Z+, r0 
821         dec r24
822         rjmp 4b /* Z points to the byte after msg in buffer */
823 5:      /* append 1-bit */
824         mov r20, r16
825         ldi r19, 0x80
826         andi r20, 0x07
827         brne bit_fucking
828         st Z+, r19
829         dec r18 /* 'allocate' another byte in buffer */
830         rjmp after_bit_fucking
831 bit_fucking:
832 1:
833         lsr r19
834         dec r20
835         brne 1b
836         or r0, r19
837         st -Z, r0
838     adiw r30, 1
839 after_bit_fucking:
840         clt     
841         cpi r18, 8
842         brmi 2f
843         set         /* store in t if the counter will also fit in this block (1 if fit)*/
844 2:
845         tst r18
846         breq 2f
847 1: /* fill remaning buffer with zeros */
848         st Z+, r1
849         dec r18
850         brne 1b
851 2:
852         sbiw r30, 63
853         sbiw r30,  1
854         movw r14, r30 /* r14:r15 now points to buffer */        
855         brts load_counter
856         /* counter does not fit, finalize this block */
857         movw r24, r12
858         movw r22, r14
859         rcall md5_nextBlock
860         movw r30, r14
861         ldi r20, 64-8
862 3:
863         st Z+, r1
864         dec r20
865         brne 3b
866         
867 load_counter:           
868         movw r26, r12 /* X points to state */
869         adiw r26, 16
870         ld r19, X+
871         ld r20, X+
872         ld r21, X+
873         ld r22, X+
874         brts post_counter_decrement     /* do not decremen because counter fits */
875 counter_decrement:
876         subi r19, 1
877         sbci r20, 0
878         sbci r21, 0
879         sbci r22, 0
880 post_counter_decrement:
881         clr r18
882         clr r23
883         lsl r19
884         rol r20
885         rol r21
886         rol r22
887         rol r23
888         mov r18, r16 /* r16:r17 length_b */
889         add r19, r17
890         adc r20, r1
891         adc r21, r1
892         adc r22, r1
893         adc r23, r1
894         movw r30, r14
895         adiw r30, 64-8
896         st Z+, r18
897         st Z+, r19
898         st Z+, r20
899         st Z+, r21
900         st Z+, r22
901         st Z+, r23
902         st Z+, r1
903         st Z, r1
904
905         sbiw r30, 63
906 ;       sbiw r30, 1
907         movw r24, r12
908         movw r22, r30
909         rcall md5_nextBlock
910 md5_lastBlock_exit:     
911         pop_range 12, 17
912         stack_free_large 64
913         ret
914
915
916 ;###############################################################################
917
918
919 .global md5_ctx2hash
920 md5_ctx2hash:
921         movw r26, r24
922         movw r30, r22
923         ldi r22, 16
924 1:
925         ld r0, Z+
926         st X+, r0
927         dec r22
928         brne 1b 
929         ret
930
931
932 ;###############################################################################
933
934
935 .global md5
936 md5:
937         stack_alloc 20
938         push_range  8, 17
939         adiw r30, 1
940         movw  r8, r30 /* ctx           */
941         movw r10, r24 /* dest          */
942         movw r12, r22 /* msg           */
943         movw r14, r18 /* length (low)  */
944         movw r16, r20 /* length (high) */
945         movw r24, r30
946         rcall md5_init
947 1:
948         tst r16
949         brne next_round
950         tst r17
951         breq last_round
952 next_round:
953         movw r24,  r8
954         movw r22, r12
955         rcall md5_nextBlock
956         ldi r22, 64
957         add r12, r22
958         adc r13, r1
959         ldi r22, 2
960         sub r15, r22
961         sbci r16, 0
962         sbci r17, 0
963         rjmp 1b
964 last_round:             
965         movw r24, r8
966         movw r22, r12
967         movw r20, r14
968         rcall md5_lastBlock
969         movw r24, r10
970         movw r22,  r8
971         rcall md5_ctx2hash
972         pop_range  8, 17
973         stack_free 20
974         ret
975
976
977