New WPA-capable version of prism2.device.
[AROS.git] / workbench / devs / networks / prism2 / encryption_68k.s
blob20e924601037f9e4d8a639e85e0d581a81212ac0
1 /*
3 Copyright (C) 2011 Neil Cafferkey
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
23 /****i* prism2.device/UpdateMIC ********************************************
25 * NAME
26 * UpdateMIC -- Include new data into a Michael MIC value.
28 * SYNOPSIS
29 * UpdateMIC(left, right, data, count)
31 * VOID UpdateMIC(ULONG *, ULONG *, ULONG *, ULONG);
33 * INTERNALS
34 * Register assignment relative to C implementation:
36 * d2: l
37 * d3: r
38 * d4: count
39 * a2: left
40 * a3: right
41 * a4: data
43 ****************************************************************************
47 .globl _UpdateMIC
49 _UpdateMIC:
51 /* Anchor stack arguments */
53 link a5,#0
55 /* Push registers that should be preserved on to stack */
57 movem.l d2-d7/a2-a4,-(sp)
59 /* Apply transformation */
61 movea.l (8,a5),a2
62 movea.l (12,a5),a3
63 movea.l (16,a5),a4
64 move.l (20,a5),d4
65 subq.w #1,d4
67 move.l (a2),d2
68 move.l (a3),d3
70 mic_loop$:
72 move.l (a4)+,d0
73 rol.w #8,d0
74 swap.w d0
75 rol.w #8,d0
76 eor.l d0,d2
78 move.l d2,d0
79 swap.w d0
80 rol.l #1,d0
81 eor.l d0,d3
83 add.l d3,d2
85 move.l d2,d0
86 rol.w #8,d0
87 swap.w d0
88 rol.w #8,d0
89 swap.w d0
90 eor.l d0,d3
92 add.l d3,d2
94 move.l d2,d0
95 rol.l #3,d0
96 eor.l d0,d3
98 add.l d3,d2
100 move.l d2,d0
101 ror.l #2,d0
102 eor.l d0,d3
104 add.l d3,d2
106 dbra d4,mic_loop$
108 /* Store new left and right values */
110 move.l d2,(a2)
111 move.l d3,(a3)
113 /* Pop preserved registers off stack and return with original SP */
115 movem.l (sp)+,d2-d7/a2-a4
116 unlk a5
122 /****i* prism2.device/TKIPKeyMix2 ******************************************
124 * NAME
125 * TKIPKeyMix2 -- Apply phase 2 of the TKIP key-mixing function.
127 * SYNOPSIS
128 * TKIPKeyMix2(rc4_seed, ttak, tk, iv16)
130 * VOID TKIPKeyMix2(UBYTE *, UWORD *, UWORD *, UWORD);
132 * INTERNALS
133 * Register assignment relative to C implementation:
135 * d4: iv16
136 * a0: temp_key
137 * a1: sbox
138 * a2: rc4_seed
139 * a3: ttak
140 * a4: tk
142 ****************************************************************************
146 .globl _TKIPKeyMix2
148 _TKIPKeyMix2:
150 /* Anchor stack arguments */
152 link a5,#0
154 /* Push registers that should be preserved on to stack */
156 movem.l d2-d7/a2-a4,-(sp)
158 /* --- */
160 movea.l (12,a5),a3
162 move.l (a3)+,d5
163 move.l (a3)+,d6
164 move.w (a3)+,d7
166 move.w d7,d1
167 move.w (22,a5),d4
168 add.w d4,d1
169 swap.w d7
170 move.w d1,d7
172 movea.l (16,a5),a4
173 lea _sbox,a1
175 /* --- */
177 move.w (a4)+,d0
178 eor.w d0,d1
179 moveq #0,d2
180 move.b d1,d2
181 lsr.w #8,d1
182 lsl.w #1,d2
183 move.w (a1,d2:w),d0
184 lsl.w #1,d1
185 move.w (a1,d1:w),d1
186 rol.w #8,d1
187 eor.w d0,d1
188 swap.w d5
189 add.w d1,d5
191 move.w (a4)+,d1
192 eor.w d5,d1
193 moveq #0,d2
194 move.b d1,d2
195 lsr.w #8,d1
196 lsl.w #1,d2
197 move.w (a1,d2:w),d0
198 lsl.w #1,d1
199 move.w (a1,d1:w),d1
200 rol.w #8,d1
201 eor.w d0,d1
202 swap.w d5
203 add.w d1,d5
205 move.w (a4)+,d1
206 eor.w d5,d1
207 moveq #0,d2
208 move.b d1,d2
209 lsr.w #8,d1
210 lsl.w #1,d2
211 move.w (a1,d2:w),d0
212 lsl.w #1,d1
213 move.w (a1,d1:w),d1
214 rol.w #8,d1
215 eor.w d0,d1
216 swap.w d6
217 add.w d1,d6
219 move.w (a4)+,d1
220 eor.w d6,d1
221 moveq #0,d2
222 move.b d1,d2
223 lsr.w #8,d1
224 lsl.w #1,d2
225 move.w (a1,d2:w),d0
226 lsl.w #1,d1
227 move.w (a1,d1:w),d1
228 rol.w #8,d1
229 eor.w d0,d1
230 swap.w d6
231 add.w d1,d6
233 move.w (a4)+,d1
234 eor.w d6,d1
235 moveq #0,d2
236 move.b d1,d2
237 lsr.w #8,d1
238 lsl.w #1,d2
239 move.w (a1,d2:w),d0
240 lsl.w #1,d1
241 move.w (a1,d1:w),d1
242 rol.w #8,d1
243 eor.w d0,d1
244 swap.w d7
245 add.w d1,d7
247 move.w (a4)+,d1
248 eor.w d7,d1
249 moveq #0,d2
250 move.b d1,d2
251 lsr.w #8,d1
252 lsl.w #1,d2
253 move.w (a1,d2:w),d0
254 lsl.w #1,d1
255 move.w (a1,d1:w),d1
256 rol.w #8,d1
257 eor.w d0,d1
258 swap.w d7
259 add.w d1,d7
261 /* --- */
263 move.w (a4)+,d0
264 eor.w d7,d0
265 ror.w #1,d0
266 swap.w d5
267 add.w d0,d5
269 move.w (a4)+,d0
270 eor.w d5,d0
271 ror.w #1,d0
272 swap.w d5
273 add.w d5,d0
274 move.w d0,d5
276 ror.w #1,d0
277 swap.w d6
278 add.w d6,d0
279 move.w d0,d6
281 ror.w #1,d0
282 swap.w d6
283 add.w d6,d0
284 move.w d0,d6
286 ror.w #1,d0
287 swap.w d7
288 add.w d7,d0
289 move.w d0,d7
291 ror.w #1,d0
292 swap.w d7
293 add.w d7,d0
294 move.w d0,d7
296 /* Write RC4 seed */
298 movea.l (8,a5),a2
300 move.w d4,d1
301 rol.w #8,d1
302 move.b d1,(a2)+
303 ori.b #0x20,d1
304 andi.b #0x7f,d1
305 move.b d1,(a2)+
306 move.b d4,(a2)+
308 movea.l (16,a5),a4
309 move.w (a4),d1
310 eor.w d1,d0
311 lsr.w #1,d0
312 move.b d0,(a2)+
314 moveq #5,d3
316 rol.w #8,d5
317 swap.w d5
318 rol.w #8,d5
319 swap.w d5
320 move.l d5,(a2)+
322 rol.w #8,d6
323 swap.w d6
324 rol.w #8,d6
325 swap.w d6
326 move.l d6,(a2)+
328 rol.w #8,d7
329 swap.w d7
330 rol.w #8,d7
331 swap.w d7
332 move.l d7,(a2)+
334 /* Pop preserved registers off stack and return with original SP */
336 movem.l (sp)+,d2-d7/a2-a4
337 unlk a5
342 /****i* prism2.device/RC4Encrypt *******************************************
344 * NAME
345 * RC4Encrypt -- Encrypt data using the RC4 cipher, and append CRC.
347 * SYNOPSIS
348 * RC4Encrypt(unit, data, size, buffer, seed)
350 * VOID RC4Encrypt(struct DevUnit *, UBYTE *, UWORD, UBYTE *, UBYTE *);
352 * NOTES
353 * The input data may overlap the output buffer as long as the output
354 * address is not higher than the input address.
356 * INTERNALS
357 * Register assignment relative to C implementation:
359 * d2: n, i
360 * d3: j
361 * d4: "k"
362 * d5: crc
363 * a0: data
364 * a1: buffer
365 * a2: s
366 * a3: seed, crc32
368 ****************************************************************************
372 .globl _RC4Encrypt
374 _RC4Encrypt:
376 /* Anchor stack arguments and make space for S table */
378 link a5,#-256
380 /* Push registers that should be preserved on to stack */
382 movem.l d2-d7/a2-a4,-(sp)
384 /* Initialise RC4 state */
386 move.l #0x00010203,d2
387 lea (-256,a5),a2
388 movea.l a2,a0
390 preinit_state$:
392 move.l d2,(a0)+
393 add.l #0x04040404,d2
394 bcc.b preinit_state$
396 moveq #0,d2
397 moveq #0,d3
398 move.w #255,d4
399 movea.l (24,a5),a3
400 movea.l a2,a0
402 init_state$:
404 move.b (a0),d0
405 andi.w #0xf,d2
406 add.b (a3,d2:w),d3
407 add.b d0,d3
409 move.b (a2,d3:w),(a0)+
410 move.b d0,(a2,d3:w)
412 addq.b #1,d2
413 dbra d4,init_state$
415 /* Encrypt data and calculate CRC */
417 moveq #0,d1
418 moveq #0,d2
419 moveq #0,d3
420 move.w (18,a5),d4
421 subq.w #1,d4
422 moveq #-1,d5
423 moveq #0,d6
424 movea.l (12,a5),a0
425 movea.l (20,a5),a1
426 lea _crc32,a3
428 encrypt$:
430 /* Encrypt a byte */
432 addq.b #1,d2
433 move.b (a2,d2:w),d0
434 add.b d0,d3
436 move.b (a2,d3:w),d1
437 move.b d1,(a2,d2:w)
438 move.b d0,(a2,d3:w)
440 add.b d0,d1
441 move.b (a0)+,d0
442 move.b (a2,d1:w),d1
443 eor.b d0,d1
444 move.b d1,(a1)+
446 /* Update CRC */
448 eor.l d5,d0
449 andi.l #0xff,d0
450 lsl.l #2,d0
451 move.l (a3,d0:w),d0
452 lsr.l #8,d5
453 eor.l d0,d5
455 dbra d4,encrypt$
457 /* Check if CRC has been encrypted */
459 tst.b d6
460 bne.b crc_done$
461 moveq #1,d6
463 /* Copy CRC complement to buffer, then go back and encrypt it */
465 not.l d5
466 rol.w #8,d5
467 swap.w d5
468 rol.w #8,d5
469 move.l d5,(a1)
471 movea.l a1,a0
472 moveq #3,d4
473 bra.b encrypt$
475 crc_done$:
477 /* Pop preserved registers off stack and return with original SP */
479 movem.l (sp)+,d2-d7/a2-a4
480 unlk a5
485 /****i* prism2.device/RC4Decrypt *******************************************
487 * NAME
488 * RC4Decrypt -- Decrypt data using the RC4 cipher, and check CRC.
490 * SYNOPSIS
491 * success = RC4Encrypt(unit, data, size, buffer, seed)
493 * BOOL RC4Decrypt(struct DevUnit *, UBYTE *, UWORD, UBYTE *, UBYTE *);
495 * NOTES
496 * The input data may overlap the output buffer as long as the output
497 * address is not higher than the input address.
499 * The output buffer must be at least as big as the input data.
501 * INTERNALS
502 * This implementation skips the CRC/ICV check in order to gain speed.
504 * Register assignment relative to C implementation:
506 * d2: n, i
507 * d3: j
508 * a0: data
509 * a1: buffer
510 * a2: s
511 * a3: seed
513 ****************************************************************************
517 .globl _RC4Decrypt
519 _RC4Decrypt:
521 /* Anchor stack arguments and make space for S table */
523 link a5,#-256
525 /* Push registers that should be preserved on to stack */
527 movem.l d2-d7/a2-a4,-(sp)
529 /* Initialise RC4 state */
531 move.l #0x00010203,d2
532 lea (-256,a5),a2
533 movea.l a2,a0
535 preinit_state2$:
537 move.l d2,(a0)+
538 add.l #0x04040404,d2
539 bcc.b preinit_state2$
541 moveq #0,d2
542 moveq #0,d3
543 move.w #255,d4
544 movea.l (24,a5),a3
545 movea.l a2,a0
547 init_state2$:
549 move.b (a0),d0
550 andi.w #0xf,d2
551 add.b (a3,d2:w),d3
552 add.b d0,d3
554 move.b (a2,d3:w),(a0)+
555 move.b d0,(a2,d3:w)
557 addq.b #1,d2
558 dbra d4,init_state2$
560 /* Decrypt data and calculate CRC */
562 moveq #0,d1
563 moveq #0,d2
564 moveq #0,d3
565 move.w (18,a5),d4
566 subq.w #5,d4
567 movea.l (12,a5),a0
568 movea.l (20,a5),a1
570 decrypt$:
572 /* Decrypt a byte */
574 addq.b #1,d2
575 move.b (a2,d2:w),d0
576 add.b d0,d3
578 move.b (a2,d3:w),d1
579 move.b d1,(a2,d2:w)
580 move.b d0,(a2,d3:w)
582 add.b d0,d1
583 move.b (a0)+,d0
584 move.b (a2,d1:w),d1
585 eor.b d1,d0
586 move.b d0,(a1)+
588 dbra d4,decrypt$
590 /* Assume a good CRC */
592 moveq #-1,d0
595 /* Pop preserved registers off stack and return with original SP */
597 movem.l (sp)+,d2-d7/a2-a4
598 unlk a5
603 /****i* prism2.device/AESEncrypt *******************************************
605 * NAME
606 * AESEncrypt -- Encrypt a block using the AES cipher.
608 * SYNOPSIS
609 * AESEncrypt(data, buffer, key)
611 * VOID AESEncrypt(UBYTE *, UBYTE *, UBYTE *);
613 * INTERNALS
614 * Register assignment relative to C implementation:
616 * d0: s0
617 * d1: s1
618 * d2: s2
619 * d3: s3
620 * d4: i
621 * a0: s0, data
622 * a1: s1
623 * a2: s2
624 * a3: s3
625 * a4: s3, key, buffer
626 * a5: te0
628 ****************************************************************************
632 .globl _AESEncrypt
634 _AESEncrypt:
636 /* Anchor stack arguments */
638 link a5,#0
640 /* Push registers that should be preserved on to stack */
642 movem.l d2-d7/a2-a4,-(sp)
644 /* Initialise AES state */
646 movea.l (8,a5),a0
647 movea.l (16,a5),a4
648 move.l a5,d5
650 move.l (a0)+,d0
651 move.l (a4)+,d7
652 eor.l d7,d0
653 move.l (a0)+,d1
654 move.l (a4)+,d7
655 eor.l d7,d1
656 move.l (a0)+,d2
657 move.l (a4)+,d7
658 eor.l d7,d2
659 move.l (a0)+,d3
660 move.l (a4)+,d7
661 eor.l d7,d3
663 /* Save s values in address registers */
665 movea.l d0,a0
666 movea.l d1,a1
667 movea.l d2,a2
668 movea.l d3,a3
670 /* Apply first 9 rounds */
672 lea _te0,a5
673 moveq #8,d4
675 aes_loop$:
677 /* Initialise new state from key */
679 move.l (a4)+,d0
680 move.l (a4)+,d1
681 move.l (a4)+,d2
682 move.l (a4)+,d3
684 /* Inject s0-based data */
686 move.l a0,d6
688 moveq #0,d7
689 move.b d6,d7
690 move.l (0x300*4:w,a5,d7:w*4),d7
691 eor.l d7,d1
693 lsr.w #8,d6
694 move.l (0x200*4:w,a5,d6:w*4),d7
695 eor.l d7,d2
697 swap.w d6
698 moveq #0,d7
699 move.b d6,d7
700 move.l (0x100*4:w,a5,d7:w*4),d7
701 eor.l d7,d3
703 lsr.w #8,d6
704 move.l (a5,d6:w*4),d7
705 eor.l d7,d0
707 /* Inject s1-based data */
709 move.l a1,d6
711 moveq #0,d7
712 move.b d6,d7
713 move.l (0x300*4:w,a5,d7:w*4),d7
714 eor.l d7,d2
716 lsr.w #8,d6
717 move.l (0x200*4:w,a5,d6:w*4),d7
718 eor.l d7,d3
720 swap.w d6
721 moveq #0,d7
722 move.b d6,d7
723 move.l (0x100*4:w,a5,d7:w*4),d7
724 eor.l d7,d0
726 lsr.w #8,d6
727 move.l (a5,d6:w*4),d7
728 eor.l d7,d1
730 /* Inject s2-based data */
732 move.l a2,d6
734 moveq #0,d7
735 move.b d6,d7
736 move.l (0x300*4:w,a5,d7:w*4),d7
737 eor.l d7,d3
739 lsr.w #8,d6
740 move.l (0x200*4:w,a5,d6:w*4),d7
741 eor.l d7,d0
743 swap.w d6
744 moveq #0,d7
745 move.b d6,d7
746 move.l (0x100*4:w:w,a5,d7:w*4),d7
747 eor.l d7,d1
749 lsr.w #8,d6
750 move.l (a5,d6:w*4),d7
751 eor.l d7,d2
753 /* Inject s3-based data */
755 move.l a3,d6
757 moveq #0,d7
758 move.b d6,d7
759 move.l (0x300*4:w,a5,d7:w*4),d7
760 eor.l d7,d0
762 lsr.w #8,d6
763 move.l (0x200*4:w,a5,d6:w*4),d7
764 eor.l d7,d1
766 swap.w d6
767 moveq #0,d7
768 move.b d6,d7
769 move.l (0x100*4:w,a5,d7:w*4),d7
770 eor.l d7,d2
772 lsr.w #8,d6
773 move.l (a5,d6:w*4),d7
774 eor.l d7,d3
776 /* Save state values in address registers */
778 movea.l d0,a0
779 movea.l d1,a1
780 movea.l d2,a2
781 movea.l d3,a3
783 dbra d4,aes_loop$
785 /* Apply final round */
787 lea _te4,a5
789 /* Initialise new state from key */
791 move.l (a4)+,d0
792 move.l (a4)+,d1
793 move.l (a4)+,d2
794 move.l (a4)+,d3
796 /* Inject s0-based data */
798 move.l a0,d6
800 move.w d6,d7
801 andi.w #0xff,d7
802 lsl.w #2,d7
803 move.l (a5,d7:w),d7
804 andi.l #0x000000ff,d7
805 eor.l d7,d1
807 lsr.w #6,d6
808 move.w d6,d7
809 andi.w #0x3fc,d7
810 move.l (a5,d7:w),d7
811 andi.l #0x0000ff00,d7
812 eor.l d7,d2
814 swap.w d6
815 move.w d6,d7
816 andi.w #0xff,d7
817 lsl.w #2,d7
818 move.l (a5,d7:w),d7
819 andi.l #0x00ff0000,d7
820 eor.l d7,d3
822 lsr.w #6,d6
823 move.w d6,d7
824 andi.w #0x3fc,d7
825 move.l (a5,d7:w),d7
826 andi.l #0xff000000,d7
827 eor.l d7,d0
829 /* Inject s1-based data */
831 move.l a1,d6
833 move.w d6,d7
834 andi.w #0xff,d7
835 lsl.w #2,d7
836 move.l (a5,d7:w),d7
837 andi.l #0x000000ff,d7
838 eor.l d7,d2
840 lsr.w #6,d6
841 move.w d6,d7
842 andi.w #0x3fc,d7
843 move.l (a5,d7:w),d7
844 andi.l #0x0000ff00,d7
845 eor.l d7,d3
847 swap.w d6
848 move.w d6,d7
849 andi.w #0xff,d7
850 lsl.w #2,d7
851 move.l (a5,d7:w),d7
852 andi.l #0x00ff0000,d7
853 eor.l d7,d0
855 lsr.w #6,d6
856 move.w d6,d7
857 andi.w #0x3fc,d7
858 move.l (a5,d7:w),d7
859 andi.l #0xff000000,d7
860 eor.l d7,d1
862 /* Inject s2-based data */
864 move.l a2,d6
866 move.w d6,d7
867 andi.w #0xff,d7
868 lsl.w #2,d7
869 move.l (a5,d7:w),d7
870 andi.l #0x000000ff,d7
871 eor.l d7,d3
873 lsr.w #6,d6
874 move.l d6,d7
875 andi.w #0x3fc,d7
876 move.l (a5,d7:w),d7
877 andi.l #0x0000ff00,d7
878 eor.l d7,d0
880 swap.w d6
881 move.w d6,d7
882 andi.w #0xff,d7
883 lsl.w #2,d7
884 move.l (a5,d7:w),d7
885 andi.l #0x00ff0000,d7
886 eor.l d7,d1
888 lsr.w #6,d6
889 move.w d6,d7
890 andi.w #0x3fc,d7
891 move.l (a5,d7:w),d7
892 andi.l #0xff000000,d7
893 eor.l d7,d2
895 /* Inject s3-based data */
897 move.l a3,d6
899 move.w d6,d7
900 andi.w #0xff,d7
901 lsl.w #2,d7
902 move.l (a5,d7:w),d7
903 andi.l #0x000000ff,d7
904 eor.l d7,d0
906 lsr.w #6,d6
907 move.w d6,d7
908 andi.w #0x3fc,d7
909 move.l (a5,d7:w),d7
910 andi.l #0x0000ff00,d7
911 eor.l d7,d1
913 swap.w d6
914 move.w d6,d7
915 andi.w #0xff,d7
916 lsl.w #2,d7
917 move.l (a5,d7:w),d7
918 andi.l #0x00ff0000,d7
919 eor.l d7,d2
921 lsr.w #6,d6
922 move.w d6,d7
923 andi.w #0x3fc,d7
924 move.l (a5,d7:w),d7
925 andi.l #0xff000000,d7
926 eor.l d7,d3
928 /* Write final state to buffer */
930 movea.l d5,a5
931 movea.l (12,a5),a4
933 move.l d0,(a4)+
934 move.l d1,(a4)+
935 move.l d2,(a4)+
936 move.l d3,(a4)+
938 /* Pop preserved registers off stack and return with original SP */
940 movem.l (sp)+,d2-d7/a2-a4
941 unlk a5