]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bmw/bmw_small-tinyasm.S
further shrinked bmw tiny to 1648 bytes
[avr-crypto-lib.git] / bmw / bmw_small-tinyasm.S
1 /* bmw_small-tinyasm.S */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2009  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 /*
21  * File:        bmw_small-tinyasm.S
22  * Author:      Daniel Otte
23  * Date:        2010-03-28
24  * License:     GPLv3 or later
25  * Description: implementation of BlueMidnightWish
26  *
27  */
28
29 #include "avr-asm-macros.S"
30
31 acc2 =  8
32 acc3 =  9
33 acc0 = 14
34 acc1 = 15
35
36 /******************************************************************************/
37 /*
38   param a: r22:r23:r24:r25
39   param s: r20
40 */
41 shiftleft32:
42         clr r0
43         cpi r20, 8
44         brlo bitrotateleft_1
45         mov r25, r24
46         mov r24, r23
47         mov r23, r22
48         clr r22
49         subi r20, 8
50         rjmp shiftleft32
51
52 /******************************************************************************/
53 /*
54   param a: r22:r23:r24:r25
55   param s: r20
56 */
57 shiftright32:
58         cpi r20, 8
59         brlo bitshiftright
60         mov r22, r23
61         mov r23, r24
62         mov r24, r25
63         clr r25
64         subi r20, 8
65         rjmp shiftright32
66 bitshiftright:
67         tst r20
68         breq 20f
69 10:     lsr r25
70         ror r24
71         ror r23
72         ror r22
73         dec r20
74         brne 10b
75 20: ret
76
77 /******************************************************************************/
78 /*
79   param a: r22:r23:r24:r25
80   param s: r20
81 */
82 rotateleft32:
83         cpi r20, 8
84         brlo bitrotateleft
85         mov r0, r25
86         mov r25, r24
87         mov r24, r23
88         mov r23, r22
89         mov r22, r0
90         subi r20, 8
91         rjmp rotateleft32
92 bitrotateleft:
93     mov r0, r25
94 bitrotateleft_1:
95         tst r20
96         breq 20f
97 10:
98         lsl r0
99 rol32:
100         rol r22
101         rol r23
102         rol r24
103         rol r25
104         dec r20
105         brne 10b
106 20: ret
107
108
109 /******************************************************************************/
110
111 sn_stub:
112         movw r22, r2
113         movw r24, r4
114         lpm r20, Z+
115         rcall rotateleft32
116 eor32_to_acc:
117         eor acc0, r22
118         eor acc1, r23
119         eor acc2, r24
120         eor acc3, r25
121         ret
122
123 s_table:
124 s0:  .byte 1, 3, 4,19
125 s1:  .byte 1, 2, 8,23
126 s2:  .byte 2, 1,12,25
127 s3:  .byte 2, 2,15,29
128 s4:  .byte 1, 0, 0, 0
129 s5:  .byte 2, 0, 0, 0
130
131 h0   = 10
132 h1   = 11
133 m0   = 12
134 m1   = 13
135
136 /*
137   param x: r22:r23:r24:25
138   param s: r20
139 */
140 sn:
141         push_range 2, 5
142         push acc0
143         push acc1
144         push acc2
145         push acc3
146         ldi r30, lo8(s_table)
147         ldi r31, hi8(s_table)
148         lsl r20
149         lsl r20
150         add r30, r20
151         adc r31, r1
152         movw r2, r22
153         movw r4, r24
154         lpm r20, Z+
155         rcall shiftright32
156         rcall mov32_to_acc
157 ;---
158         movw r22, r2
159         movw r24, r4
160         lpm r20, Z+
161         rcall shiftleft32
162         rcall eor32_to_acc
163 ;---
164         rcall sn_stub
165         rcall sn_stub
166
167         movw r22, acc0
168         movw r24, acc2
169         pop acc3
170         pop acc2
171         pop acc1
172         pop acc0
173         rjmp pop5
174
175 /******************************************************************************/
176 /*
177   param dest: r26:r27 (X)
178   param src:  r30:r31 (Z)
179   param len:  r20
180 */
181 memxor_short:
182 ;       tst r20
183 ;       breq memxor_exit
184         ldi r20, 64
185 10: ld r21, X
186         ld r22, Z+
187         eor r21, r22
188         st X+, r21
189         dec r20
190         brne 10b
191 memxor_exit:
192         ret
193
194 /******************************************************************************/
195 q0 = 2
196 q1 = 3
197 h0 = 4
198 h1 = 5
199 m0 = 6
200 m1 = 7
201
202
203 /******************************************************************************/
204 load32_from_X:
205         ld r22, X+
206         ld r23, X+
207         ld r24, X+
208         ld r25, X+
209         ret
210
211 load32_from_Y:
212         ld r22, Y+
213         ld r23, Y+
214         ld r24, Y+
215         ld r25, Y+
216         ret
217
218 store32_to_Y:
219         st Y+, r22
220         st Y+, r23
221         st Y+, r24
222         st Y+, r25
223         ret
224
225 add_X_to_32:
226         ld r0, X+
227         add r22, r0
228         ld r0, X+
229         adc r23, r0
230         ld r0, X+
231         adc r24, r0
232         ld r0, X+
233         adc r25, r0
234         ret
235
236 store32_to_X:
237         st X+, r22
238         st X+, r23
239         st X+, r24
240         st X+, r25
241         ret
242
243 mov32_to_acc:
244         movw acc0, r22
245         movw acc2, r24
246         ret
247
248 eor_acc_from_Y_add_to_Z:
249         rcall load32_from_Y
250         rcall eor32_to_acc
251         rjmp  add_acc_to_Z
252
253 /******************************************************************************/
254 /*
255   param q:  r28:r29 (Y)
256   param h:  r26:r27 (X)
257   param m:  r30:r31 (Z)
258 */
259
260 f0_hacktable:
261         .byte 0x03, 0x11, 5*4
262         .byte 0xDD, 0xB3, 7*4
263         .byte 0x2A, 0x79, 10*4
264         .byte 0x07, 0xAA, 13*4
265         .byte 0x51, 0xC2, 14*4
266         .byte 0 ; just for alignment
267
268
269 /*******************************************************************************
270 * uint32_t addelment(uint8_t j, const uint32_t* m, const uint32_t* h){
271 *       uint32_t r;
272 *       r  = pgm_read_dword(k_lut+j);
273 *       r += rotl_addel(((uint32_t*)m)[j&0xf], j+0);
274 *       r += rotl_addel(((uint32_t*)m)[(j+3)&0xf], j+3);
275 *       r -= rotl_addel(((uint32_t*)m)[(j+10)&0xf], j+10);
276 *       r ^= ((uint32_t*)h)[(j+7)&0xf];
277 *       return r;
278 * }
279 * param j: r24
280 * param m: r22:r23
281 * param h: r20:r21
282 */
283 j    = 16
284 acc2 =  8
285 acc3 =  9
286 h0   = 10
287 h1   = 11
288 m0   = 12
289 m1   = 13
290 acc0 = 14
291 acc1 = 15
292
293 load_acc_from_X:
294         ld acc0, X+
295         ld acc1, X+
296         ld acc2, X+
297         ld acc3, X+
298         ret
299
300 add_acc_to_Z:
301         ld r0, Z
302         add r0, acc0
303         st Z+, r0
304         ld r0, Z
305         adc r0, acc1
306         st Z+, r0
307         ld r0, Z
308         adc r0, acc2
309         st Z+, r0
310         ld r0, Z
311         adc r0, acc3
312         st Z+, r0
313         ret
314
315 load_rotate_add_M:
316         mov r20, j
317         andi r20, 0x0f
318         mov r0, r20
319         lsl r0
320         lsl r0
321         movw r26, m0
322         add r26, r0
323         adc r27, r1
324         rcall load32_from_X
325         inc r20
326         rcall rotateleft32
327         brts 10f
328         rjmp add32_to_acc
329 ;       ret
330 10:     sub acc0, r22
331         sbc acc1, r23
332         sbc acc2, r24
333         sbc acc3, r25
334         ret
335
336
337 ;---
338
339 /******************************************************************************/
340 load_sn_add:
341         rcall load32_from_X
342         rcall sn
343 add32_to_acc:
344         add acc0, r22
345         adc acc1, r23
346         adc acc2, r24
347         adc acc3, r25
348         ret
349
350 /*
351   param q: r26:r27
352   param m: r22:r23
353   param h: r20:r21
354   param j: r24
355 */
356
357 expand_intro:
358         push_range 26, 27
359         push r24
360 addelement:
361         mov j, r24
362         movw h0, r20
363         movw m0, r22
364         sbiw r26, 4
365         rcall load_acc_from_X
366         ldi r24, 0x55
367         add acc0, r24
368         adc acc1, r24
369         adc acc2, r24
370         ldi r24, 5
371         adc acc3, r24
372         rcall store_acc_to_dec_X
373         adiw r26, 4
374         clt
375         rcall load_rotate_add_M
376         subi j, -3
377         rcall load_rotate_add_M
378         set
379         subi j, -7
380         rcall load_rotate_add_M
381         lsl j
382         lsl j
383         subi j, -7*4+10*4
384         andi j, 0x3f
385         movw r26, h0
386         add r26, j
387         adc r27, r1
388         rcall load32_from_X
389         rcall eor32_to_acc
390 ;--
391         pop r24
392         pop_range 26, 27
393         lsl r24
394         lsl r24
395         add r26, r24
396         adc r27, r1
397         ret
398 expand1:
399         rcall expand_intro
400         ldi r19, 1
401 10:
402         mov r20, r19
403         andi r20, 3
404         rcall load_sn_add
405         inc r19
406         cpi r19, 17
407         brne 10b
408         rjmp expand2_exit
409
410
411 /******************************************************************************/
412 /*
413   param q: r26:r27
414   param m: r22:r23
415   param h: r20:r21
416   param j: r24
417 */
418
419 f2_1_shift_table:
420         .byte 0x2B, 0x64, 0x66, 0x03, 0x51, 0x55, 0x87, 0x55
421 f2_2_shift_table:
422         .byte (2<<1), (7<<1), (4<<1), (3<<1), (4<<1)+1, (6<<1)+1, (6<<1)
423
424 expand2_rot_table:
425         .byte 3,7,13,16,19,23,27
426 ;       .byte 0 ; just for alignment
427
428 expand2:
429         rcall expand_intro
430         ldi r19, 14
431         ldi r30, lo8(expand2_rot_table)
432         ldi r31, hi8(expand2_rot_table)
433 10:
434         rcall load32_from_X
435         sbrs r19, 0
436         rjmp 12f
437         lpm r20, Z+
438         rcall rotateleft32
439 12:     rcall add32_to_acc
440         dec r19
441         brne 10b
442         ldi r20, 4
443         rcall load_sn_add
444         ldi r20, 5
445         rcall load_sn_add
446 expand2_exit:
447         adiw r26, 4
448 store_acc_to_dec_X:
449         st -X, acc3
450         st -X, acc2
451         st -X, acc1
452         st -X, acc0
453         ret
454
455 /******************************************************************************/
456 /*
457   param q: r24:r25
458   param m: r22:r23
459   param h: r20:r21
460 */
461 /* for calling expand1/2
462   param q: r26:r27
463   param m: r22:r23
464   param h: r20:r21
465   param j: r24
466 */
467
468 /******************************************************************************/
469 /*
470   param q: r24:r25
471   param m: r22:r23
472   param h: r20:r21
473 */
474
475 /******************************************************************************/
476 /*
477   param ctx:  r24:r25
478   param msg:  r22:r23
479 */
480 /* f0
481   param q:  r28:r29 (Y)
482   param h:  r26:r27 (X)
483   param m:  r30:r31 (Z)
484 */
485 /* f1
486   param q: r24:r25
487   param m: r22:r23
488   param h: r20:r21
489 */
490 /* f2
491   param q: r24:r25
492   param m: r22:r23
493   param h: r20:r21
494 */
495 q0 = 2
496 q1 = 3
497 h0 = 4
498 h1 = 5
499 m0 = 6
500 m1 = 7
501 ctx0 =   2
502 ctx1 =   3
503 msg0 =   4
504 msg1 =   5
505
506 restore_f1:
507         movw r26, r2
508         movw r22, r4
509     movw r20, r6
510         ret
511 bmw_small_nextBlock_early:
512         movw r24, ctx0
513         movw r22, msg0
514 .global bmw_small_nextBlock
515 .global bmw224_nextBlock
516 .global bmw256_nextBlock
517 bmw_small_nextBlock:
518 bmw224_nextBlock:
519 bmw256_nextBlock:
520         push_range  2, 7
521         push_range 28, 29
522         push_range  8, 17
523         stack_alloc_large 32*4, r28, r29
524         ldi r16, 0x4f
525         push r16
526         ldi r16, 0xff
527         push r16
528         push r16
529         ldi r16, 0xfb
530         push r16
531         adiw r28, 1
532 ;       push_range 28, 29 /* push Q */
533 ;       push_range 22, 25 /* push M & H */
534         /* increment counter */
535         movw r26, r24
536         movw r2, r26
537         adiw r26, 63
538         adiw r26,  1
539         rcall load_acc_from_X
540         ldi r19, 1
541         add acc0, r19
542         adc acc1, r1
543         adc acc2, r1
544         adc acc3, r1
545         rcall store_acc_to_dec_X
546         /* call f0 */
547         movw r30, r22
548         movw r26, r24
549 f0:
550         movw h0, r26
551         movw q0, r28
552         movw m0, r30
553         /* xor m into h */
554 ;       ldi r20, 64
555         rcall memxor_short
556         movw r30, m0
557         movw r26, h0
558
559         /* set q to zero */
560         ldi r22, 64
561 10:     st Y+, r1
562         dec r22
563         brne 10b
564         movw r28, q0
565         /* calculate W and store it in Q */
566         ldi r19, 5
567 30:
568         ldi r18, 16
569         /* load initial index */
570
571         /* load values from hacktable */
572         ldi r30, lo8(f0_hacktable-3)
573         ldi r31, hi8(f0_hacktable-3)
574         mov r16, r19
575         lsl r16
576         add r16, r19
577         add r30, r16
578         adc r31, r1
579         lpm r21, Z+
580         lpm r20, Z+
581         lpm r16, Z+
582 40:
583         ;call add_hx_to_w
584 add_hx_to_w:
585         movw r26, h0
586         add r26, r16
587         adc r27, r1
588         rcall load32_from_Y
589         sbiw r28, 4
590         lsl r20
591         rol r21
592         brcs 300f
593         /* addition */
594         rcall add_X_to_32
595         rjmp 500f
596 300: /* substract */
597         rcall load_acc_from_X
598         sub r22, acc0
599         sbc r23, acc1
600         sbc r24, acc2
601         sbc r25, acc3
602
603 500:
604         rcall store32_to_Y
605         subi r16, -4
606         andi r16, 0x0f<<2
607         dec r18
608         brne 40b
609         movw r28, q0
610         dec r19
611         brne 30b
612         movw r26, h0
613         /* xor m into h */
614 ;       ldi r20, 64
615         movw r26, h0
616         movw r30, m0
617         rcall memxor_short
618         sbiw r26, 60
619 ;---
620         clr r17
621         ldi r21, 15
622         mov r8, r21
623 50:
624         rcall load32_from_Y
625         sbiw r28, 4
626         mov r20, r17
627         rcall sn
628         inc r17
629         cpi r17, 5
630         brne 52f
631         clr r17
632 52:
633         rcall add_X_to_32
634         rcall store32_to_Y
635
636         dec r8
637         brne 50b
638 ;---
639         rcall load32_from_Y
640         clr r20
641         rcall sn
642         movw r26, h0
643         rcall add_X_to_32
644         sbiw r26, 4
645         sbiw r28, 4
646         rcall store32_to_Y
647         sbiw r28, 4
648         sbiw r28, 15*4
649         movw r20, h0
650         movw r22, m0
651
652         /* call f1*/
653         movw r2, r28
654 f1:
655         movw r4, r22
656         movw r6, r20
657         movw r26, r2
658         clr r24
659         rcall expand1
660         rcall restore_f1
661         ldi r24, 1
662         rcall expand1
663         ldi r17, 2
664 10: rcall restore_f1
665         mov r24, r17
666         rcall expand2
667         inc r17
668         sbrs r17, 4
669         rjmp 10b
670         rcall restore_f1
671         movw r24, r2
672
673
674         /* call f2 */
675 ;       pop_range 20, 25
676 ;       push_range 20, 25
677 ;       rcall printQ
678 ;       push r20
679 ;       push r21
680 acc2  =  8
681 acc3  =  9
682 acc0  = 14
683 acc1  = 15
684 xl0   =  2
685 xl1   =  3
686 xl2   =  4
687 xl3   =  5
688 xh0   =  6
689 xh1   =  7
690 xh2   = 10
691 xh3   = 11
692 q16_0 = 12
693 q16_1 = 13
694 h0   =  18
695 h1   =  19
696 f2:
697         movw r26, r24
698         /* calc XL */
699         adiw r26, 63
700         adiw r26,  1
701         movw q16_0, r26
702         movw h0, r20
703         movw r28, r22
704         rcall load32_from_X
705         rcall mov32_to_acc
706         ldi r17, 15
707 10:     rcall load32_from_X
708         rcall eor32_to_acc
709         cpi r17, 9
710         brne 15f
711         movw xl0, acc0
712         movw xl2, acc2
713 15:
714         dec r17
715         brne 10b
716         movw xh0, acc0
717         movw xh2, acc2
718 ;--- DBG
719 ;       push_range 22, 25
720 ;       movw r22, xl0
721 ;       movw r24, xl2
722 ;       rcall print32
723 ;       movw r22, xh0
724 ;       movw r24, xh2
725 ;       rcall print32
726 ;       pop_range 22, 25
727 ;--- END DBG
728
729 ;--- /* calc first half of h0..h15 */
730         movw r26, q16_0
731         ldi r17, 16
732 10:
733         rcall load32_from_Y
734         rcall mov32_to_acc
735 ;---
736         movw r22, xh0
737         movw r24, xh2
738         cpi r17, 9
739         brge 15f
740         clr r1
741         rjmp 26f
742 15:     ldi r30, lo8(f2_1_shift_table-9)
743         ldi r31, hi8(f2_1_shift_table-9)
744         add r30, r17
745         adc r31, r1
746         lpm r20, Z
747         mov r1, r20
748         andi r20, 0x0f
749         clt
750         cpi r17, 16
751         breq 20f
752         cpi r17, 11
753         brne 21f
754 20:     set
755 21:     brts 25f
756         rcall shiftright32
757         rjmp 26f
758 25:     rcall shiftleft32
759 26: rcall eor32_to_acc
760 ;---
761         rcall load32_from_X
762         mov r20, r1
763         clr r1
764         swap r20
765         andi r20, 0x0f
766         brts 27f
767         rcall shiftleft32
768         rjmp 28f
769 27:     rcall shiftright32
770 28:     rcall eor32_to_acc
771 ;---
772         movw r30, h0
773         st Z+, acc0
774         st Z+, acc1
775         st Z+, acc2
776         st Z+, acc3
777         movw h0, r30
778 ;---
779         dec r17
780         brne 10b
781 ;-----
782         sbiw r26, 4*8 /* X points to q[24] */
783         movw r28, r26
784         sbiw r28, 63
785         sbiw r28, 33 /* Y points to q[0] */
786         sbiw r30, 63
787         sbiw r30,  1 /* Z points to h0 */
788         ldi r17, 8
789 10:     movw acc0, xl0
790         movw acc2, xl2
791         rcall load32_from_X
792         rcall eor32_to_acc
793         rcall eor_acc_from_Y_add_to_Z
794         dec r17
795         brne 10b
796         sbiw r26, 9*4 /* X points to q[23] */
797         rcall load_acc_from_X
798         eor acc1, xl0
799         eor acc2, xl1
800         eor acc3, xl2
801         rcall eor_acc_from_Y_add_to_Z
802 ;---
803         sbiw r26, 8*4 /* X points to q[16] */
804         mov h0, r30
805         ldi r17, 7
806 10:
807         ldi r30, lo8(f2_2_shift_table-1)
808         ldi r31, hi8(f2_2_shift_table-1)
809         add r30, r17
810         adc r31, r1
811         lpm r20, Z
812         rcall load_acc_from_X
813         movw r22, xl0
814         movw r24, xl2
815         lsr r20
816         brcc 20f
817         rcall shiftleft32
818         rjmp 21f
819 20:     rcall shiftright32
820 21:
821         movw r30, h0
822         rcall eor32_to_acc
823         rcall eor_acc_from_Y_add_to_Z
824         movw h0, r30
825         dec r17
826         brne 10b
827 ;-----
828         sbiw r30, 8*4 /* Z points to h8 */
829         movw r26, r30
830         sbiw r26, 4*4 /* X points to h4 */
831         ldi r17, 8
832         ldi r18, 9
833 10:
834         rcall load32_from_X
835         mov r20, r18
836         rcall rotateleft32
837         rcall mov32_to_acc
838         rcall add_acc_to_Z
839         inc r18
840         cpi r17, 5
841         brne 20f
842         sbiw r26, 8*4
843 20:     dec r17
844         brne 10b
845
846 ;--- DBG
847 ;       pop r25
848 ;       pop r24
849 ;       ldi r22, 'H'
850 ;       rcall printX
851 ;--- END DBG
852         stack_free_large3 32*4+4
853         pop_range 10, 17
854 pop9:
855         pop_range 8, 9
856 pop28:
857         pop_range 28, 29
858 pop7:
859         pop_range 6, 7
860 pop5:
861         pop_range 2, 5
862         ret
863
864 /******************************************************************************/
865 ctx0 =  2
866 ctx1 =  3
867 blc0 =  4
868 blc1 =  5
869 len0 = 28
870 len1 = 29
871 buf0 =  6
872 buf1 =  7
873
874 load32_from_Z_stub:
875         movw r30, ctx0
876         adiw r30, 60
877         ldd r21, Z+4
878         ldd r22, Z+5
879         ldd r23, Z+6
880         ldd r24, Z+7
881         ret
882
883 /******************************************************************************/
884 /*
885   param ctx:  r24:r25
886   param msg:  r22:r23
887   param len:  r20:r21
888 */
889
890 .global bmw_small_lastBlock
891 .global bmw224_lastBlock
892 .global bmw256_lastBlock
893 bmw_small_lastBlock:
894 bmw224_lastBlock:
895 bmw256_lastBlock:
896 /*      while(length_b >= BMW_SMALL_BLOCKSIZE){
897                 bmw_small_nextBlock(ctx, block);
898                 length_b -= BMW_SMALL_BLOCKSIZE;
899                 block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
900         }
901 */
902         push_range 2, 7
903         push_range 28, 29
904         movw ctx0, r24
905         movw blc0, r22
906         movw len0, r20
907 1:
908         cpi len1, hi8(512)
909         brlo 2f
910         rcall bmw_small_nextBlock_early
911         ldi r24, 64
912         add blc0, r24
913         adc blc1, r1
914         subi len1, hi8(512)
915         rjmp 1b
916 2:
917 /*      struct {
918                 uint8_t  buffer[64];
919                 uint32_t ctr;
920         } pctx;
921 */
922         stack_alloc_large 68
923         adiw r30, 1
924         movw buf0, r30
925 /*      memset(pctx.buffer, 0, 64);
926         memcpy(pctx.buffer, block, (length_b+7)/8);
927         pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
928 */      movw r24, len0
929         ldi r23, 63
930         movw r26, blc0
931         lsr r25
932         ror r24
933         lsr r24
934         lsr r24
935         breq 301f
936         sub r23, r24
937         /* copy (#r24) bytes to stack buffer */
938 30: ld r20, X+
939         st Z+, r20
940         dec r24
941         brne 30b
942 301: /* calculate the appended byte */
943         clr r20
944         mov r21, len0
945         ldi r24, 0x80
946         andi r21, 0x07
947         breq 305f
948         ld r20, X+
949 303:
950         lsr r24
951         dec r21
952         brne 303b
953 305:
954         or r20, r24
955         st Z+, r20
956         tst r23
957         breq 32f
958 31: st Z+, r1
959         dec r23
960         brne 31b
961 32:
962 /*      if(length_b+1>64*8-64){ ; = 64*7-1 = 447 max(length_b)=511
963                 bmw_small_nextBlock(ctx, pctx.buffer);
964                 memset(pctx.buffer, 0, 64-8);
965                 ctx->counter -= 1;
966         }
967 */
968         tst len1
969         breq 400f
970         cpi len0, 192
971         brlo 400f
972         movw blc0, buf0
973         rcall bmw_small_nextBlock_early
974         movw r26, buf0
975         ldi r20, 64-8
976 350:
977         st X+, r1
978         dec r20
979         brne 350b
980         rcall load32_from_Z_stub
981         subi r21, 1
982         sbc r22, r1
983         sbc r23, r1
984         sbc r24, r1
985         rjmp 410f
986 /*      *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
987         bmw_small_nextBlock(ctx, pctx.buffer);
988 */
989 400:
990         rcall load32_from_Z_stub
991 410:
992         clr r25
993         ldi r20, 1
994         lsl r21
995         rcall rol32
996         mov r20, len0
997         add r21, len1
998         adc r22, r1
999         adc r23, r1
1000         adc r24, r1
1001         adc r25, r1
1002         movw r26, buf0
1003         adiw r26, 64-8
1004         st X+, r20
1005         st X+, r21
1006         rcall store32_to_X
1007         st X+, r1
1008         st X+, r1
1009         movw blc0, buf0
1010         rcall bmw_small_nextBlock_early
1011 /*      memset(pctx.buffer, 0xaa, 64);
1012         for(i=0; i<16;++i){
1013                 pctx.buffer[i*4] = i+0xa0;
1014         }
1015 */
1016         ldi r22, 0xa0
1017         ldi r23, 0xaa
1018         ldi r24, 0xaa
1019         ldi r25, 0xaa
1020         movw r26, buf0
1021 500:
1022         rcall store32_to_X
1023         inc r22
1024         sbrs r22, 4
1025         rjmp 500b
1026 /*      bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
1027         memcpy(ctx->h, pctx.buffer, 64);
1028 */
1029     movw r24, buf0
1030     movw r22, ctx0
1031     rcall bmw_small_nextBlock
1032         ldi r18, 64
1033         movw r26, ctx0
1034         movw r30, buf0
1035 600:
1036         ld r20, Z+
1037         st X+, r20
1038         dec r18
1039         brne 600b
1040
1041         stack_free_large 68
1042         rjmp pop28
1043
1044
1045 /*******************************************************************************
1046 * void bmw224_ctx2hash(void* dest, const bmw224_ctx_t* ctx){
1047 *       memcpy(dest, &(ctx->h[9]), 224/8);
1048 * }
1049 *
1050 * param dest:  r24:r25
1051 * param ctx:   r22:r23
1052 */
1053 .global bmw224_ctx2hash
1054 bmw224_ctx2hash:
1055         movw r30, r22
1056         adiw r30, 9*4
1057         ldi r18, 28
1058         rjmp 1f
1059
1060 /*******************************************************************************
1061 * void bmw256_ctx2hash(void* dest, const bmw256_ctx_t* ctx){
1062 *       memcpy(dest, &(ctx->h[8]), 256/8);
1063 * }
1064 *
1065 * param dest:  r24:r25
1066 * param ctx:   r22:r23
1067 */
1068 .global bmw256_ctx2hash
1069 bmw256_ctx2hash:
1070         movw r30, r22
1071         adiw r30, 8*4
1072         ldi r18, 32
1073 1:      movw r26, r24
1074 1:  ld r23, Z+
1075         st X+, r23
1076         dec r18
1077         brne 1b
1078         ret
1079
1080 /*******************************************************************************
1081 * void bmw256(void* dest, const void* msg, uint32_t length_b){
1082 *       bmw_small_ctx_t ctx;
1083 *       bmw256_init(&ctx);
1084 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
1085 *               bmw_small_nextBlock(&ctx, msg);
1086 *               length_b -= BMW_SMALL_BLOCKSIZE;
1087 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
1088 *       }
1089 *       bmw_small_lastBlock(&ctx, msg, length_b);
1090 *       bmw256_ctx2hash(dest, &ctx);
1091 * }
1092 *
1093 * param dest:     r24:r25
1094 * param msg:      r22:r23
1095 * param length_b: r18:r21
1096 */
1097 ctx0 =   2
1098 ctx1 =   3
1099 msg0 =   4
1100 msg1 =   5
1101 len0 =   6
1102 len1 =   7
1103 len2 =   8
1104 len3 =   9
1105 dst0 =  10
1106 dst1 =  11
1107 .global bmw256
1108 bmw256:
1109         set
1110         rjmp bmw_small_all
1111
1112
1113 /*******************************************************************************
1114 * void bmw224(void* dest, const void* msg, uint32_t length_b){
1115 *       bmw_small_ctx_t ctx;
1116 *       bmw224_init(&ctx);
1117 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
1118 *               bmw_small_nextBlock(&ctx, msg);
1119 *               length_b -= BMW_SMALL_BLOCKSIZE;
1120 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
1121 *       }
1122 *       bmw_small_lastBlock(&ctx, msg, length_b);
1123 *       bmw224_ctx2hash(dest, &ctx);
1124 * }
1125 *
1126 * param dest:     r24:r25
1127 * param msg:      r22:r23
1128 * param length_b: r18:r21
1129 */
1130 ctx0 =   2
1131 ctx1 =   3
1132 msg0 =   4
1133 msg1 =   5
1134 len0 =  28
1135 len1 =  29
1136 len2 =   8
1137 len3 =   9
1138 dst0 =   6
1139 dst1 =   7
1140 .global bmw224
1141 bmw224:
1142         clt
1143         rjmp bmw_small_all
1144
1145
1146 bmw_small_all:
1147         push_range 2, 7
1148         push_range 28, 29
1149         push_range 8, 9
1150         push r16
1151         stack_alloc_large 64+4
1152         adiw r30, 1
1153         clr r16
1154         brtc 10f
1155         inc r16
1156 10:     movw ctx0, r30
1157         movw dst0, r24
1158         movw msg0, r22
1159         movw len0, r18
1160         movw len2, r20
1161         movw r24, ctx0
1162         ldi r30, pm_lo8(init_lut)
1163         ldi r31, pm_hi8(init_lut)
1164         add r30, r16
1165         adc r31, r1
1166         icall
1167 20:
1168         mov r18, len2
1169         or  r18, len3
1170         breq 50f
1171         rcall bmw_small_nextBlock_early
1172         subi len1, 2
1173         sbc len2, r1
1174         sbc len3, r1
1175         ldi r20, 64
1176         add msg0, r20
1177         adc msg1, r1
1178         rjmp 20b
1179 50:
1180         movw r24, ctx0
1181         movw r22, msg0
1182         movw r20, len0
1183         rcall bmw_small_lastBlock
1184         movw r24, dst0
1185         movw r22, ctx0
1186         ldi r30, pm_lo8(c2h_lut)
1187         ldi r31, pm_hi8(c2h_lut)
1188         add r30, r16
1189         adc r31, r1
1190         icall
1191         stack_free_large 64+4
1192         pop r16
1193         rjmp pop9
1194
1195 init_lut:
1196         rjmp bmw224_init
1197         rjmp bmw256_init
1198 c2h_lut:
1199         rjmp bmw224_ctx2hash
1200         rjmp bmw256_ctx2hash
1201
1202 /*******************************************************************************
1203 * void bmw224_init(bmw224_ctx_t* ctx){
1204 *       uint8_t i;
1205 *       ctx->h[0] = 0x00010203;
1206 *       for(i=1; i<16; ++i){
1207 *               ctx->h[i] = ctx->h[i-1]+ 0x04040404;
1208 *       }
1209 *       ctx->counter=0;
1210 * }
1211 *
1212 * param ctx:  r24:r25
1213 */
1214 .global bmw224_init
1215 bmw224_init:
1216         ldi r22, 0x00
1217         ldi r23, 0x40
1218 bmw_small_init:
1219         movw r26, r24
1220         adiw r26, 4
1221 10:
1222         st -X, r22
1223         inc r22
1224         mov r20, r22
1225         andi r20, 0x3
1226         brne 10b
1227         adiw r26, 8
1228 20: cp r22, r23
1229         brne 10b
1230         st -X, r1
1231         st -X, r1
1232         st -X, r1
1233         st -X, r1
1234         ret
1235
1236 .global bmw256_init
1237 bmw256_init:
1238         ldi r22, 0x40
1239         ldi r23, 0x80
1240         rjmp bmw_small_init
1241
1242
1243 /******************************************************************************/
1244
1245 #if DEBUG
1246
1247 printQ:
1248         push_range 20, 25
1249         ldi r16, 4
1250         mov r9, r16
1251         movw r16, r24
1252         ldi r24, lo8(qdbg_str)
1253         ldi r25, hi8(qdbg_str)
1254         call cli_putstr_P
1255         clr r8
1256 10:     ldi r24, lo8(qdbg_str1)
1257         ldi r25, hi8(qdbg_str1)
1258         call cli_putstr_P
1259         mov r24, r8
1260         call cli_hexdump_byte
1261         ldi r24, lo8(qdbg_str2)
1262         ldi r25, hi8(qdbg_str2)
1263         call cli_putstr_P
1264         movw r24, r16
1265         clr r23
1266         ldi r22, 4
1267         call cli_hexdump_rev
1268         add r16, r9
1269         adc r17, r1
1270         inc r8
1271         sbrs r8, 5
1272         rjmp 10b
1273         pop_range 20, 25
1274         ret
1275 qdbg_str:  .asciz "\r\nDBG Q: "
1276 qdbg_str1: .asciz "\r\n Q["
1277 qdbg_str2: .asciz "] =  "
1278
1279
1280 printX:
1281         push_range 6, 9
1282         push_range 16, 27
1283         push_range 30, 31
1284         ldi r16, 4
1285         mov r6, r22
1286         mov r9, r16
1287         movw r16, r24
1288         ldi r24, lo8(Xdbg_str)
1289         ldi r25, hi8(Xdbg_str)
1290         call cli_putstr_P
1291         mov r24, r6
1292         call cli_putc
1293         ldi r24, ':'
1294         call cli_putc
1295         clr r8
1296 10:     ldi r24, lo8(Xdbg_str1)
1297         ldi r25, hi8(Xdbg_str1)
1298         call cli_putstr_P
1299         mov r24, r6
1300         call cli_putc
1301         ldi r24, '['
1302         call cli_putc
1303         mov r24, r8
1304         call cli_hexdump_byte
1305         ldi r24, lo8(Xdbg_str2)
1306         ldi r25, hi8(Xdbg_str2)
1307         call cli_putstr_P
1308         movw r24, r16
1309         clr r23
1310         ldi r22, 4
1311         call cli_hexdump_rev
1312         add r16, r9
1313         adc r17, r1
1314         inc r8
1315         sbrs r8, 4
1316         rjmp 10b
1317         pop_range 30, 31
1318         pop_range 16, 27
1319         pop_range 6, 9
1320         ret
1321 Xdbg_str:  .asciz "\r\nDBG "
1322 Xdbg_str1: .asciz "\r\n "
1323 Xdbg_str2: .asciz "] = "
1324
1325 print32:
1326         push_range 6, 9
1327         push_range 16, 27
1328         push_range 30, 31
1329         movw r6, r22
1330         movw r8, r24
1331         ldi r24, lo8(Xdbg_str)
1332         ldi r25, hi8(Xdbg_str)
1333         call cli_putstr_P
1334         mov r24, r9
1335         call cli_hexdump_byte
1336         mov r24, r8
1337         call cli_hexdump_byte
1338         mov r24, r7
1339         call cli_hexdump_byte
1340         mov r24, r6
1341         call cli_hexdump_byte
1342         pop_range 30, 31
1343         pop_range 16, 27
1344         pop_range 6, 9
1345         ret
1346
1347
1348 print_acc:
1349         push_range 16, 27
1350         push_range 30, 31
1351         ldi r24, lo8(Xdbg_str)
1352         ldi r25, hi8(Xdbg_str)
1353         call cli_putstr_P
1354         mov r24, r9
1355         call cli_hexdump_byte
1356         mov r24, r8
1357         call cli_hexdump_byte
1358         mov r24, r15
1359         call cli_hexdump_byte
1360         mov r24, r14
1361         call cli_hexdump_byte
1362         pop_range 30, 31
1363         pop_range 16, 27
1364         ret
1365
1366 #endif
1367