File: AESAux.hs

package info (click to toggle)
haskell-crypto 4.2.4-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 344 kB
  • sloc: haskell: 2,949; makefile: 2
file content (1008 lines) | stat: -rw-r--r-- 24,733 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
-- | Advanced Encryption System (specification can be found in FIPS-197)
module Codec.Encryption.AESAux(
	aes128Encrypt,
	aes192Encrypt,
	aes256Encrypt,
	aes128Decrypt,
	aes192Decrypt,
	aes256Decrypt,
) where

import Data.Bits
import Data.Int(Int)
import Data.Word(Word32)

import Codec.Utils(Octet)

aes128Encrypt :: [Octet] -- ^ key (16 octets)
	      -> [Octet] -- ^ msg (16 octets)
	      -> [Octet] -- ^ enciphered msg (16 octets)
aes128Encrypt = aesEncrypt 10 4

aes192Encrypt :: [Octet] -- ^ key (24 octets)
	      -> [Octet] -- ^ msg (16 octets)
	      -> [Octet] -- ^ enciphered msg (16 octets)
aes192Encrypt = aesEncrypt 12 6

aes256Encrypt :: [Octet] -- ^ key (32 octets)
	      -> [Octet] -- ^ msg (16 octets)
	      -> [Octet] -- ^ enciphered msg (16 octets)
aes256Encrypt = aesEncrypt 14 8

aes128Decrypt :: [Octet] -- ^ key (16 octets)
	      -> [Octet] -- ^ enciphered msg (16 octets)
	      -> [Octet] -- ^ deciphered msg (16 octets)
aes128Decrypt = aesDecrypt 10 4

aes192Decrypt :: [Octet] -- ^ key (24 octets)
	      -> [Octet] -- ^ enciphered msg (16 octets)
	      -> [Octet] -- ^ deciphered msg (16 octets)
aes192Decrypt = aesDecrypt 12 6

aes256Decrypt :: [Octet] -- ^ key (32 octets)
	      -> [Octet] -- ^ enciphered msg (16 octets)
	      -> [Octet] -- ^ deciphered msg (16 octets)
aes256Decrypt = aesDecrypt 14 8

aesEncrypt :: Int     -- ^ nr 
	   -> Int     -- ^ nk
	   -> [Octet] -- ^ key
	   -> [Octet] -- ^ msg
	   -> [Octet] -- ^ enciphered msg
aesEncrypt nr nk key 
		[i00, i10, i20, i30,
		 i01, i11, i21, i31,
		 i02, i12, i22, i32,
		 i03, i13, i23, i33] =
		[fo o00, fo o10, fo o20, fo o30,
		 fo o01, fo o11, fo o21, fo o31,
		 fo o02, fo o12, fo o22, fo o32,
		 fo o03, fo o13, fo o23, fo o33]
	where State (o00, o01, o02, o03)	 
		    (o10, o11, o12, o13)	 
		    (o20, o21, o22, o23)	 
		    (o30, o31, o32, o33) = transform (
		    	State(fi i00, fi i01, fi i02, fi i03)
		    	     (fi i10, fi i11, fi i12, fi i13)
		    	     (fi i20, fi i21, fi i22, fi i23)
		    	     (fi i30, fi i31, fi i32, fi i33))
	      fi = (fromIntegral :: Octet -> Word32)		     
	      fo = (fromIntegral :: Word32 -> Octet)		     
	      (kt0:kts) = genAddRoundKey (generateKeys nr nk key)
	      transform = foldr (.) kt0 (reverse rest)
	      mss = replicate (nr - 1) (mixColumns . shiftRows . subBytes)
	      rest = zipWith (.) kts (mss ++ [shiftRows . subBytes ])
	      

aesDecrypt :: Int     -- ^ nr 
	   -> Int     -- ^ nk
	   -> [Octet] -- ^ key
	   -> [Octet] -- ^ enciphered msg
	   -> [Octet] -- ^ deciphered msg
aesDecrypt nr nk key 
		[i00, i10, i20, i30,
		 i01, i11, i21, i31,
		 i02, i12, i22, i32,
		 i03, i13, i23, i33] =
		[fo o00, fo o10, fo o20, fo o30,
		 fo o01, fo o11, fo o21, fo o31,
		 fo o02, fo o12, fo o22, fo o32,
		 fo o03, fo o13, fo o23, fo o33]
	where State (o00, o01, o02, o03)	 
		    (o10, o11, o12, o13)	 
		    (o20, o21, o22, o23)	 
		    (o30, o31, o32, o33) = transform (
		    	State(fi i00, fi i01, fi i02, fi i03)
		    	     (fi i10, fi i11, fi i12, fi i13)
		    	     (fi i20, fi i21, fi i22, fi i23)
		    	     (fi i30, fi i31, fi i32, fi i33))
	      fi = (fromIntegral :: Octet -> Word32)		     
	      fo = (fromIntegral :: Word32 -> Octet)		     
	      (kt0:kts) = reverse (genAddRoundKey (generateKeys nr nk key))
	      transform = foldr (.) kt0 (reverse rest)
	      ssm = replicate (nr - 1) 
	      			(subBytesRev . shiftRowsRev . mixColumnsRev)
	      rest = zipWith (.) kts ([subBytesRev . shiftRowsRev] ++ ssm)
	      


data State =  State !(Word32, Word32, Word32, Word32)
		    !(Word32, Word32, Word32, Word32)
		    !(Word32, Word32, Word32, Word32)
		    !(Word32, Word32, Word32, Word32)

sbox :: Word32 -> Word32
sboxRev :: Word32 -> Word32

sbox 0x00 = 0x63
sbox 0x01 = 0x7C
sbox 0x02 = 0x77
sbox 0x03 = 0x7B
sbox 0x04 = 0xF2
sbox 0x05 = 0x6B
sbox 0x06 = 0x6F
sbox 0x07 = 0xC5

sbox 0x08 = 0x30
sbox 0x09 = 0x01
sbox 0x0a = 0x67
sbox 0x0b = 0x2B
sbox 0x0c = 0xFE
sbox 0x0d = 0xD7
sbox 0x0e = 0xAB
sbox 0x0f = 0x76

sbox 0x10 = 0xCA
sbox 0x11 = 0x82
sbox 0x12 = 0xC9
sbox 0x13 = 0x7D
sbox 0x14 = 0xFA
sbox 0x15 = 0x59
sbox 0x16 = 0x47
sbox 0x17 = 0xF0

sbox 0x18 = 0xAD
sbox 0x19 = 0xD4
sbox 0x1a = 0xA2
sbox 0x1b = 0xAF
sbox 0x1c = 0x9C
sbox 0x1d = 0xA4
sbox 0x1e = 0x72
sbox 0x1f = 0xC0

sbox 0x20 = 0xB7
sbox 0x21 = 0xFD
sbox 0x22 = 0x93
sbox 0x23 = 0x26
sbox 0x24 = 0x36
sbox 0x25 = 0x3F
sbox 0x26 = 0xF7
sbox 0x27 = 0xCC

sbox 0x28 = 0x34
sbox 0x29 = 0xA5
sbox 0x2a = 0xE5
sbox 0x2b = 0xF1
sbox 0x2c = 0x71
sbox 0x2d = 0xD8
sbox 0x2e = 0x31
sbox 0x2f = 0x15

sbox 0x30 = 0x04
sbox 0x31 = 0xC7
sbox 0x32 = 0x23
sbox 0x33 = 0xC3
sbox 0x34 = 0x18
sbox 0x35 = 0x96
sbox 0x36 = 0x05
sbox 0x37 = 0x9A

sbox 0x38 = 0x07
sbox 0x39 = 0x12
sbox 0x3a = 0x80
sbox 0x3b = 0xE2
sbox 0x3c = 0xEB
sbox 0x3d = 0x27
sbox 0x3e = 0xB2
sbox 0x3f = 0x75

sbox 0x40 = 0x09
sbox 0x41 = 0x83
sbox 0x42 = 0x2C
sbox 0x43 = 0x1A
sbox 0x44 = 0x1B
sbox 0x45 = 0x6E
sbox 0x46 = 0x5A
sbox 0x47 = 0xA0

sbox 0x48 = 0x52
sbox 0x49 = 0x3B
sbox 0x4a = 0xD6
sbox 0x4b = 0xB3
sbox 0x4c = 0x29
sbox 0x4d = 0xE3
sbox 0x4e = 0x2F
sbox 0x4f = 0x84

sbox 0x50 = 0x53
sbox 0x51 = 0xD1
sbox 0x52 = 0x00
sbox 0x53 = 0xED
sbox 0x54 = 0x20
sbox 0x55 = 0xFC
sbox 0x56 = 0xB1
sbox 0x57 = 0x5B

sbox 0x58 = 0x6A
sbox 0x59 = 0xCB
sbox 0x5a = 0xBE
sbox 0x5b = 0x39
sbox 0x5c = 0x4A
sbox 0x5d = 0x4C
sbox 0x5e = 0x58
sbox 0x5f = 0xCF

sbox 0x60 = 0xD0
sbox 0x61 = 0xEF
sbox 0x62 = 0xAA
sbox 0x63 = 0xFB
sbox 0x64 = 0x43
sbox 0x65 = 0x4D
sbox 0x66 = 0x33
sbox 0x67 = 0x85

sbox 0x68 = 0x45
sbox 0x69 = 0xF9
sbox 0x6a = 0x02
sbox 0x6b = 0x7F
sbox 0x6c = 0x50
sbox 0x6d = 0x3C
sbox 0x6e = 0x9F
sbox 0x6f = 0xA8

sbox 0x70 = 0x51
sbox 0x71 = 0xA3
sbox 0x72 = 0x40
sbox 0x73 = 0x8F
sbox 0x74 = 0x92
sbox 0x75 = 0x9D
sbox 0x76 = 0x38
sbox 0x77 = 0xF5

sbox 0x78 = 0xBC
sbox 0x79 = 0xB6
sbox 0x7a = 0xDA
sbox 0x7b = 0x21
sbox 0x7c = 0x10
sbox 0x7d = 0xFF
sbox 0x7e = 0xF3
sbox 0x7f = 0xD2

sbox 0x80 = 0xCD
sbox 0x81 = 0x0C
sbox 0x82 = 0x13
sbox 0x83 = 0xEC
sbox 0x84 = 0x5F
sbox 0x85 = 0x97
sbox 0x86 = 0x44
sbox 0x87 = 0x17

sbox 0x88 = 0xC4
sbox 0x89 = 0xA7
sbox 0x8a = 0x7E
sbox 0x8b = 0x3D
sbox 0x8c = 0x64
sbox 0x8d = 0x5D
sbox 0x8e = 0x19
sbox 0x8f = 0x73

sbox 0x90 = 0x60
sbox 0x91 = 0x81
sbox 0x92 = 0x4F
sbox 0x93 = 0xDC
sbox 0x94 = 0x22
sbox 0x95 = 0x2A
sbox 0x96 = 0x90
sbox 0x97 = 0x88

sbox 0x98 = 0x46
sbox 0x99 = 0xEE
sbox 0x9a = 0xB8
sbox 0x9b = 0x14
sbox 0x9c = 0xDE
sbox 0x9d = 0x5E
sbox 0x9e = 0x0B
sbox 0x9f = 0xDB

sbox 0xa0 = 0xE0
sbox 0xa1 = 0x32
sbox 0xa2 = 0x3A
sbox 0xa3 = 0x0A
sbox 0xa4 = 0x49
sbox 0xa5 = 0x06
sbox 0xa6 = 0x24
sbox 0xa7 = 0x5C

sbox 0xa8 = 0xC2
sbox 0xa9 = 0xD3
sbox 0xaa = 0xAC
sbox 0xab = 0x62
sbox 0xac = 0x91
sbox 0xad = 0x95
sbox 0xae = 0xE4
sbox 0xaf = 0x79

sbox 0xb0 = 0xE7
sbox 0xb1 = 0xC8
sbox 0xb2 = 0x37
sbox 0xb3 = 0x6D
sbox 0xb4 = 0x8D
sbox 0xb5 = 0xD5
sbox 0xb6 = 0x4E
sbox 0xb7 = 0xA9

sbox 0xb8 = 0x6C
sbox 0xb9 = 0x56
sbox 0xba = 0xF4
sbox 0xbb = 0xEA
sbox 0xbc = 0x65
sbox 0xbd = 0x7A
sbox 0xbe = 0xAE
sbox 0xbf = 0x08

sbox 0xc0 = 0xBA
sbox 0xc1 = 0x78
sbox 0xc2 = 0x25
sbox 0xc3 = 0x2E
sbox 0xc4 = 0x1C
sbox 0xc5 = 0xA6
sbox 0xc6 = 0xB4
sbox 0xc7 = 0xC6

sbox 0xc8 = 0xE8
sbox 0xc9 = 0xDD
sbox 0xca = 0x74
sbox 0xcb = 0x1F
sbox 0xcc = 0x4B
sbox 0xcd = 0xBD
sbox 0xce = 0x8B
sbox 0xcf = 0x8A

sbox 0xd0 = 0x70
sbox 0xd1 = 0x3E
sbox 0xd2 = 0xB5
sbox 0xd3 = 0x66
sbox 0xd4 = 0x48
sbox 0xd5 = 0x03
sbox 0xd6 = 0xF6
sbox 0xd7 = 0x0E

sbox 0xd8 = 0x61
sbox 0xd9 = 0x35
sbox 0xda = 0x57
sbox 0xdb = 0xB9
sbox 0xdc = 0x86
sbox 0xdd = 0xC1
sbox 0xde = 0x1D
sbox 0xdf = 0x9E

sbox 0xe0 = 0xE1
sbox 0xe1 = 0xF8
sbox 0xe2 = 0x98
sbox 0xe3 = 0x11
sbox 0xe4 = 0x69
sbox 0xe5 = 0xD9
sbox 0xe6 = 0x8E
sbox 0xe7 = 0x94

sbox 0xe8 = 0x9B
sbox 0xe9 = 0x1E
sbox 0xea = 0x87
sbox 0xeb = 0xE9
sbox 0xec = 0xCE
sbox 0xed = 0x55
sbox 0xee = 0x28
sbox 0xef = 0xDF

sbox 0xf0 = 0x8C
sbox 0xf1 = 0xA1
sbox 0xf2 = 0x89
sbox 0xf3 = 0x0D
sbox 0xf4 = 0xBF
sbox 0xf5 = 0xE6
sbox 0xf6 = 0x42
sbox 0xf7 = 0x68

sbox 0xf8 = 0x41
sbox 0xf9 = 0x99
sbox 0xfa = 0x2D
sbox 0xfb = 0x0F
sbox 0xfc = 0xB0
sbox 0xfd = 0x54
sbox 0xfe = 0xBB
sbox 0xff = 0x16

{----}

sboxRev 0x63 = 0x00
sboxRev 0x7C = 0x01
sboxRev 0x77 = 0x02
sboxRev 0x7B = 0x03
sboxRev 0xF2 = 0x04
sboxRev 0x6B = 0x05
sboxRev 0x6F = 0x06
sboxRev 0xC5 = 0x07

sboxRev 0x30 = 0x08
sboxRev 0x01 = 0x09
sboxRev 0x67 = 0x0a
sboxRev 0x2B = 0x0b
sboxRev 0xFE = 0x0c
sboxRev 0xD7 = 0x0d
sboxRev 0xAB = 0x0e
sboxRev 0x76 = 0x0f

sboxRev 0xCA = 0x10
sboxRev 0x82 = 0x11
sboxRev 0xC9 = 0x12
sboxRev 0x7D = 0x13
sboxRev 0xFA = 0x14
sboxRev 0x59 = 0x15
sboxRev 0x47 = 0x16
sboxRev 0xF0 = 0x17

sboxRev 0xAD = 0x18
sboxRev 0xD4 = 0x19
sboxRev 0xA2 = 0x1a
sboxRev 0xAF = 0x1b
sboxRev 0x9C = 0x1c
sboxRev 0xA4 = 0x1d
sboxRev 0x72 = 0x1e
sboxRev 0xC0 = 0x1f

sboxRev 0xB7 = 0x20
sboxRev 0xFD = 0x21
sboxRev 0x93 = 0x22
sboxRev 0x26 = 0x23
sboxRev 0x36 = 0x24
sboxRev 0x3F = 0x25
sboxRev 0xF7 = 0x26
sboxRev 0xCC = 0x27

sboxRev 0x34 = 0x28
sboxRev 0xA5 = 0x29
sboxRev 0xE5 = 0x2a
sboxRev 0xF1 = 0x2b
sboxRev 0x71 = 0x2c
sboxRev 0xD8 = 0x2d
sboxRev 0x31 = 0x2e
sboxRev 0x15 = 0x2f

sboxRev 0x04 = 0x30
sboxRev 0xC7 = 0x31
sboxRev 0x23 = 0x32
sboxRev 0xC3 = 0x33
sboxRev 0x18 = 0x34
sboxRev 0x96 = 0x35
sboxRev 0x05 = 0x36
sboxRev 0x9A = 0x37

sboxRev 0x07 = 0x38
sboxRev 0x12 = 0x39
sboxRev 0x80 = 0x3a
sboxRev 0xE2 = 0x3b
sboxRev 0xEB = 0x3c
sboxRev 0x27 = 0x3d
sboxRev 0xB2 = 0x3e
sboxRev 0x75 = 0x3f

sboxRev 0x09 = 0x40
sboxRev 0x83 = 0x41
sboxRev 0x2C = 0x42
sboxRev 0x1A = 0x43
sboxRev 0x1B = 0x44
sboxRev 0x6E = 0x45
sboxRev 0x5A = 0x46
sboxRev 0xA0 = 0x47

sboxRev 0x52 = 0x48
sboxRev 0x3B = 0x49
sboxRev 0xD6 = 0x4a
sboxRev 0xB3 = 0x4b
sboxRev 0x29 = 0x4c
sboxRev 0xE3 = 0x4d
sboxRev 0x2F = 0x4e
sboxRev 0x84 = 0x4f

sboxRev 0x53 = 0x50
sboxRev 0xD1 = 0x51
sboxRev 0x00 = 0x52
sboxRev 0xED = 0x53
sboxRev 0x20 = 0x54
sboxRev 0xFC = 0x55
sboxRev 0xB1 = 0x56
sboxRev 0x5B = 0x57

sboxRev 0x6A = 0x58
sboxRev 0xCB = 0x59
sboxRev 0xBE = 0x5a
sboxRev 0x39 = 0x5b
sboxRev 0x4A = 0x5c
sboxRev 0x4C = 0x5d
sboxRev 0x58 = 0x5e
sboxRev 0xCF = 0x5f

sboxRev 0xD0 = 0x60
sboxRev 0xEF = 0x61
sboxRev 0xAA = 0x62
sboxRev 0xFB = 0x63
sboxRev 0x43 = 0x64
sboxRev 0x4D = 0x65
sboxRev 0x33 = 0x66
sboxRev 0x85 = 0x67

sboxRev 0x45 = 0x68
sboxRev 0xF9 = 0x69
sboxRev 0x02 = 0x6a
sboxRev 0x7F = 0x6b
sboxRev 0x50 = 0x6c
sboxRev 0x3C = 0x6d
sboxRev 0x9F = 0x6e
sboxRev 0xA8 = 0x6f

sboxRev 0x51 = 0x70
sboxRev 0xA3 = 0x71
sboxRev 0x40 = 0x72
sboxRev 0x8F = 0x73
sboxRev 0x92 = 0x74
sboxRev 0x9D = 0x75
sboxRev 0x38 = 0x76
sboxRev 0xF5 = 0x77

sboxRev 0xBC = 0x78
sboxRev 0xB6 = 0x79
sboxRev 0xDA = 0x7a
sboxRev 0x21 = 0x7b
sboxRev 0x10 = 0x7c
sboxRev 0xFF = 0x7d
sboxRev 0xF3 = 0x7e
sboxRev 0xD2 = 0x7f

sboxRev 0xCD = 0x80
sboxRev 0x0C = 0x81
sboxRev 0x13 = 0x82
sboxRev 0xEC = 0x83
sboxRev 0x5F = 0x84
sboxRev 0x97 = 0x85
sboxRev 0x44 = 0x86
sboxRev 0x17 = 0x87

sboxRev 0xC4 = 0x88
sboxRev 0xA7 = 0x89
sboxRev 0x7E = 0x8a
sboxRev 0x3D = 0x8b
sboxRev 0x64 = 0x8c
sboxRev 0x5D = 0x8d
sboxRev 0x19 = 0x8e
sboxRev 0x73 = 0x8f

sboxRev 0x60 = 0x90
sboxRev 0x81 = 0x91
sboxRev 0x4F = 0x92
sboxRev 0xDC = 0x93
sboxRev 0x22 = 0x94
sboxRev 0x2A = 0x95
sboxRev 0x90 = 0x96
sboxRev 0x88 = 0x97

sboxRev 0x46 = 0x98
sboxRev 0xEE = 0x99
sboxRev 0xB8 = 0x9a
sboxRev 0x14 = 0x9b
sboxRev 0xDE = 0x9c
sboxRev 0x5E = 0x9d
sboxRev 0x0B = 0x9e
sboxRev 0xDB = 0x9f

sboxRev 0xE0 = 0xa0
sboxRev 0x32 = 0xa1
sboxRev 0x3A = 0xa2
sboxRev 0x0A = 0xa3
sboxRev 0x49 = 0xa4
sboxRev 0x06 = 0xa5
sboxRev 0x24 = 0xa6
sboxRev 0x5C = 0xa7

sboxRev 0xC2 = 0xa8
sboxRev 0xD3 = 0xa9
sboxRev 0xAC = 0xaa
sboxRev 0x62 = 0xab
sboxRev 0x91 = 0xac
sboxRev 0x95 = 0xad
sboxRev 0xE4 = 0xae
sboxRev 0x79 = 0xaf

sboxRev 0xE7 = 0xb0
sboxRev 0xC8 = 0xb1
sboxRev 0x37 = 0xb2
sboxRev 0x6D = 0xb3
sboxRev 0x8D = 0xb4
sboxRev 0xD5 = 0xb5
sboxRev 0x4E = 0xb6
sboxRev 0xA9 = 0xb7

sboxRev 0x6C = 0xb8
sboxRev 0x56 = 0xb9
sboxRev 0xF4 = 0xba
sboxRev 0xEA = 0xbb
sboxRev 0x65 = 0xbc
sboxRev 0x7A = 0xbd
sboxRev 0xAE = 0xbe
sboxRev 0x08 = 0xbf

sboxRev 0xBA = 0xc0
sboxRev 0x78 = 0xc1
sboxRev 0x25 = 0xc2
sboxRev 0x2E = 0xc3
sboxRev 0x1C = 0xc4
sboxRev 0xA6 = 0xc5
sboxRev 0xB4 = 0xc6
sboxRev 0xC6 = 0xc7

sboxRev 0xE8 = 0xc8
sboxRev 0xDD = 0xc9
sboxRev 0x74 = 0xca
sboxRev 0x1F = 0xcb
sboxRev 0x4B = 0xcc
sboxRev 0xBD = 0xcd
sboxRev 0x8B = 0xce
sboxRev 0x8A = 0xcf

sboxRev 0x70 = 0xd0
sboxRev 0x3E = 0xd1
sboxRev 0xB5 = 0xd2
sboxRev 0x66 = 0xd3
sboxRev 0x48 = 0xd4
sboxRev 0x03 = 0xd5
sboxRev 0xF6 = 0xd6
sboxRev 0x0E = 0xd7

sboxRev 0x61 = 0xd8
sboxRev 0x35 = 0xd9
sboxRev 0x57 = 0xda
sboxRev 0xB9 = 0xdb
sboxRev 0x86 = 0xdc
sboxRev 0xC1 = 0xdd
sboxRev 0x1D = 0xde
sboxRev 0x9E = 0xdf

sboxRev 0xE1 = 0xe0
sboxRev 0xF8 = 0xe1
sboxRev 0x98 = 0xe2
sboxRev 0x11 = 0xe3
sboxRev 0x69 = 0xe4
sboxRev 0xD9 = 0xe5
sboxRev 0x8E = 0xe6
sboxRev 0x94 = 0xe7

sboxRev 0x9B = 0xe8
sboxRev 0x1E = 0xe9
sboxRev 0x87 = 0xea
sboxRev 0xE9 = 0xeb
sboxRev 0xCE = 0xec
sboxRev 0x55 = 0xed
sboxRev 0x28 = 0xee
sboxRev 0xDF = 0xef

sboxRev 0x8C = 0xf0
sboxRev 0xA1 = 0xf1
sboxRev 0x89 = 0xf2
sboxRev 0x0D = 0xf3
sboxRev 0xBF = 0xf4
sboxRev 0xE6 = 0xf5
sboxRev 0x42 = 0xf6
sboxRev 0x68 = 0xf7

sboxRev 0x41 = 0xf8
sboxRev 0x99 = 0xf9
sboxRev 0x2D = 0xfa
sboxRev 0x0F = 0xfb
sboxRev 0xB0 = 0xfc
sboxRev 0x54 = 0xfd
sboxRev 0xBB = 0xfe
sboxRev 0x16 = 0xff

xtime :: Word32 -> Word32
xtime x = b
	where	a = x `shiftL` 1
		b = if a .&. (0x0100) == 0 then a else a `xor` 0x11b

xtimeX2 :: Word32 -> Word32
--xtimeX2 = xtime . xtime
xtimeX2 x = c
	where	a = x `shiftL` 2
		b = if a .&. (0x0200) == 0 then a else a `xor` 0x236
		c = if b .&. (0x0100) == 0 then b else b `xor` 0x11b

xtimeX3 :: Word32 -> Word32
--xtimeX3 = xtime . xtime . xtime
xtimeX3 x = d
	where	a = x `shiftL` 3
		b = if a .&. (0x0400) == 0 then a else a `xor` 0x46c
		c = if b .&. (0x0200) == 0 then b else b `xor` 0x236
		d = if c .&. (0x0100) == 0 then c else c `xor` 0x11b

xtime03 :: Word32 -> Word32
xtime03 x = x `xor` (xtime x)

xtime0e :: Word32 -> Word32 
xtime0e x = xtime (x `xor` (xtime (x `xor` (xtime x))))

xtime09 :: Word32 -> Word32 
xtime09 x = x `xor` (xtimeX3 x)

xtime0d :: Word32 -> Word32 
xtime0d x = x `xor` (xtimeX2 (x `xor` (xtime x)))

xtime0b :: Word32 -> Word32 
xtime0b x = x `xor` (xtime (x `xor` (xtimeX2 x)))

generateKey :: Int -> Int -> Word32 -> Word32 -> Word32
generateKey nk i wIminus1 wIminusNk = 
		(temp' `xor` wIminusNk)
	where temp' = 
		if (i `mod` nk) == 0 then (subword(rotword temp)) `xor` rcon
		else if (nk > 6) && ((i `mod` nk) == 4) then subword temp
		else temp
	      temp = wIminus1	
	      subword :: Word32 -> Word32
	      subword w = (a `shiftL` 24) .|. (b `shiftL` 16) .|.
	      		  (c `shiftL` 8) .|. d
			  where a = sbox ((w `shiftR` 24) .&. 0xff)
			        b = sbox ((w `shiftR` 16) .&. 0xff)
			        c = sbox ((w `shiftR`  8) .&. 0xff)
			        d = sbox ( w             .&. 0xff)
	      rotword :: Word32 -> Word32
	      rotword w = w `rotateL` 8 			
	      rcon :: Word32
	      rcon = ((fromIntegral rconMSB)::Word32) `shiftL` 24
	      rconMSB = (iterate xtime 0x01) !! ((i `div` nk) - 1)
	
wordify :: [Octet] -> [Word32]
wordify [] = []
wordify octets = firstWord:otherWords
	where
		(firstWord, otherOctets) = getWord32 octets
		otherWords = wordify otherOctets

generateKeys :: Int -> Int -> [Octet] -> [Word32]
generateKeys nr nk mainKey = 
		-- assert ((nk * 4) == length mainKey) $
		(take (4 * (nr + 1)) xs)
	where   
		xs = (wordify mainKey) ++ (zipWith3 (generateKey nk)
						(drop nk [0,1..])
						(drop (nk - 1) xs)
						xs
					)

subBytes :: State -> State
subBytes (State (s00, s01, s02, s03)
		(s10, s11, s12, s13)
	 	(s20, s21, s22, s23)
	 	(s30, s31, s32, s33)) = 
	  State (sbox s00, sbox s01, sbox s02, sbox s03)
 		(sbox s10, sbox s11, sbox s12, sbox s13)
		(sbox s20, sbox s21, sbox s22, sbox s23)
		(sbox s30, sbox s31, sbox s32, sbox s33)

subBytesRev :: State -> State
subBytesRev (State (s00, s01, s02, s03)
		   (s10, s11, s12, s13)
	 	   (s20, s21, s22, s23)
	 	   (s30, s31, s32, s33)) = 
	  State (sboxRev s00, sboxRev s01, sboxRev s02, sboxRev s03)
  		(sboxRev s10, sboxRev s11, sboxRev s12, sboxRev s13)
  		(sboxRev s20, sboxRev s21, sboxRev s22, sboxRev s23)
  		(sboxRev s30, sboxRev s31, sboxRev s32, sboxRev s33)

shiftRows :: State -> State		
shiftRows (State (s00, s01, s02, s03)
		 (s10, s11, s12, s13)
	 	 (s20, s21, s22, s23)
	 	 (s30, s31, s32, s33)) = 
	  State (s00, s01, s02, s03)
 		(s11, s12, s13, s10)
		(s22, s23, s20, s21)
		(s33, s30, s31, s32)

shiftRowsRev :: State -> State		
shiftRowsRev (State (s00, s01, s02, s03)
		    (s10, s11, s12, s13)
	 	    (s20, s21, s22, s23)
	 	    (s30, s31, s32, s33)) = 
	  State (s00, s01, s02, s03)
 		(s13, s10, s11, s12)
		(s22, s23, s20, s21)
		(s31, s32, s33, s30)

mixColumn:: (Word32, Word32, Word32, Word32) -> (Word32, Word32, Word32, Word32)
mixColumn (s0,s1,s2,s3) = 
	((xtime   s0) `xor` (xtime03 s1) `xor`          s2  `xor`          s3 ,
	          s0  `xor` (xtime   s1) `xor` (xtime03 s2) `xor`          s3 ,
	          s0  `xor`          s1  `xor` (xtime   s2) `xor` (xtime03 s3),
	 (xtime03 s0) `xor`          s1  `xor`          s2  `xor` (xtime   s3))

mixColumns :: State -> State		
mixColumns (State (s00, s01, s02, s03)
		  (s10, s11, s12, s13)
	 	  (s20, s21, s22, s23)
	 	  (s30, s31, s32, s33)) = 
	  State (r00, r01, r02, r03)
 		(r10, r11, r12, r13)
		(r20, r21, r22, r23)
		(r30, r31, r32, r33)
	where (r00, r10, r20, r30) = mixColumn (s00, s10, s20, s30)
	      (r01, r11, r21, r31) = mixColumn (s01, s11, s21, s31)
	      (r02, r12, r22, r32) = mixColumn (s02, s12, s22, s32)
	      (r03, r13, r23, r33) = mixColumn (s03, s13, s23, s33)

mixColumnRev :: (Word32, Word32, Word32, Word32) 
		-> (Word32, Word32, Word32, Word32)
mixColumnRev (s0,s1,s2,s3) = 
	((xtime0e s0) `xor` (xtime0b s1) `xor` (xtime0d s2) `xor` (xtime09 s3),
	 (xtime09 s0) `xor` (xtime0e s1) `xor` (xtime0b s2) `xor` (xtime0d s3),
	 (xtime0d s0) `xor` (xtime09 s1) `xor` (xtime0e s2) `xor` (xtime0b s3),
	 (xtime0b s0) `xor` (xtime0d s1) `xor` (xtime09 s2) `xor` (xtime0e s3))

mixColumnsRev :: State -> State		
mixColumnsRev (State (s00, s01, s02, s03)
		  (s10, s11, s12, s13)
	 	  (s20, s21, s22, s23)
	 	  (s30, s31, s32, s33)) = 
	  State (r00, r01, r02, r03)
 		(r10, r11, r12, r13)
		(r20, r21, r22, r23)
		(r30, r31, r32, r33)
	where (r00, r10, r20, r30) = mixColumnRev (s00, s10, s20, s30)
	      (r01, r11, r21, r31) = mixColumnRev (s01, s11, s21, s31)
	      (r02, r12, r22, r32) = mixColumnRev (s02, s12, s22, s32)
	      (r03, r13, r23, r33) = mixColumnRev (s03, s13, s23, s33)

addRoundKey :: State -> State -> State
addRoundKey (State (k00, k01, k02, k03)
		   (k10, k11, k12, k13)
		   (k20, k21, k22, k23)
	 	   (k30, k31, k32, k33))   
	    (State (s00, s01, s02, s03)
		   (s10, s11, s12, s13)
		   (s20, s21, s22, s23)
	 	   (s30, s31, s32, s33)) = 
	  State (s00 `xor` k00, s01 `xor` k01, s02 `xor` k02, s03 `xor` k03)
 		(s10 `xor` k10, s11 `xor` k11, s12 `xor` k12, s13 `xor` k13)
		(s20 `xor` k20, s21 `xor` k21, s22 `xor` k22, s23 `xor` k23)
		(s30 `xor` k30, s31 `xor` k31, s32 `xor` k32, s33 `xor` k33)

genAddRoundKey :: [Word32] -> [State -> State]
genAddRoundKey [] = []
genAddRoundKey (a:b:c:d:ks) = (addRoundKey k):(genAddRoundKey ks)
	where k = State (fromIntegral s00, fromIntegral s01,
			 fromIntegral s02, fromIntegral s03)
			(fromIntegral s10, fromIntegral s11,
			 fromIntegral s12, fromIntegral s13)
			(fromIntegral s20, fromIntegral s21,
			 fromIntegral s22, fromIntegral s23)
			(fromIntegral s30, fromIntegral s31,
			 fromIntegral s32, fromIntegral s33) 
	      [s00, s10, s20, s30] = putWord32 a 		
	      [s01, s11, s21, s31] = putWord32 b 		
	      [s02, s12, s22, s32] = putWord32 c 		
	      [s03, s13, s23, s33] = putWord32 d 		

getWord32 :: [Octet] -> (Word32, [Octet])
getWord32 (a:b:c:d:xs) = (x, xs)
	where 
		x = ((fromIntegral a) `shiftL` 24) .|. 
		    ((fromIntegral b) `shiftL` 16) .|. 
		    ((fromIntegral c) `shiftL`  8) .|. 
		    ((fromIntegral d)            ) 

putWord32 :: Word32 -> [Octet]
--a bit slower putWord32 x = map fromIntegral [a,b,c,d]
putWord32 x = [fromIntegral a, fromIntegral b, fromIntegral c, fromIntegral d]
	where
		a = (x `shiftR` 24) 
		b = (x `shiftR` 16) .&. 255
		c = (x `shiftR`  8) .&. 255
		d = (x            ) .&. 255

{-
testGenerateKeys128 :: Test
testGenerateKeys128 = 
	let key = [0x2b, 0x7e, 0x15, 0x16,
		   0x28, 0xae, 0xd2, 0xa6,
		   0xab, 0xf7, 0x15, 0x88,
		   0x09, 0xcf, 0x4f, 0x3c]
	    expected = [0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c,
	    		0xa0fafe17, 0x88542cb1, 0x23a33939, 0x2a6c7605,
			0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f,
			0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b,
			0xef44a541, 0xa8525b7f, 0xb671253b, 0xdb0bad00,
			0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc,
			0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd,
			0x4e54f70e, 0x5f5fc9f3, 0x84a64fb2, 0x4ea6dc4f,
			0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f,
			0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e,
			0xd014f9a8, 0xc9ee2589, 0xe13f0cc8, 0xb6630ca6
			]
	in TestCase (do
		assertEqual "" expected (generateKeys 10 4 key)
	)


testGenerateKeys192 :: Test
testGenerateKeys192 = 
	let key = [0x8e, 0x73, 0xb0, 0xf7,
		   0xda, 0x0e, 0x64, 0x52,
		   0xc8, 0x10, 0xf3, 0x2b,
		   0x80, 0x90, 0x79, 0xe5,
		   0x62, 0xf8, 0xea, 0xd2,
		   0x52, 0x2c, 0x6b, 0x7b]
	    expected = [0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5,
	    		0x62f8ead2, 0x522c6b7b, 0xfe0c91f7, 0x2402f5a5,
			0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2,
			0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd,
			0xe75fad44, 0xbb095386, 0x485af057, 0x21efb14f
			]
	in TestCase (do
		assertEqual "" expected
			(take (length expected) (generateKeys 12 6 key))
	)

testGenerateKeys256 :: Test
testGenerateKeys256 = 
	let key = [0x60, 0x3d, 0xeb, 0x10,
		   0x15, 0xca, 0x71, 0xbe,
		   0x2b, 0x73, 0xae, 0xf0,
		   0x85, 0x7d, 0x77, 0x81,
		   0x1f, 0x35, 0x2c, 0x07,
		   0x3b, 0x61, 0x08, 0xd7,
		   0x2d, 0x98, 0x10, 0xa3,
		   0x09, 0x14, 0xdf, 0xf4]
	    expected = [0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781,
	    		0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4,
			0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde,
			0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a,
			0xd59aecb8, 0x5bf3c917, 0xfee94248, 0xde8ebe96
			]
	in TestCase (do
		assertEqual "" expected 
			(take (length expected) (generateKeys 14 8 key))
	)

testAes128 :: Test
testAes128 = 
	let key = [0x2b, 0x7e, 0x15, 0x16,
		   0x28, 0xae, 0xd2, 0xa6,
		   0xab, 0xf7, 0x15, 0x88,
		   0x09, 0xcf, 0x4f, 0x3c]
	    input = [0x32, 0x43, 0xf6, 0xa8, 
	    	     0x88, 0x5a, 0x30, 0x8d,
		     0x31, 0x31, 0x98, 0xa2,
		     0xe0, 0x37, 0x07, 0x34]
	    output = [0x39, 0x25, 0x84, 0x1d,
	    	      0x02, 0xdc, 0x09, 0xfb,
		      0xdc, 0x11, 0x85, 0x97,
		      0x19, 0x6a, 0x0b, 0x32]
	in TestCase (do
		assertEqual "encrypt test" output (aes128Encrypt key input)
		assertEqual "encrypt/decrypt test" input 
				(aes128Decrypt key (aes128Encrypt key input))
	)

testAesRandom :: Test
testAesRandom = 
	TestCase (do
		key128 <- getRandomOctets 16 
		key192 <- getRandomOctets 24 
		key256 <- getRandomOctets 32 
		msg <- getRandomOctets 16 
		assertEqual "aes128" msg 
			(aes128Decrypt key128 (aes128Encrypt key128 msg))
		assertEqual "aes192" msg 
			(aes192Decrypt key192 (aes192Encrypt key192 msg))
		assertEqual "aes256" msg 
			(aes256Decrypt key256 (aes256Encrypt key256 msg))
	)

-- | HUnit tests
tests :: Test
tests = TestList [
		TestLabel "testGenerateKeys128" testGenerateKeys128,
		TestLabel "testGenerateKeys192" testGenerateKeys192,
		TestLabel "testGenerateKeys256" testGenerateKeys256,
		TestLabel "testAes128" testAes128,
		TestLabel "testAesRandom" testAesRandom
	]
-}