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