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