(********************************************************************)
(*                                                                  *)
(*  aes.s7i       AES (Advanced Encryption Standard) cipher support.*)
(*  Copyright (C) 2015, 2017, 2020, 2021, 2023  Thomas Mertes       *)
(*                                                                  *)
(*  This file is part of the Seed7 Runtime Library.                 *)
(*                                                                  *)
(*  The Seed7 Runtime Library is free software; you can             *)
(*  redistribute it and/or modify it under the terms of the GNU     *)
(*  Lesser General Public License as published by the Free Software *)
(*  Foundation; either version 2.1 of the License, or (at your      *)
(*  option) any later version.                                      *)
(*                                                                  *)
(*  The Seed7 Runtime Library is distributed in the hope that it    *)
(*  will be useful, but WITHOUT ANY WARRANTY; without even the      *)
(*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *)
(*  PURPOSE.  See the GNU Lesser General Public License for more    *)
(*  details.                                                        *)
(*                                                                  *)
(*  You should have received a copy of the GNU Lesser General       *)
(*  Public License along with this program; if not, write to the    *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


include "bin32.s7i";
include "bytedata.s7i";
include "cipher.s7i";


(**
 *  [[cipher|cipherState]] implementation type describing the state of an AES cipher.
 *  The data is encrypted / decrypted with the AES (Advanced encryption
 *  standard) block cipher.
 *)
const type: aesState is sub noCipherState struct
    var array bin32: encryptionSubKey is 0 times bin32.value;
    var array bin32: decryptionSubKey is 0 times bin32.value;
    var integer: rounds is 0;
    var string: cipherBlock is "";
  end struct;


type_implements_interface(aesState, cipherState);


(**
 *  Block size used by the AES (Advanced Encryption Standard) block cipher.
 *  @return the block size used by the AES cipher.
 *)
const func integer: blockSize (AES) is 16;


const array array bin32: Te is [] (
  # Te[1]:
  [0] (bin32(16#c66363a5), bin32(16#f87c7c84), bin32(16#ee777799), bin32(16#f67b7b8d),
       bin32(16#fff2f20d), bin32(16#d66b6bbd), bin32(16#de6f6fb1), bin32(16#91c5c554),
       bin32(16#60303050), bin32(16#02010103), bin32(16#ce6767a9), bin32(16#562b2b7d),
       bin32(16#e7fefe19), bin32(16#b5d7d762), bin32(16#4dababe6), bin32(16#ec76769a),
       bin32(16#8fcaca45), bin32(16#1f82829d), bin32(16#89c9c940), bin32(16#fa7d7d87),
       bin32(16#effafa15), bin32(16#b25959eb), bin32(16#8e4747c9), bin32(16#fbf0f00b),
       bin32(16#41adadec), bin32(16#b3d4d467), bin32(16#5fa2a2fd), bin32(16#45afafea),
       bin32(16#239c9cbf), bin32(16#53a4a4f7), bin32(16#e4727296), bin32(16#9bc0c05b),
       bin32(16#75b7b7c2), bin32(16#e1fdfd1c), bin32(16#3d9393ae), bin32(16#4c26266a),
       bin32(16#6c36365a), bin32(16#7e3f3f41), bin32(16#f5f7f702), bin32(16#83cccc4f),
       bin32(16#6834345c), bin32(16#51a5a5f4), bin32(16#d1e5e534), bin32(16#f9f1f108),
       bin32(16#e2717193), bin32(16#abd8d873), bin32(16#62313153), bin32(16#2a15153f),
       bin32(16#0804040c), bin32(16#95c7c752), bin32(16#46232365), bin32(16#9dc3c35e),
       bin32(16#30181828), bin32(16#379696a1), bin32(16#0a05050f), bin32(16#2f9a9ab5),
       bin32(16#0e070709), bin32(16#24121236), bin32(16#1b80809b), bin32(16#dfe2e23d),
       bin32(16#cdebeb26), bin32(16#4e272769), bin32(16#7fb2b2cd), bin32(16#ea75759f),
       bin32(16#1209091b), bin32(16#1d83839e), bin32(16#582c2c74), bin32(16#341a1a2e),
       bin32(16#361b1b2d), bin32(16#dc6e6eb2), bin32(16#b45a5aee), bin32(16#5ba0a0fb),
       bin32(16#a45252f6), bin32(16#763b3b4d), bin32(16#b7d6d661), bin32(16#7db3b3ce),
       bin32(16#5229297b), bin32(16#dde3e33e), bin32(16#5e2f2f71), bin32(16#13848497),
       bin32(16#a65353f5), bin32(16#b9d1d168), bin32(16#00000000), bin32(16#c1eded2c),
       bin32(16#40202060), bin32(16#e3fcfc1f), bin32(16#79b1b1c8), bin32(16#b65b5bed),
       bin32(16#d46a6abe), bin32(16#8dcbcb46), bin32(16#67bebed9), bin32(16#7239394b),
       bin32(16#944a4ade), bin32(16#984c4cd4), bin32(16#b05858e8), bin32(16#85cfcf4a),
       bin32(16#bbd0d06b), bin32(16#c5efef2a), bin32(16#4faaaae5), bin32(16#edfbfb16),
       bin32(16#864343c5), bin32(16#9a4d4dd7), bin32(16#66333355), bin32(16#11858594),
       bin32(16#8a4545cf), bin32(16#e9f9f910), bin32(16#04020206), bin32(16#fe7f7f81),
       bin32(16#a05050f0), bin32(16#783c3c44), bin32(16#259f9fba), bin32(16#4ba8a8e3),
       bin32(16#a25151f3), bin32(16#5da3a3fe), bin32(16#804040c0), bin32(16#058f8f8a),
       bin32(16#3f9292ad), bin32(16#219d9dbc), bin32(16#70383848), bin32(16#f1f5f504),
       bin32(16#63bcbcdf), bin32(16#77b6b6c1), bin32(16#afdada75), bin32(16#42212163),
       bin32(16#20101030), bin32(16#e5ffff1a), bin32(16#fdf3f30e), bin32(16#bfd2d26d),
       bin32(16#81cdcd4c), bin32(16#180c0c14), bin32(16#26131335), bin32(16#c3ecec2f),
       bin32(16#be5f5fe1), bin32(16#359797a2), bin32(16#884444cc), bin32(16#2e171739),
       bin32(16#93c4c457), bin32(16#55a7a7f2), bin32(16#fc7e7e82), bin32(16#7a3d3d47),
       bin32(16#c86464ac), bin32(16#ba5d5de7), bin32(16#3219192b), bin32(16#e6737395),
       bin32(16#c06060a0), bin32(16#19818198), bin32(16#9e4f4fd1), bin32(16#a3dcdc7f),
       bin32(16#44222266), bin32(16#542a2a7e), bin32(16#3b9090ab), bin32(16#0b888883),
       bin32(16#8c4646ca), bin32(16#c7eeee29), bin32(16#6bb8b8d3), bin32(16#2814143c),
       bin32(16#a7dede79), bin32(16#bc5e5ee2), bin32(16#160b0b1d), bin32(16#addbdb76),
       bin32(16#dbe0e03b), bin32(16#64323256), bin32(16#743a3a4e), bin32(16#140a0a1e),
       bin32(16#924949db), bin32(16#0c06060a), bin32(16#4824246c), bin32(16#b85c5ce4),
       bin32(16#9fc2c25d), bin32(16#bdd3d36e), bin32(16#43acacef), bin32(16#c46262a6),
       bin32(16#399191a8), bin32(16#319595a4), bin32(16#d3e4e437), bin32(16#f279798b),
       bin32(16#d5e7e732), bin32(16#8bc8c843), bin32(16#6e373759), bin32(16#da6d6db7),
       bin32(16#018d8d8c), bin32(16#b1d5d564), bin32(16#9c4e4ed2), bin32(16#49a9a9e0),
       bin32(16#d86c6cb4), bin32(16#ac5656fa), bin32(16#f3f4f407), bin32(16#cfeaea25),
       bin32(16#ca6565af), bin32(16#f47a7a8e), bin32(16#47aeaee9), bin32(16#10080818),
       bin32(16#6fbabad5), bin32(16#f0787888), bin32(16#4a25256f), bin32(16#5c2e2e72),
       bin32(16#381c1c24), bin32(16#57a6a6f1), bin32(16#73b4b4c7), bin32(16#97c6c651),
       bin32(16#cbe8e823), bin32(16#a1dddd7c), bin32(16#e874749c), bin32(16#3e1f1f21),
       bin32(16#964b4bdd), bin32(16#61bdbddc), bin32(16#0d8b8b86), bin32(16#0f8a8a85),
       bin32(16#e0707090), bin32(16#7c3e3e42), bin32(16#71b5b5c4), bin32(16#cc6666aa),
       bin32(16#904848d8), bin32(16#06030305), bin32(16#f7f6f601), bin32(16#1c0e0e12),
       bin32(16#c26161a3), bin32(16#6a35355f), bin32(16#ae5757f9), bin32(16#69b9b9d0),
       bin32(16#17868691), bin32(16#99c1c158), bin32(16#3a1d1d27), bin32(16#279e9eb9),
       bin32(16#d9e1e138), bin32(16#ebf8f813), bin32(16#2b9898b3), bin32(16#22111133),
       bin32(16#d26969bb), bin32(16#a9d9d970), bin32(16#078e8e89), bin32(16#339494a7),
       bin32(16#2d9b9bb6), bin32(16#3c1e1e22), bin32(16#15878792), bin32(16#c9e9e920),
       bin32(16#87cece49), bin32(16#aa5555ff), bin32(16#50282878), bin32(16#a5dfdf7a),
       bin32(16#038c8c8f), bin32(16#59a1a1f8), bin32(16#09898980), bin32(16#1a0d0d17),
       bin32(16#65bfbfda), bin32(16#d7e6e631), bin32(16#844242c6), bin32(16#d06868b8),
       bin32(16#824141c3), bin32(16#299999b0), bin32(16#5a2d2d77), bin32(16#1e0f0f11),
       bin32(16#7bb0b0cb), bin32(16#a85454fc), bin32(16#6dbbbbd6), bin32(16#2c16163a)),
  # Te[2]:
  [0] (bin32(16#a5c66363), bin32(16#84f87c7c), bin32(16#99ee7777), bin32(16#8df67b7b),
       bin32(16#0dfff2f2), bin32(16#bdd66b6b), bin32(16#b1de6f6f), bin32(16#5491c5c5),
       bin32(16#50603030), bin32(16#03020101), bin32(16#a9ce6767), bin32(16#7d562b2b),
       bin32(16#19e7fefe), bin32(16#62b5d7d7), bin32(16#e64dabab), bin32(16#9aec7676),
       bin32(16#458fcaca), bin32(16#9d1f8282), bin32(16#4089c9c9), bin32(16#87fa7d7d),
       bin32(16#15effafa), bin32(16#ebb25959), bin32(16#c98e4747), bin32(16#0bfbf0f0),
       bin32(16#ec41adad), bin32(16#67b3d4d4), bin32(16#fd5fa2a2), bin32(16#ea45afaf),
       bin32(16#bf239c9c), bin32(16#f753a4a4), bin32(16#96e47272), bin32(16#5b9bc0c0),
       bin32(16#c275b7b7), bin32(16#1ce1fdfd), bin32(16#ae3d9393), bin32(16#6a4c2626),
       bin32(16#5a6c3636), bin32(16#417e3f3f), bin32(16#02f5f7f7), bin32(16#4f83cccc),
       bin32(16#5c683434), bin32(16#f451a5a5), bin32(16#34d1e5e5), bin32(16#08f9f1f1),
       bin32(16#93e27171), bin32(16#73abd8d8), bin32(16#53623131), bin32(16#3f2a1515),
       bin32(16#0c080404), bin32(16#5295c7c7), bin32(16#65462323), bin32(16#5e9dc3c3),
       bin32(16#28301818), bin32(16#a1379696), bin32(16#0f0a0505), bin32(16#b52f9a9a),
       bin32(16#090e0707), bin32(16#36241212), bin32(16#9b1b8080), bin32(16#3ddfe2e2),
       bin32(16#26cdebeb), bin32(16#694e2727), bin32(16#cd7fb2b2), bin32(16#9fea7575),
       bin32(16#1b120909), bin32(16#9e1d8383), bin32(16#74582c2c), bin32(16#2e341a1a),
       bin32(16#2d361b1b), bin32(16#b2dc6e6e), bin32(16#eeb45a5a), bin32(16#fb5ba0a0),
       bin32(16#f6a45252), bin32(16#4d763b3b), bin32(16#61b7d6d6), bin32(16#ce7db3b3),
       bin32(16#7b522929), bin32(16#3edde3e3), bin32(16#715e2f2f), bin32(16#97138484),
       bin32(16#f5a65353), bin32(16#68b9d1d1), bin32(16#00000000), bin32(16#2cc1eded),
       bin32(16#60402020), bin32(16#1fe3fcfc), bin32(16#c879b1b1), bin32(16#edb65b5b),
       bin32(16#bed46a6a), bin32(16#468dcbcb), bin32(16#d967bebe), bin32(16#4b723939),
       bin32(16#de944a4a), bin32(16#d4984c4c), bin32(16#e8b05858), bin32(16#4a85cfcf),
       bin32(16#6bbbd0d0), bin32(16#2ac5efef), bin32(16#e54faaaa), bin32(16#16edfbfb),
       bin32(16#c5864343), bin32(16#d79a4d4d), bin32(16#55663333), bin32(16#94118585),
       bin32(16#cf8a4545), bin32(16#10e9f9f9), bin32(16#06040202), bin32(16#81fe7f7f),
       bin32(16#f0a05050), bin32(16#44783c3c), bin32(16#ba259f9f), bin32(16#e34ba8a8),
       bin32(16#f3a25151), bin32(16#fe5da3a3), bin32(16#c0804040), bin32(16#8a058f8f),
       bin32(16#ad3f9292), bin32(16#bc219d9d), bin32(16#48703838), bin32(16#04f1f5f5),
       bin32(16#df63bcbc), bin32(16#c177b6b6), bin32(16#75afdada), bin32(16#63422121),
       bin32(16#30201010), bin32(16#1ae5ffff), bin32(16#0efdf3f3), bin32(16#6dbfd2d2),
       bin32(16#4c81cdcd), bin32(16#14180c0c), bin32(16#35261313), bin32(16#2fc3ecec),
       bin32(16#e1be5f5f), bin32(16#a2359797), bin32(16#cc884444), bin32(16#392e1717),
       bin32(16#5793c4c4), bin32(16#f255a7a7), bin32(16#82fc7e7e), bin32(16#477a3d3d),
       bin32(16#acc86464), bin32(16#e7ba5d5d), bin32(16#2b321919), bin32(16#95e67373),
       bin32(16#a0c06060), bin32(16#98198181), bin32(16#d19e4f4f), bin32(16#7fa3dcdc),
       bin32(16#66442222), bin32(16#7e542a2a), bin32(16#ab3b9090), bin32(16#830b8888),
       bin32(16#ca8c4646), bin32(16#29c7eeee), bin32(16#d36bb8b8), bin32(16#3c281414),
       bin32(16#79a7dede), bin32(16#e2bc5e5e), bin32(16#1d160b0b), bin32(16#76addbdb),
       bin32(16#3bdbe0e0), bin32(16#56643232), bin32(16#4e743a3a), bin32(16#1e140a0a),
       bin32(16#db924949), bin32(16#0a0c0606), bin32(16#6c482424), bin32(16#e4b85c5c),
       bin32(16#5d9fc2c2), bin32(16#6ebdd3d3), bin32(16#ef43acac), bin32(16#a6c46262),
       bin32(16#a8399191), bin32(16#a4319595), bin32(16#37d3e4e4), bin32(16#8bf27979),
       bin32(16#32d5e7e7), bin32(16#438bc8c8), bin32(16#596e3737), bin32(16#b7da6d6d),
       bin32(16#8c018d8d), bin32(16#64b1d5d5), bin32(16#d29c4e4e), bin32(16#e049a9a9),
       bin32(16#b4d86c6c), bin32(16#faac5656), bin32(16#07f3f4f4), bin32(16#25cfeaea),
       bin32(16#afca6565), bin32(16#8ef47a7a), bin32(16#e947aeae), bin32(16#18100808),
       bin32(16#d56fbaba), bin32(16#88f07878), bin32(16#6f4a2525), bin32(16#725c2e2e),
       bin32(16#24381c1c), bin32(16#f157a6a6), bin32(16#c773b4b4), bin32(16#5197c6c6),
       bin32(16#23cbe8e8), bin32(16#7ca1dddd), bin32(16#9ce87474), bin32(16#213e1f1f),
       bin32(16#dd964b4b), bin32(16#dc61bdbd), bin32(16#860d8b8b), bin32(16#850f8a8a),
       bin32(16#90e07070), bin32(16#427c3e3e), bin32(16#c471b5b5), bin32(16#aacc6666),
       bin32(16#d8904848), bin32(16#05060303), bin32(16#01f7f6f6), bin32(16#121c0e0e),
       bin32(16#a3c26161), bin32(16#5f6a3535), bin32(16#f9ae5757), bin32(16#d069b9b9),
       bin32(16#91178686), bin32(16#5899c1c1), bin32(16#273a1d1d), bin32(16#b9279e9e),
       bin32(16#38d9e1e1), bin32(16#13ebf8f8), bin32(16#b32b9898), bin32(16#33221111),
       bin32(16#bbd26969), bin32(16#70a9d9d9), bin32(16#89078e8e), bin32(16#a7339494),
       bin32(16#b62d9b9b), bin32(16#223c1e1e), bin32(16#92158787), bin32(16#20c9e9e9),
       bin32(16#4987cece), bin32(16#ffaa5555), bin32(16#78502828), bin32(16#7aa5dfdf),
       bin32(16#8f038c8c), bin32(16#f859a1a1), bin32(16#80098989), bin32(16#171a0d0d),
       bin32(16#da65bfbf), bin32(16#31d7e6e6), bin32(16#c6844242), bin32(16#b8d06868),
       bin32(16#c3824141), bin32(16#b0299999), bin32(16#775a2d2d), bin32(16#111e0f0f),
       bin32(16#cb7bb0b0), bin32(16#fca85454), bin32(16#d66dbbbb), bin32(16#3a2c1616)),
  # Te[3]:
  [0] (bin32(16#63a5c663), bin32(16#7c84f87c), bin32(16#7799ee77), bin32(16#7b8df67b),
       bin32(16#f20dfff2), bin32(16#6bbdd66b), bin32(16#6fb1de6f), bin32(16#c55491c5),
       bin32(16#30506030), bin32(16#01030201), bin32(16#67a9ce67), bin32(16#2b7d562b),
       bin32(16#fe19e7fe), bin32(16#d762b5d7), bin32(16#abe64dab), bin32(16#769aec76),
       bin32(16#ca458fca), bin32(16#829d1f82), bin32(16#c94089c9), bin32(16#7d87fa7d),
       bin32(16#fa15effa), bin32(16#59ebb259), bin32(16#47c98e47), bin32(16#f00bfbf0),
       bin32(16#adec41ad), bin32(16#d467b3d4), bin32(16#a2fd5fa2), bin32(16#afea45af),
       bin32(16#9cbf239c), bin32(16#a4f753a4), bin32(16#7296e472), bin32(16#c05b9bc0),
       bin32(16#b7c275b7), bin32(16#fd1ce1fd), bin32(16#93ae3d93), bin32(16#266a4c26),
       bin32(16#365a6c36), bin32(16#3f417e3f), bin32(16#f702f5f7), bin32(16#cc4f83cc),
       bin32(16#345c6834), bin32(16#a5f451a5), bin32(16#e534d1e5), bin32(16#f108f9f1),
       bin32(16#7193e271), bin32(16#d873abd8), bin32(16#31536231), bin32(16#153f2a15),
       bin32(16#040c0804), bin32(16#c75295c7), bin32(16#23654623), bin32(16#c35e9dc3),
       bin32(16#18283018), bin32(16#96a13796), bin32(16#050f0a05), bin32(16#9ab52f9a),
       bin32(16#07090e07), bin32(16#12362412), bin32(16#809b1b80), bin32(16#e23ddfe2),
       bin32(16#eb26cdeb), bin32(16#27694e27), bin32(16#b2cd7fb2), bin32(16#759fea75),
       bin32(16#091b1209), bin32(16#839e1d83), bin32(16#2c74582c), bin32(16#1a2e341a),
       bin32(16#1b2d361b), bin32(16#6eb2dc6e), bin32(16#5aeeb45a), bin32(16#a0fb5ba0),
       bin32(16#52f6a452), bin32(16#3b4d763b), bin32(16#d661b7d6), bin32(16#b3ce7db3),
       bin32(16#297b5229), bin32(16#e33edde3), bin32(16#2f715e2f), bin32(16#84971384),
       bin32(16#53f5a653), bin32(16#d168b9d1), bin32(16#00000000), bin32(16#ed2cc1ed),
       bin32(16#20604020), bin32(16#fc1fe3fc), bin32(16#b1c879b1), bin32(16#5bedb65b),
       bin32(16#6abed46a), bin32(16#cb468dcb), bin32(16#bed967be), bin32(16#394b7239),
       bin32(16#4ade944a), bin32(16#4cd4984c), bin32(16#58e8b058), bin32(16#cf4a85cf),
       bin32(16#d06bbbd0), bin32(16#ef2ac5ef), bin32(16#aae54faa), bin32(16#fb16edfb),
       bin32(16#43c58643), bin32(16#4dd79a4d), bin32(16#33556633), bin32(16#85941185),
       bin32(16#45cf8a45), bin32(16#f910e9f9), bin32(16#02060402), bin32(16#7f81fe7f),
       bin32(16#50f0a050), bin32(16#3c44783c), bin32(16#9fba259f), bin32(16#a8e34ba8),
       bin32(16#51f3a251), bin32(16#a3fe5da3), bin32(16#40c08040), bin32(16#8f8a058f),
       bin32(16#92ad3f92), bin32(16#9dbc219d), bin32(16#38487038), bin32(16#f504f1f5),
       bin32(16#bcdf63bc), bin32(16#b6c177b6), bin32(16#da75afda), bin32(16#21634221),
       bin32(16#10302010), bin32(16#ff1ae5ff), bin32(16#f30efdf3), bin32(16#d26dbfd2),
       bin32(16#cd4c81cd), bin32(16#0c14180c), bin32(16#13352613), bin32(16#ec2fc3ec),
       bin32(16#5fe1be5f), bin32(16#97a23597), bin32(16#44cc8844), bin32(16#17392e17),
       bin32(16#c45793c4), bin32(16#a7f255a7), bin32(16#7e82fc7e), bin32(16#3d477a3d),
       bin32(16#64acc864), bin32(16#5de7ba5d), bin32(16#192b3219), bin32(16#7395e673),
       bin32(16#60a0c060), bin32(16#81981981), bin32(16#4fd19e4f), bin32(16#dc7fa3dc),
       bin32(16#22664422), bin32(16#2a7e542a), bin32(16#90ab3b90), bin32(16#88830b88),
       bin32(16#46ca8c46), bin32(16#ee29c7ee), bin32(16#b8d36bb8), bin32(16#143c2814),
       bin32(16#de79a7de), bin32(16#5ee2bc5e), bin32(16#0b1d160b), bin32(16#db76addb),
       bin32(16#e03bdbe0), bin32(16#32566432), bin32(16#3a4e743a), bin32(16#0a1e140a),
       bin32(16#49db9249), bin32(16#060a0c06), bin32(16#246c4824), bin32(16#5ce4b85c),
       bin32(16#c25d9fc2), bin32(16#d36ebdd3), bin32(16#acef43ac), bin32(16#62a6c462),
       bin32(16#91a83991), bin32(16#95a43195), bin32(16#e437d3e4), bin32(16#798bf279),
       bin32(16#e732d5e7), bin32(16#c8438bc8), bin32(16#37596e37), bin32(16#6db7da6d),
       bin32(16#8d8c018d), bin32(16#d564b1d5), bin32(16#4ed29c4e), bin32(16#a9e049a9),
       bin32(16#6cb4d86c), bin32(16#56faac56), bin32(16#f407f3f4), bin32(16#ea25cfea),
       bin32(16#65afca65), bin32(16#7a8ef47a), bin32(16#aee947ae), bin32(16#08181008),
       bin32(16#bad56fba), bin32(16#7888f078), bin32(16#256f4a25), bin32(16#2e725c2e),
       bin32(16#1c24381c), bin32(16#a6f157a6), bin32(16#b4c773b4), bin32(16#c65197c6),
       bin32(16#e823cbe8), bin32(16#dd7ca1dd), bin32(16#749ce874), bin32(16#1f213e1f),
       bin32(16#4bdd964b), bin32(16#bddc61bd), bin32(16#8b860d8b), bin32(16#8a850f8a),
       bin32(16#7090e070), bin32(16#3e427c3e), bin32(16#b5c471b5), bin32(16#66aacc66),
       bin32(16#48d89048), bin32(16#03050603), bin32(16#f601f7f6), bin32(16#0e121c0e),
       bin32(16#61a3c261), bin32(16#355f6a35), bin32(16#57f9ae57), bin32(16#b9d069b9),
       bin32(16#86911786), bin32(16#c15899c1), bin32(16#1d273a1d), bin32(16#9eb9279e),
       bin32(16#e138d9e1), bin32(16#f813ebf8), bin32(16#98b32b98), bin32(16#11332211),
       bin32(16#69bbd269), bin32(16#d970a9d9), bin32(16#8e89078e), bin32(16#94a73394),
       bin32(16#9bb62d9b), bin32(16#1e223c1e), bin32(16#87921587), bin32(16#e920c9e9),
       bin32(16#ce4987ce), bin32(16#55ffaa55), bin32(16#28785028), bin32(16#df7aa5df),
       bin32(16#8c8f038c), bin32(16#a1f859a1), bin32(16#89800989), bin32(16#0d171a0d),
       bin32(16#bfda65bf), bin32(16#e631d7e6), bin32(16#42c68442), bin32(16#68b8d068),
       bin32(16#41c38241), bin32(16#99b02999), bin32(16#2d775a2d), bin32(16#0f111e0f),
       bin32(16#b0cb7bb0), bin32(16#54fca854), bin32(16#bbd66dbb), bin32(16#163a2c16)),
  # Te[4]:
  [0] (bin32(16#6363a5c6), bin32(16#7c7c84f8), bin32(16#777799ee), bin32(16#7b7b8df6),
       bin32(16#f2f20dff), bin32(16#6b6bbdd6), bin32(16#6f6fb1de), bin32(16#c5c55491),
       bin32(16#30305060), bin32(16#01010302), bin32(16#6767a9ce), bin32(16#2b2b7d56),
       bin32(16#fefe19e7), bin32(16#d7d762b5), bin32(16#ababe64d), bin32(16#76769aec),
       bin32(16#caca458f), bin32(16#82829d1f), bin32(16#c9c94089), bin32(16#7d7d87fa),
       bin32(16#fafa15ef), bin32(16#5959ebb2), bin32(16#4747c98e), bin32(16#f0f00bfb),
       bin32(16#adadec41), bin32(16#d4d467b3), bin32(16#a2a2fd5f), bin32(16#afafea45),
       bin32(16#9c9cbf23), bin32(16#a4a4f753), bin32(16#727296e4), bin32(16#c0c05b9b),
       bin32(16#b7b7c275), bin32(16#fdfd1ce1), bin32(16#9393ae3d), bin32(16#26266a4c),
       bin32(16#36365a6c), bin32(16#3f3f417e), bin32(16#f7f702f5), bin32(16#cccc4f83),
       bin32(16#34345c68), bin32(16#a5a5f451), bin32(16#e5e534d1), bin32(16#f1f108f9),
       bin32(16#717193e2), bin32(16#d8d873ab), bin32(16#31315362), bin32(16#15153f2a),
       bin32(16#04040c08), bin32(16#c7c75295), bin32(16#23236546), bin32(16#c3c35e9d),
       bin32(16#18182830), bin32(16#9696a137), bin32(16#05050f0a), bin32(16#9a9ab52f),
       bin32(16#0707090e), bin32(16#12123624), bin32(16#80809b1b), bin32(16#e2e23ddf),
       bin32(16#ebeb26cd), bin32(16#2727694e), bin32(16#b2b2cd7f), bin32(16#75759fea),
       bin32(16#09091b12), bin32(16#83839e1d), bin32(16#2c2c7458), bin32(16#1a1a2e34),
       bin32(16#1b1b2d36), bin32(16#6e6eb2dc), bin32(16#5a5aeeb4), bin32(16#a0a0fb5b),
       bin32(16#5252f6a4), bin32(16#3b3b4d76), bin32(16#d6d661b7), bin32(16#b3b3ce7d),
       bin32(16#29297b52), bin32(16#e3e33edd), bin32(16#2f2f715e), bin32(16#84849713),
       bin32(16#5353f5a6), bin32(16#d1d168b9), bin32(16#00000000), bin32(16#eded2cc1),
       bin32(16#20206040), bin32(16#fcfc1fe3), bin32(16#b1b1c879), bin32(16#5b5bedb6),
       bin32(16#6a6abed4), bin32(16#cbcb468d), bin32(16#bebed967), bin32(16#39394b72),
       bin32(16#4a4ade94), bin32(16#4c4cd498), bin32(16#5858e8b0), bin32(16#cfcf4a85),
       bin32(16#d0d06bbb), bin32(16#efef2ac5), bin32(16#aaaae54f), bin32(16#fbfb16ed),
       bin32(16#4343c586), bin32(16#4d4dd79a), bin32(16#33335566), bin32(16#85859411),
       bin32(16#4545cf8a), bin32(16#f9f910e9), bin32(16#02020604), bin32(16#7f7f81fe),
       bin32(16#5050f0a0), bin32(16#3c3c4478), bin32(16#9f9fba25), bin32(16#a8a8e34b),
       bin32(16#5151f3a2), bin32(16#a3a3fe5d), bin32(16#4040c080), bin32(16#8f8f8a05),
       bin32(16#9292ad3f), bin32(16#9d9dbc21), bin32(16#38384870), bin32(16#f5f504f1),
       bin32(16#bcbcdf63), bin32(16#b6b6c177), bin32(16#dada75af), bin32(16#21216342),
       bin32(16#10103020), bin32(16#ffff1ae5), bin32(16#f3f30efd), bin32(16#d2d26dbf),
       bin32(16#cdcd4c81), bin32(16#0c0c1418), bin32(16#13133526), bin32(16#ecec2fc3),
       bin32(16#5f5fe1be), bin32(16#9797a235), bin32(16#4444cc88), bin32(16#1717392e),
       bin32(16#c4c45793), bin32(16#a7a7f255), bin32(16#7e7e82fc), bin32(16#3d3d477a),
       bin32(16#6464acc8), bin32(16#5d5de7ba), bin32(16#19192b32), bin32(16#737395e6),
       bin32(16#6060a0c0), bin32(16#81819819), bin32(16#4f4fd19e), bin32(16#dcdc7fa3),
       bin32(16#22226644), bin32(16#2a2a7e54), bin32(16#9090ab3b), bin32(16#8888830b),
       bin32(16#4646ca8c), bin32(16#eeee29c7), bin32(16#b8b8d36b), bin32(16#14143c28),
       bin32(16#dede79a7), bin32(16#5e5ee2bc), bin32(16#0b0b1d16), bin32(16#dbdb76ad),
       bin32(16#e0e03bdb), bin32(16#32325664), bin32(16#3a3a4e74), bin32(16#0a0a1e14),
       bin32(16#4949db92), bin32(16#06060a0c), bin32(16#24246c48), bin32(16#5c5ce4b8),
       bin32(16#c2c25d9f), bin32(16#d3d36ebd), bin32(16#acacef43), bin32(16#6262a6c4),
       bin32(16#9191a839), bin32(16#9595a431), bin32(16#e4e437d3), bin32(16#79798bf2),
       bin32(16#e7e732d5), bin32(16#c8c8438b), bin32(16#3737596e), bin32(16#6d6db7da),
       bin32(16#8d8d8c01), bin32(16#d5d564b1), bin32(16#4e4ed29c), bin32(16#a9a9e049),
       bin32(16#6c6cb4d8), bin32(16#5656faac), bin32(16#f4f407f3), bin32(16#eaea25cf),
       bin32(16#6565afca), bin32(16#7a7a8ef4), bin32(16#aeaee947), bin32(16#08081810),
       bin32(16#babad56f), bin32(16#787888f0), bin32(16#25256f4a), bin32(16#2e2e725c),
       bin32(16#1c1c2438), bin32(16#a6a6f157), bin32(16#b4b4c773), bin32(16#c6c65197),
       bin32(16#e8e823cb), bin32(16#dddd7ca1), bin32(16#74749ce8), bin32(16#1f1f213e),
       bin32(16#4b4bdd96), bin32(16#bdbddc61), bin32(16#8b8b860d), bin32(16#8a8a850f),
       bin32(16#707090e0), bin32(16#3e3e427c), bin32(16#b5b5c471), bin32(16#6666aacc),
       bin32(16#4848d890), bin32(16#03030506), bin32(16#f6f601f7), bin32(16#0e0e121c),
       bin32(16#6161a3c2), bin32(16#35355f6a), bin32(16#5757f9ae), bin32(16#b9b9d069),
       bin32(16#86869117), bin32(16#c1c15899), bin32(16#1d1d273a), bin32(16#9e9eb927),
       bin32(16#e1e138d9), bin32(16#f8f813eb), bin32(16#9898b32b), bin32(16#11113322),
       bin32(16#6969bbd2), bin32(16#d9d970a9), bin32(16#8e8e8907), bin32(16#9494a733),
       bin32(16#9b9bb62d), bin32(16#1e1e223c), bin32(16#87879215), bin32(16#e9e920c9),
       bin32(16#cece4987), bin32(16#5555ffaa), bin32(16#28287850), bin32(16#dfdf7aa5),
       bin32(16#8c8c8f03), bin32(16#a1a1f859), bin32(16#89898009), bin32(16#0d0d171a),
       bin32(16#bfbfda65), bin32(16#e6e631d7), bin32(16#4242c684), bin32(16#6868b8d0),
       bin32(16#4141c382), bin32(16#9999b029), bin32(16#2d2d775a), bin32(16#0f0f111e),
       bin32(16#b0b0cb7b), bin32(16#5454fca8), bin32(16#bbbbd66d), bin32(16#16163a2c)),
  # Te[5]:
  [0] (bin32(16#63636363), bin32(16#7c7c7c7c), bin32(16#77777777), bin32(16#7b7b7b7b),
       bin32(16#f2f2f2f2), bin32(16#6b6b6b6b), bin32(16#6f6f6f6f), bin32(16#c5c5c5c5),
       bin32(16#30303030), bin32(16#01010101), bin32(16#67676767), bin32(16#2b2b2b2b),
       bin32(16#fefefefe), bin32(16#d7d7d7d7), bin32(16#abababab), bin32(16#76767676),
       bin32(16#cacacaca), bin32(16#82828282), bin32(16#c9c9c9c9), bin32(16#7d7d7d7d),
       bin32(16#fafafafa), bin32(16#59595959), bin32(16#47474747), bin32(16#f0f0f0f0),
       bin32(16#adadadad), bin32(16#d4d4d4d4), bin32(16#a2a2a2a2), bin32(16#afafafaf),
       bin32(16#9c9c9c9c), bin32(16#a4a4a4a4), bin32(16#72727272), bin32(16#c0c0c0c0),
       bin32(16#b7b7b7b7), bin32(16#fdfdfdfd), bin32(16#93939393), bin32(16#26262626),
       bin32(16#36363636), bin32(16#3f3f3f3f), bin32(16#f7f7f7f7), bin32(16#cccccccc),
       bin32(16#34343434), bin32(16#a5a5a5a5), bin32(16#e5e5e5e5), bin32(16#f1f1f1f1),
       bin32(16#71717171), bin32(16#d8d8d8d8), bin32(16#31313131), bin32(16#15151515),
       bin32(16#04040404), bin32(16#c7c7c7c7), bin32(16#23232323), bin32(16#c3c3c3c3),
       bin32(16#18181818), bin32(16#96969696), bin32(16#05050505), bin32(16#9a9a9a9a),
       bin32(16#07070707), bin32(16#12121212), bin32(16#80808080), bin32(16#e2e2e2e2),
       bin32(16#ebebebeb), bin32(16#27272727), bin32(16#b2b2b2b2), bin32(16#75757575),
       bin32(16#09090909), bin32(16#83838383), bin32(16#2c2c2c2c), bin32(16#1a1a1a1a),
       bin32(16#1b1b1b1b), bin32(16#6e6e6e6e), bin32(16#5a5a5a5a), bin32(16#a0a0a0a0),
       bin32(16#52525252), bin32(16#3b3b3b3b), bin32(16#d6d6d6d6), bin32(16#b3b3b3b3),
       bin32(16#29292929), bin32(16#e3e3e3e3), bin32(16#2f2f2f2f), bin32(16#84848484),
       bin32(16#53535353), bin32(16#d1d1d1d1), bin32(16#00000000), bin32(16#edededed),
       bin32(16#20202020), bin32(16#fcfcfcfc), bin32(16#b1b1b1b1), bin32(16#5b5b5b5b),
       bin32(16#6a6a6a6a), bin32(16#cbcbcbcb), bin32(16#bebebebe), bin32(16#39393939),
       bin32(16#4a4a4a4a), bin32(16#4c4c4c4c), bin32(16#58585858), bin32(16#cfcfcfcf),
       bin32(16#d0d0d0d0), bin32(16#efefefef), bin32(16#aaaaaaaa), bin32(16#fbfbfbfb),
       bin32(16#43434343), bin32(16#4d4d4d4d), bin32(16#33333333), bin32(16#85858585),
       bin32(16#45454545), bin32(16#f9f9f9f9), bin32(16#02020202), bin32(16#7f7f7f7f),
       bin32(16#50505050), bin32(16#3c3c3c3c), bin32(16#9f9f9f9f), bin32(16#a8a8a8a8),
       bin32(16#51515151), bin32(16#a3a3a3a3), bin32(16#40404040), bin32(16#8f8f8f8f),
       bin32(16#92929292), bin32(16#9d9d9d9d), bin32(16#38383838), bin32(16#f5f5f5f5),
       bin32(16#bcbcbcbc), bin32(16#b6b6b6b6), bin32(16#dadadada), bin32(16#21212121),
       bin32(16#10101010), bin32(16#ffffffff), bin32(16#f3f3f3f3), bin32(16#d2d2d2d2),
       bin32(16#cdcdcdcd), bin32(16#0c0c0c0c), bin32(16#13131313), bin32(16#ecececec),
       bin32(16#5f5f5f5f), bin32(16#97979797), bin32(16#44444444), bin32(16#17171717),
       bin32(16#c4c4c4c4), bin32(16#a7a7a7a7), bin32(16#7e7e7e7e), bin32(16#3d3d3d3d),
       bin32(16#64646464), bin32(16#5d5d5d5d), bin32(16#19191919), bin32(16#73737373),
       bin32(16#60606060), bin32(16#81818181), bin32(16#4f4f4f4f), bin32(16#dcdcdcdc),
       bin32(16#22222222), bin32(16#2a2a2a2a), bin32(16#90909090), bin32(16#88888888),
       bin32(16#46464646), bin32(16#eeeeeeee), bin32(16#b8b8b8b8), bin32(16#14141414),
       bin32(16#dededede), bin32(16#5e5e5e5e), bin32(16#0b0b0b0b), bin32(16#dbdbdbdb),
       bin32(16#e0e0e0e0), bin32(16#32323232), bin32(16#3a3a3a3a), bin32(16#0a0a0a0a),
       bin32(16#49494949), bin32(16#06060606), bin32(16#24242424), bin32(16#5c5c5c5c),
       bin32(16#c2c2c2c2), bin32(16#d3d3d3d3), bin32(16#acacacac), bin32(16#62626262),
       bin32(16#91919191), bin32(16#95959595), bin32(16#e4e4e4e4), bin32(16#79797979),
       bin32(16#e7e7e7e7), bin32(16#c8c8c8c8), bin32(16#37373737), bin32(16#6d6d6d6d),
       bin32(16#8d8d8d8d), bin32(16#d5d5d5d5), bin32(16#4e4e4e4e), bin32(16#a9a9a9a9),
       bin32(16#6c6c6c6c), bin32(16#56565656), bin32(16#f4f4f4f4), bin32(16#eaeaeaea),
       bin32(16#65656565), bin32(16#7a7a7a7a), bin32(16#aeaeaeae), bin32(16#08080808),
       bin32(16#babababa), bin32(16#78787878), bin32(16#25252525), bin32(16#2e2e2e2e),
       bin32(16#1c1c1c1c), bin32(16#a6a6a6a6), bin32(16#b4b4b4b4), bin32(16#c6c6c6c6),
       bin32(16#e8e8e8e8), bin32(16#dddddddd), bin32(16#74747474), bin32(16#1f1f1f1f),
       bin32(16#4b4b4b4b), bin32(16#bdbdbdbd), bin32(16#8b8b8b8b), bin32(16#8a8a8a8a),
       bin32(16#70707070), bin32(16#3e3e3e3e), bin32(16#b5b5b5b5), bin32(16#66666666),
       bin32(16#48484848), bin32(16#03030303), bin32(16#f6f6f6f6), bin32(16#0e0e0e0e),
       bin32(16#61616161), bin32(16#35353535), bin32(16#57575757), bin32(16#b9b9b9b9),
       bin32(16#86868686), bin32(16#c1c1c1c1), bin32(16#1d1d1d1d), bin32(16#9e9e9e9e),
       bin32(16#e1e1e1e1), bin32(16#f8f8f8f8), bin32(16#98989898), bin32(16#11111111),
       bin32(16#69696969), bin32(16#d9d9d9d9), bin32(16#8e8e8e8e), bin32(16#94949494),
       bin32(16#9b9b9b9b), bin32(16#1e1e1e1e), bin32(16#87878787), bin32(16#e9e9e9e9),
       bin32(16#cececece), bin32(16#55555555), bin32(16#28282828), bin32(16#dfdfdfdf),
       bin32(16#8c8c8c8c), bin32(16#a1a1a1a1), bin32(16#89898989), bin32(16#0d0d0d0d),
       bin32(16#bfbfbfbf), bin32(16#e6e6e6e6), bin32(16#42424242), bin32(16#68686868),
       bin32(16#41414141), bin32(16#99999999), bin32(16#2d2d2d2d), bin32(16#0f0f0f0f),
       bin32(16#b0b0b0b0), bin32(16#54545454), bin32(16#bbbbbbbb), bin32(16#16161616)));


const array array bin32: Td is [] (
  # Td[1]:
  [0] (bin32(16#51f4a750), bin32(16#7e416553), bin32(16#1a17a4c3), bin32(16#3a275e96),
       bin32(16#3bab6bcb), bin32(16#1f9d45f1), bin32(16#acfa58ab), bin32(16#4be30393),
       bin32(16#2030fa55), bin32(16#ad766df6), bin32(16#88cc7691), bin32(16#f5024c25),
       bin32(16#4fe5d7fc), bin32(16#c52acbd7), bin32(16#26354480), bin32(16#b562a38f),
       bin32(16#deb15a49), bin32(16#25ba1b67), bin32(16#45ea0e98), bin32(16#5dfec0e1),
       bin32(16#c32f7502), bin32(16#814cf012), bin32(16#8d4697a3), bin32(16#6bd3f9c6),
       bin32(16#038f5fe7), bin32(16#15929c95), bin32(16#bf6d7aeb), bin32(16#955259da),
       bin32(16#d4be832d), bin32(16#587421d3), bin32(16#49e06929), bin32(16#8ec9c844),
       bin32(16#75c2896a), bin32(16#f48e7978), bin32(16#99583e6b), bin32(16#27b971dd),
       bin32(16#bee14fb6), bin32(16#f088ad17), bin32(16#c920ac66), bin32(16#7dce3ab4),
       bin32(16#63df4a18), bin32(16#e51a3182), bin32(16#97513360), bin32(16#62537f45),
       bin32(16#b16477e0), bin32(16#bb6bae84), bin32(16#fe81a01c), bin32(16#f9082b94),
       bin32(16#70486858), bin32(16#8f45fd19), bin32(16#94de6c87), bin32(16#527bf8b7),
       bin32(16#ab73d323), bin32(16#724b02e2), bin32(16#e31f8f57), bin32(16#6655ab2a),
       bin32(16#b2eb2807), bin32(16#2fb5c203), bin32(16#86c57b9a), bin32(16#d33708a5),
       bin32(16#302887f2), bin32(16#23bfa5b2), bin32(16#02036aba), bin32(16#ed16825c),
       bin32(16#8acf1c2b), bin32(16#a779b492), bin32(16#f307f2f0), bin32(16#4e69e2a1),
       bin32(16#65daf4cd), bin32(16#0605bed5), bin32(16#d134621f), bin32(16#c4a6fe8a),
       bin32(16#342e539d), bin32(16#a2f355a0), bin32(16#058ae132), bin32(16#a4f6eb75),
       bin32(16#0b83ec39), bin32(16#4060efaa), bin32(16#5e719f06), bin32(16#bd6e1051),
       bin32(16#3e218af9), bin32(16#96dd063d), bin32(16#dd3e05ae), bin32(16#4de6bd46),
       bin32(16#91548db5), bin32(16#71c45d05), bin32(16#0406d46f), bin32(16#605015ff),
       bin32(16#1998fb24), bin32(16#d6bde997), bin32(16#894043cc), bin32(16#67d99e77),
       bin32(16#b0e842bd), bin32(16#07898b88), bin32(16#e7195b38), bin32(16#79c8eedb),
       bin32(16#a17c0a47), bin32(16#7c420fe9), bin32(16#f8841ec9), bin32(16#00000000),
       bin32(16#09808683), bin32(16#322bed48), bin32(16#1e1170ac), bin32(16#6c5a724e),
       bin32(16#fd0efffb), bin32(16#0f853856), bin32(16#3daed51e), bin32(16#362d3927),
       bin32(16#0a0fd964), bin32(16#685ca621), bin32(16#9b5b54d1), bin32(16#24362e3a),
       bin32(16#0c0a67b1), bin32(16#9357e70f), bin32(16#b4ee96d2), bin32(16#1b9b919e),
       bin32(16#80c0c54f), bin32(16#61dc20a2), bin32(16#5a774b69), bin32(16#1c121a16),
       bin32(16#e293ba0a), bin32(16#c0a02ae5), bin32(16#3c22e043), bin32(16#121b171d),
       bin32(16#0e090d0b), bin32(16#f28bc7ad), bin32(16#2db6a8b9), bin32(16#141ea9c8),
       bin32(16#57f11985), bin32(16#af75074c), bin32(16#ee99ddbb), bin32(16#a37f60fd),
       bin32(16#f701269f), bin32(16#5c72f5bc), bin32(16#44663bc5), bin32(16#5bfb7e34),
       bin32(16#8b432976), bin32(16#cb23c6dc), bin32(16#b6edfc68), bin32(16#b8e4f163),
       bin32(16#d731dcca), bin32(16#42638510), bin32(16#13972240), bin32(16#84c61120),
       bin32(16#854a247d), bin32(16#d2bb3df8), bin32(16#aef93211), bin32(16#c729a16d),
       bin32(16#1d9e2f4b), bin32(16#dcb230f3), bin32(16#0d8652ec), bin32(16#77c1e3d0),
       bin32(16#2bb3166c), bin32(16#a970b999), bin32(16#119448fa), bin32(16#47e96422),
       bin32(16#a8fc8cc4), bin32(16#a0f03f1a), bin32(16#567d2cd8), bin32(16#223390ef),
       bin32(16#87494ec7), bin32(16#d938d1c1), bin32(16#8ccaa2fe), bin32(16#98d40b36),
       bin32(16#a6f581cf), bin32(16#a57ade28), bin32(16#dab78e26), bin32(16#3fadbfa4),
       bin32(16#2c3a9de4), bin32(16#5078920d), bin32(16#6a5fcc9b), bin32(16#547e4662),
       bin32(16#f68d13c2), bin32(16#90d8b8e8), bin32(16#2e39f75e), bin32(16#82c3aff5),
       bin32(16#9f5d80be), bin32(16#69d0937c), bin32(16#6fd52da9), bin32(16#cf2512b3),
       bin32(16#c8ac993b), bin32(16#10187da7), bin32(16#e89c636e), bin32(16#db3bbb7b),
       bin32(16#cd267809), bin32(16#6e5918f4), bin32(16#ec9ab701), bin32(16#834f9aa8),
       bin32(16#e6956e65), bin32(16#aaffe67e), bin32(16#21bccf08), bin32(16#ef15e8e6),
       bin32(16#bae79bd9), bin32(16#4a6f36ce), bin32(16#ea9f09d4), bin32(16#29b07cd6),
       bin32(16#31a4b2af), bin32(16#2a3f2331), bin32(16#c6a59430), bin32(16#35a266c0),
       bin32(16#744ebc37), bin32(16#fc82caa6), bin32(16#e090d0b0), bin32(16#33a7d815),
       bin32(16#f104984a), bin32(16#41ecdaf7), bin32(16#7fcd500e), bin32(16#1791f62f),
       bin32(16#764dd68d), bin32(16#43efb04d), bin32(16#ccaa4d54), bin32(16#e49604df),
       bin32(16#9ed1b5e3), bin32(16#4c6a881b), bin32(16#c12c1fb8), bin32(16#4665517f),
       bin32(16#9d5eea04), bin32(16#018c355d), bin32(16#fa877473), bin32(16#fb0b412e),
       bin32(16#b3671d5a), bin32(16#92dbd252), bin32(16#e9105633), bin32(16#6dd64713),
       bin32(16#9ad7618c), bin32(16#37a10c7a), bin32(16#59f8148e), bin32(16#eb133c89),
       bin32(16#cea927ee), bin32(16#b761c935), bin32(16#e11ce5ed), bin32(16#7a47b13c),
       bin32(16#9cd2df59), bin32(16#55f2733f), bin32(16#1814ce79), bin32(16#73c737bf),
       bin32(16#53f7cdea), bin32(16#5ffdaa5b), bin32(16#df3d6f14), bin32(16#7844db86),
       bin32(16#caaff381), bin32(16#b968c43e), bin32(16#3824342c), bin32(16#c2a3405f),
       bin32(16#161dc372), bin32(16#bce2250c), bin32(16#283c498b), bin32(16#ff0d9541),
       bin32(16#39a80171), bin32(16#080cb3de), bin32(16#d8b4e49c), bin32(16#6456c190),
       bin32(16#7bcb8461), bin32(16#d532b670), bin32(16#486c5c74), bin32(16#d0b85742)),
  # Td[2]:
  [0] (bin32(16#5051f4a7), bin32(16#537e4165), bin32(16#c31a17a4), bin32(16#963a275e),
       bin32(16#cb3bab6b), bin32(16#f11f9d45), bin32(16#abacfa58), bin32(16#934be303),
       bin32(16#552030fa), bin32(16#f6ad766d), bin32(16#9188cc76), bin32(16#25f5024c),
       bin32(16#fc4fe5d7), bin32(16#d7c52acb), bin32(16#80263544), bin32(16#8fb562a3),
       bin32(16#49deb15a), bin32(16#6725ba1b), bin32(16#9845ea0e), bin32(16#e15dfec0),
       bin32(16#02c32f75), bin32(16#12814cf0), bin32(16#a38d4697), bin32(16#c66bd3f9),
       bin32(16#e7038f5f), bin32(16#9515929c), bin32(16#ebbf6d7a), bin32(16#da955259),
       bin32(16#2dd4be83), bin32(16#d3587421), bin32(16#2949e069), bin32(16#448ec9c8),
       bin32(16#6a75c289), bin32(16#78f48e79), bin32(16#6b99583e), bin32(16#dd27b971),
       bin32(16#b6bee14f), bin32(16#17f088ad), bin32(16#66c920ac), bin32(16#b47dce3a),
       bin32(16#1863df4a), bin32(16#82e51a31), bin32(16#60975133), bin32(16#4562537f),
       bin32(16#e0b16477), bin32(16#84bb6bae), bin32(16#1cfe81a0), bin32(16#94f9082b),
       bin32(16#58704868), bin32(16#198f45fd), bin32(16#8794de6c), bin32(16#b7527bf8),
       bin32(16#23ab73d3), bin32(16#e2724b02), bin32(16#57e31f8f), bin32(16#2a6655ab),
       bin32(16#07b2eb28), bin32(16#032fb5c2), bin32(16#9a86c57b), bin32(16#a5d33708),
       bin32(16#f2302887), bin32(16#b223bfa5), bin32(16#ba02036a), bin32(16#5ced1682),
       bin32(16#2b8acf1c), bin32(16#92a779b4), bin32(16#f0f307f2), bin32(16#a14e69e2),
       bin32(16#cd65daf4), bin32(16#d50605be), bin32(16#1fd13462), bin32(16#8ac4a6fe),
       bin32(16#9d342e53), bin32(16#a0a2f355), bin32(16#32058ae1), bin32(16#75a4f6eb),
       bin32(16#390b83ec), bin32(16#aa4060ef), bin32(16#065e719f), bin32(16#51bd6e10),
       bin32(16#f93e218a), bin32(16#3d96dd06), bin32(16#aedd3e05), bin32(16#464de6bd),
       bin32(16#b591548d), bin32(16#0571c45d), bin32(16#6f0406d4), bin32(16#ff605015),
       bin32(16#241998fb), bin32(16#97d6bde9), bin32(16#cc894043), bin32(16#7767d99e),
       bin32(16#bdb0e842), bin32(16#8807898b), bin32(16#38e7195b), bin32(16#db79c8ee),
       bin32(16#47a17c0a), bin32(16#e97c420f), bin32(16#c9f8841e), bin32(16#00000000),
       bin32(16#83098086), bin32(16#48322bed), bin32(16#ac1e1170), bin32(16#4e6c5a72),
       bin32(16#fbfd0eff), bin32(16#560f8538), bin32(16#1e3daed5), bin32(16#27362d39),
       bin32(16#640a0fd9), bin32(16#21685ca6), bin32(16#d19b5b54), bin32(16#3a24362e),
       bin32(16#b10c0a67), bin32(16#0f9357e7), bin32(16#d2b4ee96), bin32(16#9e1b9b91),
       bin32(16#4f80c0c5), bin32(16#a261dc20), bin32(16#695a774b), bin32(16#161c121a),
       bin32(16#0ae293ba), bin32(16#e5c0a02a), bin32(16#433c22e0), bin32(16#1d121b17),
       bin32(16#0b0e090d), bin32(16#adf28bc7), bin32(16#b92db6a8), bin32(16#c8141ea9),
       bin32(16#8557f119), bin32(16#4caf7507), bin32(16#bbee99dd), bin32(16#fda37f60),
       bin32(16#9ff70126), bin32(16#bc5c72f5), bin32(16#c544663b), bin32(16#345bfb7e),
       bin32(16#768b4329), bin32(16#dccb23c6), bin32(16#68b6edfc), bin32(16#63b8e4f1),
       bin32(16#cad731dc), bin32(16#10426385), bin32(16#40139722), bin32(16#2084c611),
       bin32(16#7d854a24), bin32(16#f8d2bb3d), bin32(16#11aef932), bin32(16#6dc729a1),
       bin32(16#4b1d9e2f), bin32(16#f3dcb230), bin32(16#ec0d8652), bin32(16#d077c1e3),
       bin32(16#6c2bb316), bin32(16#99a970b9), bin32(16#fa119448), bin32(16#2247e964),
       bin32(16#c4a8fc8c), bin32(16#1aa0f03f), bin32(16#d8567d2c), bin32(16#ef223390),
       bin32(16#c787494e), bin32(16#c1d938d1), bin32(16#fe8ccaa2), bin32(16#3698d40b),
       bin32(16#cfa6f581), bin32(16#28a57ade), bin32(16#26dab78e), bin32(16#a43fadbf),
       bin32(16#e42c3a9d), bin32(16#0d507892), bin32(16#9b6a5fcc), bin32(16#62547e46),
       bin32(16#c2f68d13), bin32(16#e890d8b8), bin32(16#5e2e39f7), bin32(16#f582c3af),
       bin32(16#be9f5d80), bin32(16#7c69d093), bin32(16#a96fd52d), bin32(16#b3cf2512),
       bin32(16#3bc8ac99), bin32(16#a710187d), bin32(16#6ee89c63), bin32(16#7bdb3bbb),
       bin32(16#09cd2678), bin32(16#f46e5918), bin32(16#01ec9ab7), bin32(16#a8834f9a),
       bin32(16#65e6956e), bin32(16#7eaaffe6), bin32(16#0821bccf), bin32(16#e6ef15e8),
       bin32(16#d9bae79b), bin32(16#ce4a6f36), bin32(16#d4ea9f09), bin32(16#d629b07c),
       bin32(16#af31a4b2), bin32(16#312a3f23), bin32(16#30c6a594), bin32(16#c035a266),
       bin32(16#37744ebc), bin32(16#a6fc82ca), bin32(16#b0e090d0), bin32(16#1533a7d8),
       bin32(16#4af10498), bin32(16#f741ecda), bin32(16#0e7fcd50), bin32(16#2f1791f6),
       bin32(16#8d764dd6), bin32(16#4d43efb0), bin32(16#54ccaa4d), bin32(16#dfe49604),
       bin32(16#e39ed1b5), bin32(16#1b4c6a88), bin32(16#b8c12c1f), bin32(16#7f466551),
       bin32(16#049d5eea), bin32(16#5d018c35), bin32(16#73fa8774), bin32(16#2efb0b41),
       bin32(16#5ab3671d), bin32(16#5292dbd2), bin32(16#33e91056), bin32(16#136dd647),
       bin32(16#8c9ad761), bin32(16#7a37a10c), bin32(16#8e59f814), bin32(16#89eb133c),
       bin32(16#eecea927), bin32(16#35b761c9), bin32(16#ede11ce5), bin32(16#3c7a47b1),
       bin32(16#599cd2df), bin32(16#3f55f273), bin32(16#791814ce), bin32(16#bf73c737),
       bin32(16#ea53f7cd), bin32(16#5b5ffdaa), bin32(16#14df3d6f), bin32(16#867844db),
       bin32(16#81caaff3), bin32(16#3eb968c4), bin32(16#2c382434), bin32(16#5fc2a340),
       bin32(16#72161dc3), bin32(16#0cbce225), bin32(16#8b283c49), bin32(16#41ff0d95),
       bin32(16#7139a801), bin32(16#de080cb3), bin32(16#9cd8b4e4), bin32(16#906456c1),
       bin32(16#617bcb84), bin32(16#70d532b6), bin32(16#74486c5c), bin32(16#42d0b857)),
  # Td[3]:
  [0] (bin32(16#a75051f4), bin32(16#65537e41), bin32(16#a4c31a17), bin32(16#5e963a27),
       bin32(16#6bcb3bab), bin32(16#45f11f9d), bin32(16#58abacfa), bin32(16#03934be3),
       bin32(16#fa552030), bin32(16#6df6ad76), bin32(16#769188cc), bin32(16#4c25f502),
       bin32(16#d7fc4fe5), bin32(16#cbd7c52a), bin32(16#44802635), bin32(16#a38fb562),
       bin32(16#5a49deb1), bin32(16#1b6725ba), bin32(16#0e9845ea), bin32(16#c0e15dfe),
       bin32(16#7502c32f), bin32(16#f012814c), bin32(16#97a38d46), bin32(16#f9c66bd3),
       bin32(16#5fe7038f), bin32(16#9c951592), bin32(16#7aebbf6d), bin32(16#59da9552),
       bin32(16#832dd4be), bin32(16#21d35874), bin32(16#692949e0), bin32(16#c8448ec9),
       bin32(16#896a75c2), bin32(16#7978f48e), bin32(16#3e6b9958), bin32(16#71dd27b9),
       bin32(16#4fb6bee1), bin32(16#ad17f088), bin32(16#ac66c920), bin32(16#3ab47dce),
       bin32(16#4a1863df), bin32(16#3182e51a), bin32(16#33609751), bin32(16#7f456253),
       bin32(16#77e0b164), bin32(16#ae84bb6b), bin32(16#a01cfe81), bin32(16#2b94f908),
       bin32(16#68587048), bin32(16#fd198f45), bin32(16#6c8794de), bin32(16#f8b7527b),
       bin32(16#d323ab73), bin32(16#02e2724b), bin32(16#8f57e31f), bin32(16#ab2a6655),
       bin32(16#2807b2eb), bin32(16#c2032fb5), bin32(16#7b9a86c5), bin32(16#08a5d337),
       bin32(16#87f23028), bin32(16#a5b223bf), bin32(16#6aba0203), bin32(16#825ced16),
       bin32(16#1c2b8acf), bin32(16#b492a779), bin32(16#f2f0f307), bin32(16#e2a14e69),
       bin32(16#f4cd65da), bin32(16#bed50605), bin32(16#621fd134), bin32(16#fe8ac4a6),
       bin32(16#539d342e), bin32(16#55a0a2f3), bin32(16#e132058a), bin32(16#eb75a4f6),
       bin32(16#ec390b83), bin32(16#efaa4060), bin32(16#9f065e71), bin32(16#1051bd6e),
       bin32(16#8af93e21), bin32(16#063d96dd), bin32(16#05aedd3e), bin32(16#bd464de6),
       bin32(16#8db59154), bin32(16#5d0571c4), bin32(16#d46f0406), bin32(16#15ff6050),
       bin32(16#fb241998), bin32(16#e997d6bd), bin32(16#43cc8940), bin32(16#9e7767d9),
       bin32(16#42bdb0e8), bin32(16#8b880789), bin32(16#5b38e719), bin32(16#eedb79c8),
       bin32(16#0a47a17c), bin32(16#0fe97c42), bin32(16#1ec9f884), bin32(16#00000000),
       bin32(16#86830980), bin32(16#ed48322b), bin32(16#70ac1e11), bin32(16#724e6c5a),
       bin32(16#fffbfd0e), bin32(16#38560f85), bin32(16#d51e3dae), bin32(16#3927362d),
       bin32(16#d9640a0f), bin32(16#a621685c), bin32(16#54d19b5b), bin32(16#2e3a2436),
       bin32(16#67b10c0a), bin32(16#e70f9357), bin32(16#96d2b4ee), bin32(16#919e1b9b),
       bin32(16#c54f80c0), bin32(16#20a261dc), bin32(16#4b695a77), bin32(16#1a161c12),
       bin32(16#ba0ae293), bin32(16#2ae5c0a0), bin32(16#e0433c22), bin32(16#171d121b),
       bin32(16#0d0b0e09), bin32(16#c7adf28b), bin32(16#a8b92db6), bin32(16#a9c8141e),
       bin32(16#198557f1), bin32(16#074caf75), bin32(16#ddbbee99), bin32(16#60fda37f),
       bin32(16#269ff701), bin32(16#f5bc5c72), bin32(16#3bc54466), bin32(16#7e345bfb),
       bin32(16#29768b43), bin32(16#c6dccb23), bin32(16#fc68b6ed), bin32(16#f163b8e4),
       bin32(16#dccad731), bin32(16#85104263), bin32(16#22401397), bin32(16#112084c6),
       bin32(16#247d854a), bin32(16#3df8d2bb), bin32(16#3211aef9), bin32(16#a16dc729),
       bin32(16#2f4b1d9e), bin32(16#30f3dcb2), bin32(16#52ec0d86), bin32(16#e3d077c1),
       bin32(16#166c2bb3), bin32(16#b999a970), bin32(16#48fa1194), bin32(16#642247e9),
       bin32(16#8cc4a8fc), bin32(16#3f1aa0f0), bin32(16#2cd8567d), bin32(16#90ef2233),
       bin32(16#4ec78749), bin32(16#d1c1d938), bin32(16#a2fe8cca), bin32(16#0b3698d4),
       bin32(16#81cfa6f5), bin32(16#de28a57a), bin32(16#8e26dab7), bin32(16#bfa43fad),
       bin32(16#9de42c3a), bin32(16#920d5078), bin32(16#cc9b6a5f), bin32(16#4662547e),
       bin32(16#13c2f68d), bin32(16#b8e890d8), bin32(16#f75e2e39), bin32(16#aff582c3),
       bin32(16#80be9f5d), bin32(16#937c69d0), bin32(16#2da96fd5), bin32(16#12b3cf25),
       bin32(16#993bc8ac), bin32(16#7da71018), bin32(16#636ee89c), bin32(16#bb7bdb3b),
       bin32(16#7809cd26), bin32(16#18f46e59), bin32(16#b701ec9a), bin32(16#9aa8834f),
       bin32(16#6e65e695), bin32(16#e67eaaff), bin32(16#cf0821bc), bin32(16#e8e6ef15),
       bin32(16#9bd9bae7), bin32(16#36ce4a6f), bin32(16#09d4ea9f), bin32(16#7cd629b0),
       bin32(16#b2af31a4), bin32(16#23312a3f), bin32(16#9430c6a5), bin32(16#66c035a2),
       bin32(16#bc37744e), bin32(16#caa6fc82), bin32(16#d0b0e090), bin32(16#d81533a7),
       bin32(16#984af104), bin32(16#daf741ec), bin32(16#500e7fcd), bin32(16#f62f1791),
       bin32(16#d68d764d), bin32(16#b04d43ef), bin32(16#4d54ccaa), bin32(16#04dfe496),
       bin32(16#b5e39ed1), bin32(16#881b4c6a), bin32(16#1fb8c12c), bin32(16#517f4665),
       bin32(16#ea049d5e), bin32(16#355d018c), bin32(16#7473fa87), bin32(16#412efb0b),
       bin32(16#1d5ab367), bin32(16#d25292db), bin32(16#5633e910), bin32(16#47136dd6),
       bin32(16#618c9ad7), bin32(16#0c7a37a1), bin32(16#148e59f8), bin32(16#3c89eb13),
       bin32(16#27eecea9), bin32(16#c935b761), bin32(16#e5ede11c), bin32(16#b13c7a47),
       bin32(16#df599cd2), bin32(16#733f55f2), bin32(16#ce791814), bin32(16#37bf73c7),
       bin32(16#cdea53f7), bin32(16#aa5b5ffd), bin32(16#6f14df3d), bin32(16#db867844),
       bin32(16#f381caaf), bin32(16#c43eb968), bin32(16#342c3824), bin32(16#405fc2a3),
       bin32(16#c372161d), bin32(16#250cbce2), bin32(16#498b283c), bin32(16#9541ff0d),
       bin32(16#017139a8), bin32(16#b3de080c), bin32(16#e49cd8b4), bin32(16#c1906456),
       bin32(16#84617bcb), bin32(16#b670d532), bin32(16#5c74486c), bin32(16#5742d0b8)),
  # Td[4]:
  [0] (bin32(16#f4a75051), bin32(16#4165537e), bin32(16#17a4c31a), bin32(16#275e963a),
       bin32(16#ab6bcb3b), bin32(16#9d45f11f), bin32(16#fa58abac), bin32(16#e303934b),
       bin32(16#30fa5520), bin32(16#766df6ad), bin32(16#cc769188), bin32(16#024c25f5),
       bin32(16#e5d7fc4f), bin32(16#2acbd7c5), bin32(16#35448026), bin32(16#62a38fb5),
       bin32(16#b15a49de), bin32(16#ba1b6725), bin32(16#ea0e9845), bin32(16#fec0e15d),
       bin32(16#2f7502c3), bin32(16#4cf01281), bin32(16#4697a38d), bin32(16#d3f9c66b),
       bin32(16#8f5fe703), bin32(16#929c9515), bin32(16#6d7aebbf), bin32(16#5259da95),
       bin32(16#be832dd4), bin32(16#7421d358), bin32(16#e0692949), bin32(16#c9c8448e),
       bin32(16#c2896a75), bin32(16#8e7978f4), bin32(16#583e6b99), bin32(16#b971dd27),
       bin32(16#e14fb6be), bin32(16#88ad17f0), bin32(16#20ac66c9), bin32(16#ce3ab47d),
       bin32(16#df4a1863), bin32(16#1a3182e5), bin32(16#51336097), bin32(16#537f4562),
       bin32(16#6477e0b1), bin32(16#6bae84bb), bin32(16#81a01cfe), bin32(16#082b94f9),
       bin32(16#48685870), bin32(16#45fd198f), bin32(16#de6c8794), bin32(16#7bf8b752),
       bin32(16#73d323ab), bin32(16#4b02e272), bin32(16#1f8f57e3), bin32(16#55ab2a66),
       bin32(16#eb2807b2), bin32(16#b5c2032f), bin32(16#c57b9a86), bin32(16#3708a5d3),
       bin32(16#2887f230), bin32(16#bfa5b223), bin32(16#036aba02), bin32(16#16825ced),
       bin32(16#cf1c2b8a), bin32(16#79b492a7), bin32(16#07f2f0f3), bin32(16#69e2a14e),
       bin32(16#daf4cd65), bin32(16#05bed506), bin32(16#34621fd1), bin32(16#a6fe8ac4),
       bin32(16#2e539d34), bin32(16#f355a0a2), bin32(16#8ae13205), bin32(16#f6eb75a4),
       bin32(16#83ec390b), bin32(16#60efaa40), bin32(16#719f065e), bin32(16#6e1051bd),
       bin32(16#218af93e), bin32(16#dd063d96), bin32(16#3e05aedd), bin32(16#e6bd464d),
       bin32(16#548db591), bin32(16#c45d0571), bin32(16#06d46f04), bin32(16#5015ff60),
       bin32(16#98fb2419), bin32(16#bde997d6), bin32(16#4043cc89), bin32(16#d99e7767),
       bin32(16#e842bdb0), bin32(16#898b8807), bin32(16#195b38e7), bin32(16#c8eedb79),
       bin32(16#7c0a47a1), bin32(16#420fe97c), bin32(16#841ec9f8), bin32(16#00000000),
       bin32(16#80868309), bin32(16#2bed4832), bin32(16#1170ac1e), bin32(16#5a724e6c),
       bin32(16#0efffbfd), bin32(16#8538560f), bin32(16#aed51e3d), bin32(16#2d392736),
       bin32(16#0fd9640a), bin32(16#5ca62168), bin32(16#5b54d19b), bin32(16#362e3a24),
       bin32(16#0a67b10c), bin32(16#57e70f93), bin32(16#ee96d2b4), bin32(16#9b919e1b),
       bin32(16#c0c54f80), bin32(16#dc20a261), bin32(16#774b695a), bin32(16#121a161c),
       bin32(16#93ba0ae2), bin32(16#a02ae5c0), bin32(16#22e0433c), bin32(16#1b171d12),
       bin32(16#090d0b0e), bin32(16#8bc7adf2), bin32(16#b6a8b92d), bin32(16#1ea9c814),
       bin32(16#f1198557), bin32(16#75074caf), bin32(16#99ddbbee), bin32(16#7f60fda3),
       bin32(16#01269ff7), bin32(16#72f5bc5c), bin32(16#663bc544), bin32(16#fb7e345b),
       bin32(16#4329768b), bin32(16#23c6dccb), bin32(16#edfc68b6), bin32(16#e4f163b8),
       bin32(16#31dccad7), bin32(16#63851042), bin32(16#97224013), bin32(16#c6112084),
       bin32(16#4a247d85), bin32(16#bb3df8d2), bin32(16#f93211ae), bin32(16#29a16dc7),
       bin32(16#9e2f4b1d), bin32(16#b230f3dc), bin32(16#8652ec0d), bin32(16#c1e3d077),
       bin32(16#b3166c2b), bin32(16#70b999a9), bin32(16#9448fa11), bin32(16#e9642247),
       bin32(16#fc8cc4a8), bin32(16#f03f1aa0), bin32(16#7d2cd856), bin32(16#3390ef22),
       bin32(16#494ec787), bin32(16#38d1c1d9), bin32(16#caa2fe8c), bin32(16#d40b3698),
       bin32(16#f581cfa6), bin32(16#7ade28a5), bin32(16#b78e26da), bin32(16#adbfa43f),
       bin32(16#3a9de42c), bin32(16#78920d50), bin32(16#5fcc9b6a), bin32(16#7e466254),
       bin32(16#8d13c2f6), bin32(16#d8b8e890), bin32(16#39f75e2e), bin32(16#c3aff582),
       bin32(16#5d80be9f), bin32(16#d0937c69), bin32(16#d52da96f), bin32(16#2512b3cf),
       bin32(16#ac993bc8), bin32(16#187da710), bin32(16#9c636ee8), bin32(16#3bbb7bdb),
       bin32(16#267809cd), bin32(16#5918f46e), bin32(16#9ab701ec), bin32(16#4f9aa883),
       bin32(16#956e65e6), bin32(16#ffe67eaa), bin32(16#bccf0821), bin32(16#15e8e6ef),
       bin32(16#e79bd9ba), bin32(16#6f36ce4a), bin32(16#9f09d4ea), bin32(16#b07cd629),
       bin32(16#a4b2af31), bin32(16#3f23312a), bin32(16#a59430c6), bin32(16#a266c035),
       bin32(16#4ebc3774), bin32(16#82caa6fc), bin32(16#90d0b0e0), bin32(16#a7d81533),
       bin32(16#04984af1), bin32(16#ecdaf741), bin32(16#cd500e7f), bin32(16#91f62f17),
       bin32(16#4dd68d76), bin32(16#efb04d43), bin32(16#aa4d54cc), bin32(16#9604dfe4),
       bin32(16#d1b5e39e), bin32(16#6a881b4c), bin32(16#2c1fb8c1), bin32(16#65517f46),
       bin32(16#5eea049d), bin32(16#8c355d01), bin32(16#877473fa), bin32(16#0b412efb),
       bin32(16#671d5ab3), bin32(16#dbd25292), bin32(16#105633e9), bin32(16#d647136d),
       bin32(16#d7618c9a), bin32(16#a10c7a37), bin32(16#f8148e59), bin32(16#133c89eb),
       bin32(16#a927eece), bin32(16#61c935b7), bin32(16#1ce5ede1), bin32(16#47b13c7a),
       bin32(16#d2df599c), bin32(16#f2733f55), bin32(16#14ce7918), bin32(16#c737bf73),
       bin32(16#f7cdea53), bin32(16#fdaa5b5f), bin32(16#3d6f14df), bin32(16#44db8678),
       bin32(16#aff381ca), bin32(16#68c43eb9), bin32(16#24342c38), bin32(16#a3405fc2),
       bin32(16#1dc37216), bin32(16#e2250cbc), bin32(16#3c498b28), bin32(16#0d9541ff),
       bin32(16#a8017139), bin32(16#0cb3de08), bin32(16#b4e49cd8), bin32(16#56c19064),
       bin32(16#cb84617b), bin32(16#32b670d5), bin32(16#6c5c7448), bin32(16#b85742d0)),
  # Td[5]:
  [0] (bin32(16#52525252), bin32(16#09090909), bin32(16#6a6a6a6a), bin32(16#d5d5d5d5),
       bin32(16#30303030), bin32(16#36363636), bin32(16#a5a5a5a5), bin32(16#38383838),
       bin32(16#bfbfbfbf), bin32(16#40404040), bin32(16#a3a3a3a3), bin32(16#9e9e9e9e),
       bin32(16#81818181), bin32(16#f3f3f3f3), bin32(16#d7d7d7d7), bin32(16#fbfbfbfb),
       bin32(16#7c7c7c7c), bin32(16#e3e3e3e3), bin32(16#39393939), bin32(16#82828282),
       bin32(16#9b9b9b9b), bin32(16#2f2f2f2f), bin32(16#ffffffff), bin32(16#87878787),
       bin32(16#34343434), bin32(16#8e8e8e8e), bin32(16#43434343), bin32(16#44444444),
       bin32(16#c4c4c4c4), bin32(16#dededede), bin32(16#e9e9e9e9), bin32(16#cbcbcbcb),
       bin32(16#54545454), bin32(16#7b7b7b7b), bin32(16#94949494), bin32(16#32323232),
       bin32(16#a6a6a6a6), bin32(16#c2c2c2c2), bin32(16#23232323), bin32(16#3d3d3d3d),
       bin32(16#eeeeeeee), bin32(16#4c4c4c4c), bin32(16#95959595), bin32(16#0b0b0b0b),
       bin32(16#42424242), bin32(16#fafafafa), bin32(16#c3c3c3c3), bin32(16#4e4e4e4e),
       bin32(16#08080808), bin32(16#2e2e2e2e), bin32(16#a1a1a1a1), bin32(16#66666666),
       bin32(16#28282828), bin32(16#d9d9d9d9), bin32(16#24242424), bin32(16#b2b2b2b2),
       bin32(16#76767676), bin32(16#5b5b5b5b), bin32(16#a2a2a2a2), bin32(16#49494949),
       bin32(16#6d6d6d6d), bin32(16#8b8b8b8b), bin32(16#d1d1d1d1), bin32(16#25252525),
       bin32(16#72727272), bin32(16#f8f8f8f8), bin32(16#f6f6f6f6), bin32(16#64646464),
       bin32(16#86868686), bin32(16#68686868), bin32(16#98989898), bin32(16#16161616),
       bin32(16#d4d4d4d4), bin32(16#a4a4a4a4), bin32(16#5c5c5c5c), bin32(16#cccccccc),
       bin32(16#5d5d5d5d), bin32(16#65656565), bin32(16#b6b6b6b6), bin32(16#92929292),
       bin32(16#6c6c6c6c), bin32(16#70707070), bin32(16#48484848), bin32(16#50505050),
       bin32(16#fdfdfdfd), bin32(16#edededed), bin32(16#b9b9b9b9), bin32(16#dadadada),
       bin32(16#5e5e5e5e), bin32(16#15151515), bin32(16#46464646), bin32(16#57575757),
       bin32(16#a7a7a7a7), bin32(16#8d8d8d8d), bin32(16#9d9d9d9d), bin32(16#84848484),
       bin32(16#90909090), bin32(16#d8d8d8d8), bin32(16#abababab), bin32(16#00000000),
       bin32(16#8c8c8c8c), bin32(16#bcbcbcbc), bin32(16#d3d3d3d3), bin32(16#0a0a0a0a),
       bin32(16#f7f7f7f7), bin32(16#e4e4e4e4), bin32(16#58585858), bin32(16#05050505),
       bin32(16#b8b8b8b8), bin32(16#b3b3b3b3), bin32(16#45454545), bin32(16#06060606),
       bin32(16#d0d0d0d0), bin32(16#2c2c2c2c), bin32(16#1e1e1e1e), bin32(16#8f8f8f8f),
       bin32(16#cacacaca), bin32(16#3f3f3f3f), bin32(16#0f0f0f0f), bin32(16#02020202),
       bin32(16#c1c1c1c1), bin32(16#afafafaf), bin32(16#bdbdbdbd), bin32(16#03030303),
       bin32(16#01010101), bin32(16#13131313), bin32(16#8a8a8a8a), bin32(16#6b6b6b6b),
       bin32(16#3a3a3a3a), bin32(16#91919191), bin32(16#11111111), bin32(16#41414141),
       bin32(16#4f4f4f4f), bin32(16#67676767), bin32(16#dcdcdcdc), bin32(16#eaeaeaea),
       bin32(16#97979797), bin32(16#f2f2f2f2), bin32(16#cfcfcfcf), bin32(16#cececece),
       bin32(16#f0f0f0f0), bin32(16#b4b4b4b4), bin32(16#e6e6e6e6), bin32(16#73737373),
       bin32(16#96969696), bin32(16#acacacac), bin32(16#74747474), bin32(16#22222222),
       bin32(16#e7e7e7e7), bin32(16#adadadad), bin32(16#35353535), bin32(16#85858585),
       bin32(16#e2e2e2e2), bin32(16#f9f9f9f9), bin32(16#37373737), bin32(16#e8e8e8e8),
       bin32(16#1c1c1c1c), bin32(16#75757575), bin32(16#dfdfdfdf), bin32(16#6e6e6e6e),
       bin32(16#47474747), bin32(16#f1f1f1f1), bin32(16#1a1a1a1a), bin32(16#71717171),
       bin32(16#1d1d1d1d), bin32(16#29292929), bin32(16#c5c5c5c5), bin32(16#89898989),
       bin32(16#6f6f6f6f), bin32(16#b7b7b7b7), bin32(16#62626262), bin32(16#0e0e0e0e),
       bin32(16#aaaaaaaa), bin32(16#18181818), bin32(16#bebebebe), bin32(16#1b1b1b1b),
       bin32(16#fcfcfcfc), bin32(16#56565656), bin32(16#3e3e3e3e), bin32(16#4b4b4b4b),
       bin32(16#c6c6c6c6), bin32(16#d2d2d2d2), bin32(16#79797979), bin32(16#20202020),
       bin32(16#9a9a9a9a), bin32(16#dbdbdbdb), bin32(16#c0c0c0c0), bin32(16#fefefefe),
       bin32(16#78787878), bin32(16#cdcdcdcd), bin32(16#5a5a5a5a), bin32(16#f4f4f4f4),
       bin32(16#1f1f1f1f), bin32(16#dddddddd), bin32(16#a8a8a8a8), bin32(16#33333333),
       bin32(16#88888888), bin32(16#07070707), bin32(16#c7c7c7c7), bin32(16#31313131),
       bin32(16#b1b1b1b1), bin32(16#12121212), bin32(16#10101010), bin32(16#59595959),
       bin32(16#27272727), bin32(16#80808080), bin32(16#ecececec), bin32(16#5f5f5f5f),
       bin32(16#60606060), bin32(16#51515151), bin32(16#7f7f7f7f), bin32(16#a9a9a9a9),
       bin32(16#19191919), bin32(16#b5b5b5b5), bin32(16#4a4a4a4a), bin32(16#0d0d0d0d),
       bin32(16#2d2d2d2d), bin32(16#e5e5e5e5), bin32(16#7a7a7a7a), bin32(16#9f9f9f9f),
       bin32(16#93939393), bin32(16#c9c9c9c9), bin32(16#9c9c9c9c), bin32(16#efefefef),
       bin32(16#a0a0a0a0), bin32(16#e0e0e0e0), bin32(16#3b3b3b3b), bin32(16#4d4d4d4d),
       bin32(16#aeaeaeae), bin32(16#2a2a2a2a), bin32(16#f5f5f5f5), bin32(16#b0b0b0b0),
       bin32(16#c8c8c8c8), bin32(16#ebebebeb), bin32(16#bbbbbbbb), bin32(16#3c3c3c3c),
       bin32(16#83838383), bin32(16#53535353), bin32(16#99999999), bin32(16#61616161),
       bin32(16#17171717), bin32(16#2b2b2b2b), bin32(16#04040404), bin32(16#7e7e7e7e),
       bin32(16#babababa), bin32(16#77777777), bin32(16#d6d6d6d6), bin32(16#26262626),
       bin32(16#e1e1e1e1), bin32(16#69696969), bin32(16#14141414), bin32(16#63636363),
       bin32(16#55555555), bin32(16#21212121), bin32(16#0c0c0c0c), bin32(16#7d7d7d7d)));


const array bin32: rcon is [] (
    # For 128-bit blocks, Rijndael never uses more than 10 rcon values.
    # For 192- and 256-bit blocks the maximum index to rcon is 8 and 7.
    bin32(16#01000000), bin32(16#02000000), bin32(16#04000000), bin32(16#08000000),
    bin32(16#10000000), bin32(16#20000000), bin32(16#40000000), bin32(16#80000000),
    bin32(16#1B000000), bin32(16#36000000));


const proc: expandAesKey128 (inout array bin32: subKey) is func
  local
    var integer: rconIdx is 0;
    var integer: keyIdx is 1;
    var integer: temp is 0;
  begin
    for rconIdx range 1 to 10 do
      temp := ord(subKey[keyIdx + 3]);
      subKey[keyIdx + 4] := subKey[keyIdx + 0] ><
          (Te[5][(temp >> 16) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(temp >>  8) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][ temp        mod 256] & bin32(16#0000ff00)) ><
          (Te[5][(temp >> 24) mod 256] & bin32(16#000000ff)) ><
          rcon[rconIdx];
      subKey[keyIdx + 5] := subKey[keyIdx + 1] >< subKey[keyIdx + 4];
      subKey[keyIdx + 6] := subKey[keyIdx + 2] >< subKey[keyIdx + 5];
      subKey[keyIdx + 7] := subKey[keyIdx + 3] >< subKey[keyIdx + 6];
      keyIdx +:= 4;
    end for;
  end func;


const proc: expandAesKey192 (inout array bin32: subKey) is func
  local
    var integer: rconIdx is 0;
    var integer: keyIdx is 1;
    var integer: temp is 0;
  begin
    for rconIdx range 1 to 8 do
      temp := ord(subKey[keyIdx + 5]);
      subKey[keyIdx + 6] := subKey[keyIdx + 0] ><
          (Te[5][(temp >> 16) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(temp >>  8) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][ temp        mod 256] & bin32(16#0000ff00)) ><
          (Te[5][(temp >> 24) mod 256] & bin32(16#000000ff)) ><
          rcon[rconIdx];
      subKey[keyIdx + 7] := subKey[keyIdx + 1] >< subKey[keyIdx + 6];
      subKey[keyIdx + 8] := subKey[keyIdx + 2] >< subKey[keyIdx + 7];
      subKey[keyIdx + 9] := subKey[keyIdx + 3] >< subKey[keyIdx + 8];
      if rconIdx <> 8 then
        subKey[keyIdx + 10] := subKey[keyIdx + 4] >< subKey[keyIdx +  9];
        subKey[keyIdx + 11] := subKey[keyIdx + 5] >< subKey[keyIdx + 10];
        keyIdx +:= 6;
      end if;
    end for;
  end func;


const proc: expandAesKey256 (inout array bin32: subKey) is func
  local
    var integer: rconIdx is 0;
    var integer: keyIdx is 1;
    var integer: temp is 0;
  begin
    for rconIdx range 1 to 7 do
      temp := ord(subKey[keyIdx + 7]);
      subKey[keyIdx + 8] := subKey[keyIdx + 0] ><
          (Te[5][(temp >> 16) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(temp >>  8) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][ temp        mod 256] & bin32(16#0000ff00)) ><
          (Te[5][(temp >> 24) mod 256] & bin32(16#000000ff)) ><
          rcon[rconIdx];
      subKey[keyIdx +  9] := subKey[keyIdx + 1] >< subKey[keyIdx +  8];
      subKey[keyIdx + 10] := subKey[keyIdx + 2] >< subKey[keyIdx +  9];
      subKey[keyIdx + 11] := subKey[keyIdx + 3] >< subKey[keyIdx + 10];
      if rconIdx <> 7 then
        temp := ord(subKey[keyIdx + 11]);
        subKey[keyIdx + 12] := subKey[keyIdx + 4] ><
            (Te[5][(temp >> 24) mod 256] & bin32(16#ff000000)) ><
            (Te[5][(temp >> 16) mod 256] & bin32(16#00ff0000)) ><
            (Te[5][(temp >>  8) mod 256] & bin32(16#0000ff00)) ><
            (Te[5][ temp        mod 256] & bin32(16#000000ff));
        subKey[keyIdx + 13] := subKey[keyIdx + 5] >< subKey[keyIdx + 12];
        subKey[keyIdx + 14] := subKey[keyIdx + 6] >< subKey[keyIdx + 13];
        subKey[keyIdx + 15] := subKey[keyIdx + 7] >< subKey[keyIdx + 14];
        keyIdx +:= 8;
      end if;
    end for;
  end func;


const func array bin32: setAesKey (in string: aesKey) is func
  result
    var array bin32: encryptKey is 0 times bin32.value;
  local
    var integer: encryptKeyLength is 0;
    var integer: keyIdx is 0;
  begin
    case length(aesKey) of
      when {16}: encryptKeyLength := 44;
      when {24}: encryptKeyLength := 52;
      when {32}: encryptKeyLength := 60;
      otherwise: raise RANGE_ERROR;
    end case;
    encryptKey := encryptKeyLength times bin32.value;
    for keyIdx range 1 to length(aesKey) mdiv 4 do
      encryptKey[keyIdx] := bin32(bytes2Int(aesKey[4 * keyIdx - 3 fixLen 4], UNSIGNED, BE));
    end for;
    case length(aesKey) of
      when {16}: expandAesKey128(encryptKey);
      when {24}: expandAesKey192(encryptKey);
      when {32}: expandAesKey256(encryptKey);
    end case;
  end func;


const func array bin32: genAesDecryptKey (in array bin32: encryptKey, in integer: rounds) is func
  result
    var array bin32: decryptKey is 0 times bin32.value;
  local
    var bin32: temp is bin32.value;
    var integer: idx is 0;
    var integer: j is 0;
    var integer: keyIdx is 1;
  begin
    decryptKey := encryptKey;
    # Invert the order of the round keys:
    j := 4 * rounds + 2;
    for idx range 1 to 2 * rounds step 4 do
      temp := decryptKey[idx    ]; decryptKey[idx    ] := decryptKey[j - idx    ]; decryptKey[j - idx    ] := temp;
      temp := decryptKey[idx + 1]; decryptKey[idx + 1] := decryptKey[j - idx + 1]; decryptKey[j - idx + 1] := temp;
      temp := decryptKey[idx + 2]; decryptKey[idx + 2] := decryptKey[j - idx + 2]; decryptKey[j - idx + 2] := temp;
      temp := decryptKey[idx + 3]; decryptKey[idx + 3] := decryptKey[j - idx + 3]; decryptKey[j - idx + 3] := temp;
    end for;
    # Apply the inverse MixColumn transform to all round keys but the first and the last:
    for idx range 1 to pred(rounds) do
      keyIdx +:= 4;
      decryptKey[keyIdx    ] := Td[1][ord(Te[5][(ord(decryptKey[keyIdx    ]) >> 24) mod 256]) mod 256] ><
                                Td[2][ord(Te[5][(ord(decryptKey[keyIdx    ]) >> 16) mod 256]) mod 256] ><
                                Td[3][ord(Te[5][(ord(decryptKey[keyIdx    ]) >>  8) mod 256]) mod 256] ><
                                Td[4][ord(Te[5][ ord(decryptKey[keyIdx    ])        mod 256]) mod 256];
      decryptKey[keyIdx + 1] := Td[1][ord(Te[5][(ord(decryptKey[keyIdx + 1]) >> 24) mod 256]) mod 256] ><
                                Td[2][ord(Te[5][(ord(decryptKey[keyIdx + 1]) >> 16) mod 256]) mod 256] ><
                                Td[3][ord(Te[5][(ord(decryptKey[keyIdx + 1]) >>  8) mod 256]) mod 256] ><
                                Td[4][ord(Te[5][ ord(decryptKey[keyIdx + 1])        mod 256]) mod 256];
      decryptKey[keyIdx + 2] := Td[1][ord(Te[5][(ord(decryptKey[keyIdx + 2]) >> 24) mod 256]) mod 256] ><
                                Td[2][ord(Te[5][(ord(decryptKey[keyIdx + 2]) >> 16) mod 256]) mod 256] ><
                                Td[3][ord(Te[5][(ord(decryptKey[keyIdx + 2]) >>  8) mod 256]) mod 256] ><
                                Td[4][ord(Te[5][ ord(decryptKey[keyIdx + 2])        mod 256]) mod 256];
      decryptKey[keyIdx + 3] := Td[1][ord(Te[5][(ord(decryptKey[keyIdx + 3]) >> 24) mod 256]) mod 256] ><
                                Td[2][ord(Te[5][(ord(decryptKey[keyIdx + 3]) >> 16) mod 256]) mod 256] ><
                                Td[3][ord(Te[5][(ord(decryptKey[keyIdx + 3]) >>  8) mod 256]) mod 256] ><
                                Td[4][ord(Te[5][ ord(decryptKey[keyIdx + 3])        mod 256]) mod 256];
    end for;
  end func;


(**
 *  Set key and initialization vector for the AES (Advanced Encryption Standard) block cipher.
 *  @param aesKey The key to be used for AES.
 *  @param initializationVector The initialisation vector (IV) for AES.
 *  @return the AES (Advanced Encryption Standard) cipher state.
 *)
const func aesState: setAesKey (in string: aesKey, in string: initializationVector) is func
  result
    var aesState: state is aesState.value;
  begin
    state.rounds := length(aesKey) mdiv 4 + 6;
    state.encryptionSubKey := setAesKey(aesKey);
    state.decryptionSubKey := genAesDecryptKey(state.encryptionSubKey, state.rounds);
    state.cipherBlock := initializationVector;
  end func;


(**
 *  Set key and initialization vector for the AES (Advanced Encryption Standard) block cipher.
 *  @param cipherKey The key to be used for AES.
 *  @param initializationVector The initialisation vector (IV) for AES.
 *  @return the initial ''cipherState'' of a AES cipher.
 *)
const func cipherState: setCipherKey (AES, in string: cipherKey,
    in string: initializationVector) is
  return toInterface(setAesKey(cipherKey, initializationVector));


const func string: encodeAesBlock (in array bin32: subKey, in integer: rounds, in string: inData) is func
  result
    var string: outData is "";
  local
    var bin32: s1 is bin32.value;
    var bin32: s2 is bin32.value;
    var bin32: s3 is bin32.value;
    var bin32: s4 is bin32.value;
    var bin32: t1 is bin32.value;
    var bin32: t2 is bin32.value;
    var bin32: t3 is bin32.value;
    var bin32: t4 is bin32.value;
    var integer: keyIdx is 1;
    var integer: countRounds is 0;
  begin
    # Map byte array block to cipher state and add initial round key:
    s1 := bin32(bytes2Int(inData[ 1 fixLen 4], UNSIGNED, BE)) >< subKey[1];
    s2 := bin32(bytes2Int(inData[ 5 fixLen 4], UNSIGNED, BE)) >< subKey[2];
    s3 := bin32(bytes2Int(inData[ 9 fixLen 4], UNSIGNED, BE)) >< subKey[3];
    s4 := bin32(bytes2Int(inData[13 fixLen 4], UNSIGNED, BE)) >< subKey[4];

    # Full rounds except last round:
    countRounds := rounds mdiv 2;
    repeat
      t1 := Te[1][(ord(s1) >> 24) mod 256] ><
            Te[2][(ord(s2) >> 16) mod 256] ><
            Te[3][(ord(s3) >>  8) mod 256] ><
            Te[4][ ord(s4)        mod 256] ><
            subKey[keyIdx + 4];
      t2 := Te[1][(ord(s2) >> 24) mod 256] ><
            Te[2][(ord(s3) >> 16) mod 256] ><
            Te[3][(ord(s4) >>  8) mod 256] ><
            Te[4][ ord(s1)        mod 256] ><
            subKey[keyIdx + 5];
      t3 := Te[1][(ord(s3) >> 24) mod 256] ><
            Te[2][(ord(s4) >> 16) mod 256] ><
            Te[3][(ord(s1) >>  8) mod 256] ><
            Te[4][ ord(s2)        mod 256] ><
            subKey[keyIdx + 6];
      t4 := Te[1][(ord(s4) >> 24) mod 256] ><
            Te[2][(ord(s1) >> 16) mod 256] ><
            Te[3][(ord(s2) >>  8) mod 256] ><
            Te[4][ ord(s3)        mod 256] ><
            subKey[keyIdx + 7];
      keyIdx +:= 8;
      decr(countRounds);
      if countRounds <> 0 then
        s1 := Te[1][(ord(t1) >> 24) mod 256] ><
              Te[2][(ord(t2) >> 16) mod 256] ><
              Te[3][(ord(t3) >>  8) mod 256] ><
              Te[4][ ord(t4)        mod 256] ><
              subKey[keyIdx];
        s2 := Te[1][(ord(t2) >> 24) mod 256] ><
              Te[2][(ord(t3) >> 16) mod 256] ><
              Te[3][(ord(t4) >>  8) mod 256] ><
              Te[4][ ord(t1)        mod 256] ><
              subKey[keyIdx + 1];
        s3 := Te[1][(ord(t3) >> 24) mod 256] ><
              Te[2][(ord(t4) >> 16) mod 256] ><
              Te[3][(ord(t1) >>  8) mod 256] ><
              Te[4][ ord(t2)        mod 256] ><
              subKey[keyIdx + 2];
        s4 := Te[1][(ord(t4) >> 24) mod 256] ><
              Te[2][(ord(t1) >> 16) mod 256] ><
              Te[3][(ord(t2) >>  8) mod 256] ><
              Te[4][ ord(t3)        mod 256] ><
              subKey[keyIdx + 3];
      end if;
    until countRounds = 0;

    # Last round:
    s1 := (Te[5][(ord(t1) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(ord(t2) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][(ord(t3) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Te[5][ ord(t4)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx];
    s2 := (Te[5][(ord(t2) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(ord(t3) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][(ord(t4) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Te[5][ ord(t1)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 1];
    s3 := (Te[5][(ord(t3) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(ord(t4) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][(ord(t1) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Te[5][ ord(t2)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 2];
    s4 := (Te[5][(ord(t4) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Te[5][(ord(t1) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Te[5][(ord(t2) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Te[5][ ord(t3)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 3];

    # Map cipher state to byte array block:
    outData := bytes(ord(s1), UNSIGNED, BE, 4) &
               bytes(ord(s2), UNSIGNED, BE, 4) &
               bytes(ord(s3), UNSIGNED, BE, 4) &
               bytes(ord(s4), UNSIGNED, BE, 4);
  end func;


const func string: decodeAesBlock (in array bin32: subKey, in integer: rounds, in string: inData) is func
  result
    var string: outData is "";
  local
    var bin32: s1 is bin32.value;
    var bin32: s2 is bin32.value;
    var bin32: s3 is bin32.value;
    var bin32: s4 is bin32.value;
    var bin32: t1 is bin32.value;
    var bin32: t2 is bin32.value;
    var bin32: t3 is bin32.value;
    var bin32: t4 is bin32.value;
    var integer: keyIdx is 1;
    var integer: countRounds is 0;
  begin
    # Map byte array block to cipher state and add initial round key:
    s1 := bin32(bytes2Int(inData[ 1 fixLen 4], UNSIGNED, BE)) >< subKey[1];
    s2 := bin32(bytes2Int(inData[ 5 fixLen 4], UNSIGNED, BE)) >< subKey[2];
    s3 := bin32(bytes2Int(inData[ 9 fixLen 4], UNSIGNED, BE)) >< subKey[3];
    s4 := bin32(bytes2Int(inData[13 fixLen 4], UNSIGNED, BE)) >< subKey[4];

    # Full rounds except last round:
    countRounds := rounds mdiv 2;
    repeat
      t1 := Td[1][(ord(s1) >> 24) mod 256] ><
            Td[2][(ord(s4) >> 16) mod 256] ><
            Td[3][(ord(s3) >>  8) mod 256] ><
            Td[4][ ord(s2)        mod 256] ><
            subKey[keyIdx + 4];
      t2 := Td[1][(ord(s2) >> 24) mod 256] ><
            Td[2][(ord(s1) >> 16) mod 256] ><
            Td[3][(ord(s4) >>  8) mod 256] ><
            Td[4][ ord(s3)        mod 256] ><
            subKey[keyIdx + 5];
      t3 := Td[1][(ord(s3) >> 24) mod 256] ><
            Td[2][(ord(s2) >> 16) mod 256] ><
            Td[3][(ord(s1) >>  8) mod 256] ><
            Td[4][ ord(s4)        mod 256] ><
            subKey[keyIdx + 6];
      t4 := Td[1][(ord(s4) >> 24) mod 256] ><
            Td[2][(ord(s3) >> 16) mod 256] ><
            Td[3][(ord(s2) >>  8) mod 256] ><
            Td[4][ ord(s1)        mod 256] ><
            subKey[keyIdx + 7];
      keyIdx +:= 8;
      decr(countRounds);
      if countRounds <> 0 then
        s1 := Td[1][(ord(t1) >> 24) mod 256] ><
              Td[2][(ord(t4) >> 16) mod 256] ><
              Td[3][(ord(t3) >>  8) mod 256] ><
              Td[4][ ord(t2)        mod 256] ><
              subKey[keyIdx + 0];
        s2 := Td[1][(ord(t2) >> 24) mod 256] ><
              Td[2][(ord(t1) >> 16) mod 256] ><
              Td[3][(ord(t4) >>  8) mod 256] ><
              Td[4][ ord(t3)        mod 256] ><
              subKey[keyIdx + 1];
        s3 := Td[1][(ord(t3) >> 24) mod 256] ><
              Td[2][(ord(t2) >> 16) mod 256] ><
              Td[3][(ord(t1) >>  8) mod 256] ><
              Td[4][ ord(t4)        mod 256] ><
              subKey[keyIdx + 2];
        s4 := Td[1][(ord(t4) >> 24) mod 256] ><
              Td[2][(ord(t3) >> 16) mod 256] ><
              Td[3][(ord(t2) >>  8) mod 256] ><
              Td[4][ ord(t1)        mod 256] ><
              subKey[keyIdx + 3];
      end if;
    until countRounds = 0;

    # Last round:
    s1 := (Td[5][(ord(t1) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Td[5][(ord(t4) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Td[5][(ord(t3) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Td[5][ ord(t2)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 0];
    s2 := (Td[5][(ord(t2) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Td[5][(ord(t1) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Td[5][(ord(t4) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Td[5][ ord(t3)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 1];
    s3 := (Td[5][(ord(t3) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Td[5][(ord(t2) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Td[5][(ord(t1) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Td[5][ ord(t4)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 2];
    s4 := (Td[5][(ord(t4) >> 24) mod 256] & bin32(16#ff000000)) ><
          (Td[5][(ord(t3) >> 16) mod 256] & bin32(16#00ff0000)) ><
          (Td[5][(ord(t2) >>  8) mod 256] & bin32(16#0000ff00)) ><
          (Td[5][ ord(t1)        mod 256] & bin32(16#000000ff)) ><
          subKey[keyIdx + 3];

    # Map cipher state to byte array block:
    outData := bytes(ord(s1), UNSIGNED, BE, 4) &
               bytes(ord(s2), UNSIGNED, BE, 4) &
               bytes(ord(s3), UNSIGNED, BE, 4) &
               bytes(ord(s4), UNSIGNED, BE, 4);
  end func;


(**
 *  Encode a string with the AES (Advanced Encryption Standard) block cipher.
 *  @return the encoded string.
 *)
const func string: encode (inout aesState: state, in string: plaintext) is func
  result
    var string: encoded is "";
  local
    var integer: index is 0;
    var integer: subIndex is 0;
    var string: dataBlock is "";
    var string: cipherBlock is "";
  begin
    for index range 1 to length(plaintext) step blockSize(AES) do
      dataBlock := "";
      for subIndex range 1 to blockSize(AES) do
        dataBlock &:= chr(ord(bin32(plaintext[pred(index + subIndex)]) ><
                              bin32(state.cipherBlock[subIndex])));
      end for;
      cipherBlock := encodeAesBlock(state.encryptionSubKey, state.rounds, dataBlock);
      state.cipherBlock := cipherBlock;
      encoded &:= cipherBlock;
    end for;
  end func;


(**
 *  Decode a string with the AES (Advanced Encryption Standard) block cipher.
 *  @return the decoded string.
 *)
const func string: decode (inout aesState: state, in string: encoded) is func
  result
    var string: plaintext is "";
  local
    var integer: index is 0;
    var integer: subIndex is 0;
    var string: cipherBlock is "";
    var string: dataBlock is "";
    var string: plainBlock is "";
  begin
    for index range 1 to length(encoded) step blockSize(AES) do
      cipherBlock := encoded[index fixLen blockSize(AES)];
      dataBlock := decodeAesBlock(state.decryptionSubKey, state.rounds, cipherBlock);
      for subIndex range 1 to blockSize(AES) do
        plaintext &:= chr(ord(bin32(dataBlock[subIndex]) ><
                              bin32(state.cipherBlock[subIndex])));
      end for;
      state.cipherBlock := cipherBlock;
    end for;
  end func;