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