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