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