/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include "aes_impl.h" #ifndef _KERNEL #include #include #endif /* !_KERNEL */ #ifdef __amd64 #ifdef _KERNEL #include /* cpu_t, CPU */ #include /* x86_featureset, X86FSET_AES */ #include /* kpreempt_disable(), kpreempt_enable */ /* Workaround for no XMM kernel thread save/restore */ #define KPREEMPT_DISABLE kpreempt_disable() #define KPREEMPT_ENABLE kpreempt_enable() #else #include /* getisax() */ #include /* AV_386_AES bit */ #define KPREEMPT_DISABLE #define KPREEMPT_ENABLE #endif /* _KERNEL */ #endif /* __amd64 */ /* * This file is derived from the file rijndael-alg-fst.c taken from the * "optimized C code v3.0" on the "rijndael home page" * http://www.iaik.tu-graz.ac.at/research/krypto/AES/old/~rijmen/rijndael/ * pointed by the NIST web-site http://csrc.nist.gov/archive/aes/ * * The following note is from the original file: */ /* * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(sun4u) /* External assembly functions: */ extern void aes_encrypt_impl(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4]); extern void aes_decrypt_impl(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]); #define AES_ENCRYPT_IMPL(a, b, c, d, e) aes_encrypt_impl(a, b, c, d) #define AES_DECRYPT_IMPL(a, b, c, d, e) aes_decrypt_impl(a, b, c, d) #elif defined(__amd64) /* These functions are used to execute amd64 instructions for AMD or Intel: */ extern int rijndael_key_setup_enc_amd64(uint32_t rk[], const uint32_t cipherKey[], int keyBits); extern int rijndael_key_setup_dec_amd64(uint32_t rk[], const uint32_t cipherKey[], int keyBits); extern void aes_encrypt_amd64(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4]); extern void aes_decrypt_amd64(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]); /* These functions are used to execute Intel-specific AES-NI instructions: */ extern int rijndael_key_setup_enc_intel(uint32_t rk[], const uint32_t cipherKey[], uint64_t keyBits); extern int rijndael_key_setup_dec_intel(uint32_t rk[], const uint32_t cipherKey[], uint64_t keyBits); extern void aes_encrypt_intel(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4]); extern void aes_decrypt_intel(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]); static int intel_aes_instructions_present(void); #define AES_ENCRYPT_IMPL(a, b, c, d, e) rijndael_encrypt(a, b, c, d, e) #define AES_DECRYPT_IMPL(a, b, c, d, e) rijndael_decrypt(a, b, c, d, e) #else /* Generic C implementation */ #define AES_ENCRYPT_IMPL(a, b, c, d, e) rijndael_encrypt(a, b, c, d) #define AES_DECRYPT_IMPL(a, b, c, d, e) rijndael_decrypt(a, b, c, d) #define rijndael_key_setup_enc_raw rijndael_key_setup_enc #endif /* sun4u || __amd64 */ #if defined(_LITTLE_ENDIAN) && !defined(__amd64) #define AES_BYTE_SWAP #endif #if !defined(__amd64) /* * Constant tables */ /* * Te0[x] = S [x].[02, 01, 01, 03]; * Te1[x] = S [x].[03, 02, 01, 01]; * Te2[x] = S [x].[01, 03, 02, 01]; * Te3[x] = S [x].[01, 01, 03, 02]; * Te4[x] = S [x].[01, 01, 01, 01]; * * Td0[x] = Si[x].[0e, 09, 0d, 0b]; * Td1[x] = Si[x].[0b, 0e, 09, 0d]; * Td2[x] = Si[x].[0d, 0b, 0e, 09]; * Td3[x] = Si[x].[09, 0d, 0b, 0e]; * Td4[x] = Si[x].[01, 01, 01, 01]; */ /* Encrypt Sbox constants (for the substitute bytes operation) */ #ifndef sun4u static const uint32_t Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU }; static const uint32_t Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U }; static const uint32_t Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U }; static const uint32_t Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU }; #endif /* !sun4u */ static const uint32_t Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U }; /* Decrypt Sbox constants (for the substitute bytes operation) */ static const uint32_t Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U }; static const uint32_t Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U }; static const uint32_t Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U }; static const uint32_t Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U }; #ifndef sun4u static const uint32_t Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU }; #endif /* !sun4u */ /* Rcon is Round Constant; used for encryption key expansion */ static const uint32_t rcon[RC_LENGTH] = { /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 }; /* * Expand the cipher key into the encryption key schedule. * * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk AES key schedule 32-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ static int rijndael_key_setup_enc_raw(uint32_t rk[], const uint32_t cipherKey[], int keyBits) { int i = 0; uint32_t temp; rk[0] = cipherKey[0]; rk[1] = cipherKey[1]; rk[2] = cipherKey[2]; rk[3] = cipherKey[3]; if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[temp & 0xff] & 0x0000ff00) ^ (Te4[temp >> 24] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return (10); } rk += 4; } } rk[4] = cipherKey[4]; rk[5] = cipherKey[5]; if (keyBits == 192) { for (;;) { temp = rk[5]; rk[6] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[temp & 0xff] & 0x0000ff00) ^ (Te4[temp >> 24] & 0x000000ff) ^ rcon[i]; rk[7] = rk[1] ^ rk[6]; rk[8] = rk[2] ^ rk[7]; rk[9] = rk[3] ^ rk[8]; if (++i == 8) { return (12); } rk[10] = rk[4] ^ rk[9]; rk[11] = rk[5] ^ rk[10]; rk += 6; } } rk[6] = cipherKey[6]; rk[7] = cipherKey[7]; if (keyBits == 256) { for (;;) { temp = rk[7]; rk[8] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[temp & 0xff] & 0x0000ff00) ^ (Te4[temp >> 24] & 0x000000ff) ^ rcon[i]; rk[9] = rk[1] ^ rk[8]; rk[10] = rk[2] ^ rk[9]; rk[11] = rk[3] ^ rk[10]; if (++i == 7) { return (14); } temp = rk[11]; rk[12] = rk[4] ^ (Te4[temp >> 24] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te4[temp & 0xff] & 0x000000ff); rk[13] = rk[5] ^ rk[12]; rk[14] = rk[6] ^ rk[13]; rk[15] = rk[7] ^ rk[14]; rk += 8; } } return (0); } #endif /* !__amd64 */ #ifdef sun4u /* * Expand the cipher key into the encryption key schedule. * by the sun4u optimized assembly implementation. * * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk AES key schedule 64-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ static int rijndael_key_setup_enc(uint64_t rk[], const uint32_t cipherKey[], int keyBits) { uint32_t rk1[4 * (MAX_AES_NR + 1)]; uint64_t *rk64 = (uint64_t *)rk; uint32_t *rkt; uint64_t t; int i, Nr; Nr = rijndael_key_setup_enc_raw(rk1, cipherKey, keyBits); for (i = 0; i < 4 * Nr; i++) { t = (uint64_t)(rk1[i]); rk64[i] = ((t & 0xff000000) << 11) | ((t & 0xff0000) << 8) | ((t & 0xffff) << 3); } rkt = (uint32_t *)(&(rk64[4 * Nr])); for (i = 0; i < 4; i++) { rkt[i] = rk1[4 * Nr+i]; } return (Nr); } /* * Expand the cipher key into the decryption key schedule as used * by the sun4u optimized assembly implementation. * * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk AES key schedule 32-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ static int rijndael_key_setup_dec_raw(uint32_t rk[], const uint32_t cipherKey[], int keyBits) { int Nr, i; uint32_t temp; /* expand the cipher key: */ Nr = rijndael_key_setup_enc_raw(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0; i < 2 * Nr + 2; i++) { temp = rk[i]; rk[i] = rk[4 * Nr - i + 3]; rk[4 * Nr - i + 3] = temp; } /* * apply the inverse MixColumn transform to all * round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[rk[0] >> 24] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[0] & 0xff] & 0xff]; rk[1] = Td0[Te4[rk[1] >> 24] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[1] & 0xff] & 0xff]; rk[2] = Td0[Te4[rk[2] >> 24] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[2] & 0xff] & 0xff]; rk[3] = Td0[Te4[rk[3] >> 24] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[3] & 0xff] & 0xff]; } return (Nr); } /* * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk AES key schedule 64-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ static int rijndael_key_setup_dec(uint64_t rk[], const uint32_t cipherKey[], int keyBits) { uint32_t rk1[4 * (MAX_AES_NR + 1)]; uint64_t *rk64 = (uint64_t *)rk; uint32_t *rkt; uint64_t t; int i, Nr; Nr = rijndael_key_setup_dec_raw(rk1, cipherKey, keyBits); for (i = 0; i < 4 * Nr; i++) { t = (uint64_t)(rk1[i]); rk64[i] = ((t & 0xff000000) << 11) | ((t & 0xff0000) << 8) | ((t & 0xffff) << 3); } rkt = (uint32_t *)(&(rk64[4 * Nr])); for (i = 0; i < 4; i++) { rkt[i] = rk1[4 * Nr + i]; } return (Nr); } /* * Expand the 64-bit AES cipher key array into the encryption and decryption * key schedules. * * Parameters: * key AES key schedule to be initialized * keyarr32 User key * keyBits AES key size (128, 192, or 256 bits) */ static void aes_setupkeys(aes_key_t *key, const uint32_t *keyarr32, int keybits) { key->nr = rijndael_key_setup_enc(&(key->encr_ks.ks64[0]), keyarr32, keybits); key->nr = rijndael_key_setup_dec(&(key->decr_ks.ks64[0]), keyarr32, keybits); key->type = AES_64BIT_KS; } #elif defined(__amd64) /* * Expand the 32-bit AES cipher key array into the encryption and decryption * key schedules. * * Parameters: * key AES key schedule to be initialized * keyarr32 User key * keyBits AES key size (128, 192, or 256 bits) */ static void aes_setupkeys(aes_key_t *key, const uint32_t *keyarr32, int keybits) { if (intel_aes_instructions_present()) { key->flags = INTEL_AES_NI_CAPABLE; KPREEMPT_DISABLE; key->nr = rijndael_key_setup_enc_intel(&(key->encr_ks.ks32[0]), keyarr32, keybits); key->nr = rijndael_key_setup_dec_intel(&(key->decr_ks.ks32[0]), keyarr32, keybits); KPREEMPT_ENABLE; } else { key->flags = 0; key->nr = rijndael_key_setup_enc_amd64(&(key->encr_ks.ks32[0]), keyarr32, keybits); key->nr = rijndael_key_setup_dec_amd64(&(key->decr_ks.ks32[0]), keyarr32, keybits); } key->type = AES_32BIT_KS; } /* * Encrypt one block of data. The block is assumed to be an array * of four uint32_t values, so copy for alignment (and byte-order * reversal for little endian systems might be necessary on the * input and output byte streams. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk Key schedule, of aes_ks_t (60 32-bit integers) * Nr Number of rounds * pt Input block (plain text) * ct Output block (crypto text). Can overlap with pt * flags Indicates whether we're on Intel AES-NI-capable hardware */ static void rijndael_encrypt(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4], int flags) { if (flags & INTEL_AES_NI_CAPABLE) { KPREEMPT_DISABLE; aes_encrypt_intel(rk, Nr, pt, ct); KPREEMPT_ENABLE; } else { aes_encrypt_amd64(rk, Nr, pt, ct); } } /* * Decrypt one block of data. The block is assumed to be an array * of four uint32_t values, so copy for alignment (and byte-order * reversal for little endian systems might be necessary on the * input and output byte streams. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk Key schedule, of aes_ks_t (60 32-bit integers) * Nr Number of rounds * ct Input block (crypto text) * pt Output block (plain text). Can overlap with pt * flags Indicates whether we're on Intel AES-NI-capable hardware */ static void rijndael_decrypt(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4], int flags) { if (flags & INTEL_AES_NI_CAPABLE) { KPREEMPT_DISABLE; aes_decrypt_intel(rk, Nr, ct, pt); KPREEMPT_ENABLE; } else { aes_decrypt_amd64(rk, Nr, ct, pt); } } #else /* generic C implementation */ /* * Expand the cipher key into the decryption key schedule. * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk AES key schedule 32-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ static int rijndael_key_setup_dec(uint32_t rk[], const uint32_t cipherKey[], int keyBits) { int Nr, i, j; uint32_t temp; /* expand the cipher key: */ Nr = rijndael_key_setup_enc_raw(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0, j = 4 * Nr; i < j; i += 4, j -= 4) { temp = rk[i]; rk[i] = rk[j]; rk[j] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* * apply the inverse MixColumn transform to all * round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[rk[0] >> 24] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[0] & 0xff] & 0xff]; rk[1] = Td0[Te4[rk[1] >> 24] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[1] & 0xff] & 0xff]; rk[2] = Td0[Te4[rk[2] >> 24] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[2] & 0xff] & 0xff]; rk[3] = Td0[Te4[rk[3] >> 24] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te4[rk[3] & 0xff] & 0xff]; } return (Nr); } /* * Expand the 32-bit AES cipher key array into the encryption and decryption * key schedules. * * Parameters: * key AES key schedule to be initialized * keyarr32 User key * keyBits AES key size (128, 192, or 256 bits) */ static void aes_setupkeys(aes_key_t *key, const uint32_t *keyarr32, int keybits) { key->nr = rijndael_key_setup_enc(&(key->encr_ks.ks32[0]), keyarr32, keybits); key->nr = rijndael_key_setup_dec(&(key->decr_ks.ks32[0]), keyarr32, keybits); key->type = AES_32BIT_KS; } /* * Encrypt one block of data. The block is assumed to be an array * of four uint32_t values, so copy for alignment (and byte-order * reversal for little endian systems might be necessary on the * input and output byte streams. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk Key schedule, of aes_ks_t (60 32-bit integers) * Nr Number of rounds * pt Input block (plain text) * ct Output block (crypto text). Can overlap with pt */ static void rijndael_encrypt(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4]) { uint32_t s0, s1, s2, s3, t0, t1, t2, t3; int r; /* * map byte array block to cipher state * and add initial round key: */ s0 = pt[0] ^ rk[0]; s1 = pt[1] ^ rk[1]; s2 = pt[2] ^ rk[2]; s3 = pt[3] ^ rk[3]; /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[0]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[1]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[2]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[3]; } /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24)] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[t3 & 0xff] & 0x000000ff) ^ rk[0]; ct[0] = s0; s1 = (Te4[(t1 >> 24)] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[t0 & 0xff] & 0x000000ff) ^ rk[1]; ct[1] = s1; s2 = (Te4[(t2 >> 24)] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[t1 & 0xff] & 0x000000ff) ^ rk[2]; ct[2] = s2; s3 = (Te4[(t3 >> 24)] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[t2 & 0xff] & 0x000000ff) ^ rk[3]; ct[3] = s3; } /* * Decrypt one block of data. The block is assumed to be an array * of four uint32_t values, so copy for alignment (and byte-order * reversal for little endian systems might be necessary on the * input and output byte streams. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4*(Nr + 1). * * Parameters: * rk Key schedule, of aes_ks_t (60 32-bit integers) * Nr Number of rounds * ct Input block (crypto text) * pt Output block (plain text). Can overlap with pt */ static void rijndael_decrypt(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]) { uint32_t s0, s1, s2, s3, t0, t1, t2, t3; int r; /* * map byte array block to cipher state * and add initial round key: */ s0 = ct[0] ^ rk[0]; s1 = ct[1] ^ rk[1]; s2 = ct[2] ^ rk[2]; s3 = ct[3] ^ rk[3]; /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[4]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[5]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[6]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[0]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[1]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[2]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[3]; } /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[t0 >> 24] & 0xff000000) ^ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[t1 & 0xff] & 0x000000ff) ^ rk[0]; pt[0] = s0; s1 = (Td4[t1 >> 24] & 0xff000000) ^ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[t2 & 0xff] & 0x000000ff) ^ rk[1]; pt[1] = s1; s2 = (Td4[t2 >> 24] & 0xff000000) ^ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[t3 & 0xff] & 0x000000ff) ^ rk[2]; pt[2] = s2; s3 = (Td4[t3 >> 24] & 0xff000000) ^ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[t0 & 0xff] & 0x000000ff) ^ rk[3]; pt[3] = s3; } #endif /* sun4u, __amd64 */ /* * Initialize AES encryption and decryption key schedules. * * Parameters: * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) * keysched AES key schedule to be initialized, of type aes_key_t. * Allocated by aes_alloc_keysched(). */ void aes_init_keysched(const uint8_t *cipherKey, uint_t keyBits, void *keysched) { aes_key_t *newbie = keysched; uint_t keysize, i, j; union { uint64_t ka64[4]; uint32_t ka32[8]; } keyarr; switch (keyBits) { case 128: newbie->nr = 10; break; case 192: newbie->nr = 12; break; case 256: newbie->nr = 14; break; default: /* should never get here */ return; } keysize = CRYPTO_BITS2BYTES(keyBits); /* * For _LITTLE_ENDIAN machines (except AMD64), reverse every * 4 bytes in the key. On _BIG_ENDIAN and AMD64, copy the key * without reversing bytes. * For AMD64, do not byte swap for aes_setupkeys(). * * SPARCv8/v9 uses a key schedule array with 64-bit elements. * X86/AMD64 uses a key schedule array with 32-bit elements. */ #ifndef AES_BYTE_SWAP if (IS_P2ALIGNED(cipherKey, sizeof (uint64_t))) { for (i = 0, j = 0; j < keysize; i++, j += 8) { /* LINTED: pointer alignment */ keyarr.ka64[i] = *((uint64_t *)&cipherKey[j]); } } else { bcopy(cipherKey, keyarr.ka32, keysize); } #else /* byte swap */ for (i = 0, j = 0; j < keysize; i++, j += 4) { keyarr.ka32[i] = htonl(*(uint32_t *)(void *)&cipherKey[j]); } #endif aes_setupkeys(newbie, keyarr.ka32, keyBits); } /* * Encrypt one block using AES. * Align if needed and (for x86 32-bit only) byte-swap. * * Parameters: * ks Key schedule, of type aes_key_t * pt Input block (plain text) * ct Output block (crypto text). Can overlap with pt */ int aes_encrypt_block(const void *ks, const uint8_t *pt, uint8_t *ct) { aes_key_t *ksch = (aes_key_t *)ks; #ifndef AES_BYTE_SWAP if (IS_P2ALIGNED2(pt, ct, sizeof (uint32_t))) { /* LINTED: pointer alignment */ AES_ENCRYPT_IMPL(&ksch->encr_ks.ks32[0], ksch->nr, /* LINTED: pointer alignment */ (uint32_t *)pt, (uint32_t *)ct, ksch->flags); } else { #endif uint32_t buffer[AES_BLOCK_LEN / sizeof (uint32_t)]; /* Copy input block into buffer */ #ifndef AES_BYTE_SWAP bcopy(pt, &buffer, AES_BLOCK_LEN); #else /* byte swap */ buffer[0] = htonl(*(uint32_t *)(void *)&pt[0]); buffer[1] = htonl(*(uint32_t *)(void *)&pt[4]); buffer[2] = htonl(*(uint32_t *)(void *)&pt[8]); buffer[3] = htonl(*(uint32_t *)(void *)&pt[12]); #endif AES_ENCRYPT_IMPL(&ksch->encr_ks.ks32[0], ksch->nr, buffer, buffer, ksch->flags); /* Copy result from buffer to output block */ #ifndef AES_BYTE_SWAP bcopy(&buffer, ct, AES_BLOCK_LEN); } #else /* byte swap */ *(uint32_t *)(void *)&ct[0] = htonl(buffer[0]); *(uint32_t *)(void *)&ct[4] = htonl(buffer[1]); *(uint32_t *)(void *)&ct[8] = htonl(buffer[2]); *(uint32_t *)(void *)&ct[12] = htonl(buffer[3]); #endif return (CRYPTO_SUCCESS); } /* * Decrypt one block using AES. * Align and byte-swap if needed. * * Parameters: * ks Key schedule, of type aes_key_t * ct Input block (crypto text) * pt Output block (plain text). Can overlap with pt */ int aes_decrypt_block(const void *ks, const uint8_t *ct, uint8_t *pt) { aes_key_t *ksch = (aes_key_t *)ks; #ifndef AES_BYTE_SWAP if (IS_P2ALIGNED2(ct, pt, sizeof (uint32_t))) { /* LINTED: pointer alignment */ AES_DECRYPT_IMPL(&ksch->decr_ks.ks32[0], ksch->nr, /* LINTED: pointer alignment */ (uint32_t *)ct, (uint32_t *)pt, ksch->flags); } else { #endif uint32_t buffer[AES_BLOCK_LEN / sizeof (uint32_t)]; /* Copy input block into buffer */ #ifndef AES_BYTE_SWAP bcopy(ct, &buffer, AES_BLOCK_LEN); #else /* byte swap */ buffer[0] = htonl(*(uint32_t *)(void *)&ct[0]); buffer[1] = htonl(*(uint32_t *)(void *)&ct[4]); buffer[2] = htonl(*(uint32_t *)(void *)&ct[8]); buffer[3] = htonl(*(uint32_t *)(void *)&ct[12]); #endif AES_DECRYPT_IMPL(&ksch->decr_ks.ks32[0], ksch->nr, buffer, buffer, ksch->flags); /* Copy result from buffer to output block */ #ifndef AES_BYTE_SWAP bcopy(&buffer, pt, AES_BLOCK_LEN); } #else /* byte swap */ *(uint32_t *)(void *)&pt[0] = htonl(buffer[0]); *(uint32_t *)(void *)&pt[4] = htonl(buffer[1]); *(uint32_t *)(void *)&pt[8] = htonl(buffer[2]); *(uint32_t *)(void *)&pt[12] = htonl(buffer[3]); #endif return (CRYPTO_SUCCESS); } /* * Allocate key schedule for AES. * * Return the pointer and set size to the number of bytes allocated. * Memory allocated must be freed by the caller when done. * * Parameters: * size Size of key schedule allocated, in bytes * kmflag Flag passed to kmem_alloc(9F); ignored in userland. */ /* ARGSUSED */ void * aes_alloc_keysched(size_t *size, int kmflag) { aes_key_t *keysched; #ifdef _KERNEL keysched = (aes_key_t *)kmem_alloc(sizeof (aes_key_t), kmflag); #else /* !_KERNEL */ keysched = (aes_key_t *)malloc(sizeof (aes_key_t)); #endif /* _KERNEL */ if (keysched != NULL) { *size = sizeof (aes_key_t); return (keysched); } return (NULL); } #ifdef __amd64 /* * Return 1 if executing on Intel with AES-NI instructions, * otherwise 0 (i.e., Intel without AES-NI or AMD64). * Cache the result, as the CPU can't change. * * Note: the userland version uses getisax(). The kernel version uses * global variable x86_featureset. */ static int intel_aes_instructions_present(void) { static int cached_result = -1; if (cached_result == -1) { /* first time */ #ifdef _KERNEL cached_result = is_x86_feature(x86_featureset, X86FSET_AES); #else uint_t ui = 0; (void) getisax(&ui, 1); cached_result = (ui & AV_386_AES) != 0; #endif /* _KERNEL */ } return (cached_result); } #endif /* __amd64 */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2018, Joyent, Inc. */ #ifndef _AES_IMPL_H #define _AES_IMPL_H /* * Common definitions used by AES. */ #ifdef __cplusplus extern "C" { #endif #include #include /* Similar to sysmacros.h IS_P2ALIGNED, but checks two pointers: */ #define IS_P2ALIGNED2(v, w, a) \ ((((uintptr_t)(v) | (uintptr_t)(w)) & ((uintptr_t)(a) - 1)) == 0) #define AES_BLOCK_LEN 16 /* bytes */ /* Round constant length, in number of 32-bit elements: */ #define RC_LENGTH (5 * ((AES_BLOCK_LEN) / 4 - 2)) #define AES_COPY_BLOCK(src, dst) \ (dst)[0] = (src)[0]; \ (dst)[1] = (src)[1]; \ (dst)[2] = (src)[2]; \ (dst)[3] = (src)[3]; \ (dst)[4] = (src)[4]; \ (dst)[5] = (src)[5]; \ (dst)[6] = (src)[6]; \ (dst)[7] = (src)[7]; \ (dst)[8] = (src)[8]; \ (dst)[9] = (src)[9]; \ (dst)[10] = (src)[10]; \ (dst)[11] = (src)[11]; \ (dst)[12] = (src)[12]; \ (dst)[13] = (src)[13]; \ (dst)[14] = (src)[14]; \ (dst)[15] = (src)[15] #define AES_XOR_BLOCK(src, dst) \ (dst)[0] ^= (src)[0]; \ (dst)[1] ^= (src)[1]; \ (dst)[2] ^= (src)[2]; \ (dst)[3] ^= (src)[3]; \ (dst)[4] ^= (src)[4]; \ (dst)[5] ^= (src)[5]; \ (dst)[6] ^= (src)[6]; \ (dst)[7] ^= (src)[7]; \ (dst)[8] ^= (src)[8]; \ (dst)[9] ^= (src)[9]; \ (dst)[10] ^= (src)[10]; \ (dst)[11] ^= (src)[11]; \ (dst)[12] ^= (src)[12]; \ (dst)[13] ^= (src)[13]; \ (dst)[14] ^= (src)[14]; \ (dst)[15] ^= (src)[15] /* AES key size definitions */ #define AES_MINBITS 128 #define AES_MINBYTES ((AES_MINBITS) >> 3) #define AES_MAXBITS 256 #define AES_MAXBYTES ((AES_MAXBITS) >> 3) #define AES_MIN_KEY_BYTES ((AES_MINBITS) >> 3) #define AES_MAX_KEY_BYTES ((AES_MAXBITS) >> 3) #define AES_192_KEY_BYTES 24 #define AES_IV_LEN 16 /* CBC, ECB */ #define AES_GMAC_IV_LEN 12 /* AES key schedule may be implemented with 32- or 64-bit elements: */ #define AES_32BIT_KS 32 #define AES_64BIT_KS 64 #define MAX_AES_NR 14 /* Maximum number of rounds */ #define MAX_AES_NB 4 /* Number of columns comprising a state */ typedef union { #ifdef sun4u uint64_t ks64[((MAX_AES_NR) + 1) * (MAX_AES_NB)]; #endif uint32_t ks32[((MAX_AES_NR) + 1) * (MAX_AES_NB)]; } aes_ks_t; /* aes_key.flags value: */ #define INTEL_AES_NI_CAPABLE 0x1 /* AES-NI instructions present */ typedef struct aes_key aes_key_t; struct aes_key { aes_ks_t encr_ks; /* encryption key schedule */ aes_ks_t decr_ks; /* decryption key schedule */ #ifdef __amd64 long double align128; /* Align fields above for Intel AES-NI */ int flags; /* implementation-dependent flags */ #endif /* __amd64 */ int nr; /* number of rounds (10, 12, or 14) */ int type; /* key schedule size (32 or 64 bits) */ }; /* * Core AES functions. * ks and keysched are pointers to aes_key_t. * They are declared void* as they are intended to be opaque types. * Use function aes_alloc_keysched() to allocate memory for ks and keysched. */ extern void *aes_alloc_keysched(size_t *size, int kmflag); extern void aes_init_keysched(const uint8_t *cipherKey, uint_t keyBits, void *keysched); extern int aes_encrypt_block(const void *ks, const uint8_t *pt, uint8_t *ct); extern int aes_decrypt_block(const void *ks, const uint8_t *ct, uint8_t *pt); /* * AES mode functions. * The first 3 functions operate on 16-byte AES blocks. */ extern void aes_copy_block(uint8_t *in, uint8_t *out); extern void aes_copy_block64(uint8_t *in, uint64_t *out); extern void aes_xor_block(uint8_t *data, uint8_t *dst); /* Note: ctx is a pointer to aes_ctx_t defined in modes.h */ extern int aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length, crypto_data_t *out); extern int aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, crypto_data_t *out); /* * The following definitions and declarations are only used by AES FIPS POST */ #ifdef _AES_IMPL #ifdef _KERNEL typedef enum aes_mech_type { AES_ECB_MECH_INFO_TYPE, /* SUN_CKM_AES_ECB */ AES_CBC_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC */ AES_CBC_PAD_MECH_INFO_TYPE, /* SUN_CKM_AES_CBC_PAD */ AES_CTR_MECH_INFO_TYPE, /* SUN_CKM_AES_CTR */ AES_CCM_MECH_INFO_TYPE, /* SUN_CKM_AES_CCM */ AES_GCM_MECH_INFO_TYPE, /* SUN_CKM_AES_GCM */ AES_GMAC_MECH_INFO_TYPE, /* SUN_CKM_AES_GMAC */ AES_CMAC_MECH_INFO_TYPE /* SUN_CKM_AES_CMAC */ } aes_mech_type_t; #endif /* _KERNEL */ #endif /* _AES_IMPL */ #ifdef __cplusplus } #endif #endif /* _AES_IMPL_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2019 Joyent, Inc. */ #include #include #include #include "aes_impl.h" #ifndef _KERNEL #include #endif /* !_KERNEL */ /* Copy a 16-byte AES block from "in" to "out" */ void aes_copy_block(uint8_t *in, uint8_t *out) { if (IS_P2ALIGNED2(in, out, sizeof (uint32_t))) { /* LINTED: pointer alignment */ *(uint32_t *)&out[0] = *(uint32_t *)&in[0]; /* LINTED: pointer alignment */ *(uint32_t *)&out[4] = *(uint32_t *)&in[4]; /* LINTED: pointer alignment */ *(uint32_t *)&out[8] = *(uint32_t *)&in[8]; /* LINTED: pointer alignment */ *(uint32_t *)&out[12] = *(uint32_t *)&in[12]; } else { AES_COPY_BLOCK(in, out); } } /* * Copy a 16-byte AES block in 64-bit chunks if the input address is aligned * to 64-bits */ void aes_copy_block64(uint8_t *in, uint64_t *out) { if (IS_P2ALIGNED(in, sizeof (uint64_t))) { /* LINTED: pointer alignment */ out[0] = *(uint64_t *)&in[0]; /* LINTED: pointer alignment */ out[1] = *(uint64_t *)&in[8]; } else { uint8_t *iv8 = (uint8_t *)&out[0]; AES_COPY_BLOCK(in, iv8); } } /* XOR a 16-byte AES block of data into dst */ void aes_xor_block(uint8_t *data, uint8_t *dst) { if (IS_P2ALIGNED2(dst, data, sizeof (uint32_t))) { /* LINTED: pointer alignment */ *(uint32_t *)&dst[0] ^= *(uint32_t *)&data[0]; /* LINTED: pointer alignment */ *(uint32_t *)&dst[4] ^= *(uint32_t *)&data[4]; /* LINTED: pointer alignment */ *(uint32_t *)&dst[8] ^= *(uint32_t *)&data[8]; /* LINTED: pointer alignment */ *(uint32_t *)&dst[12] ^= *(uint32_t *)&data[12]; } else { AES_XOR_BLOCK(data, dst); } } /* * Encrypt multiple blocks of data according to mode. */ int aes_encrypt_contiguous_blocks(void *ctx, char *data, size_t length, crypto_data_t *out) { aes_ctx_t *aes_ctx = ctx; int rv; if (aes_ctx->ac_flags & CTR_MODE) { rv = ctr_mode_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block); } else if (aes_ctx->ac_flags & CCM_MODE) { rv = ccm_mode_encrypt_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, aes_xor_block); } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { rv = gcm_mode_encrypt_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, aes_xor_block); } else if (aes_ctx->ac_flags & (CBC_MODE|CMAC_MODE)) { rv = cbc_encrypt_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, aes_xor_block); } else { rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block); } return (rv); } /* * Decrypt multiple blocks of data according to mode. */ int aes_decrypt_contiguous_blocks(void *ctx, char *data, size_t length, crypto_data_t *out) { aes_ctx_t *aes_ctx = ctx; int rv; if (aes_ctx->ac_flags & CTR_MODE) { rv = ctr_mode_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block); if (rv == CRYPTO_DATA_LEN_RANGE) rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; } else if (aes_ctx->ac_flags & CCM_MODE) { rv = ccm_mode_decrypt_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, aes_xor_block); } else if (aes_ctx->ac_flags & (GCM_MODE|GMAC_MODE)) { rv = gcm_mode_decrypt_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block, aes_xor_block); } else if (aes_ctx->ac_flags & CBC_MODE) { rv = cbc_decrypt_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_decrypt_block, aes_copy_block, aes_xor_block); } else { rv = ecb_cipher_contiguous_blocks(ctx, data, length, out, AES_BLOCK_LEN, aes_decrypt_block); if (rv == CRYPTO_DATA_LEN_RANGE) rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE; } return (rv); } --------------------------------------------------------------------------- Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. LICENSE TERMS The free distribution and use of this software is allowed (with or without changes) provided that: 1. source code distributions include the above copyright notice, this list of conditions and the following disclaimer; 2. binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation; 3. the name of the copyright holder is not used to endorse products built using this software without specific written permission. DISCLAIMER This software is provided 'as is' with no explicit or implied warranties in respect of its properties, including, but not limited to, correctness and/or fitness for purpose. --------------------------------------------------------------------------- PORTIONS OF AES FUNCTIONALITY LICENSE ISSUES ============== The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the OpenSSL License and the original SSLeay license apply to the toolkit. See below for the actual license texts. Actually both licenses are BSD-style Open Source licenses. In case of any license issues related to OpenSSL please contact openssl-core@openssl.org. OpenSSL License --------------- /* ==================================================================== * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ Original SSLeay License ----------------------- /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ PORTIONS OF AES FUNCTIONALITY /* * --------------------------------------------------------------------------- * Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. * * LICENSE TERMS * * The free distribution and use of this software is allowed (with or without * changes) provided that: * * 1. source code distributions include the above copyright notice, this * list of conditions and the following disclaimer; * * 2. binary distributions include the above copyright notice, this list * of conditions and the following disclaimer in their documentation; * * 3. the name of the copyright holder is not used to endorse products * built using this software without specific written permission. * * DISCLAIMER * * This software is provided 'as is' with no explicit or implied warranties * in respect of its properties, including, but not limited to, correctness * and/or fitness for purpose. * --------------------------------------------------------------------------- * Issue 20/12/2007 * * I am grateful to Dag Arne Osvik for many discussions of the techniques that * can be used to optimise AES assembler code on AMD64/EM64T architectures. * Some of the techniques used in this implementation are the result of * suggestions made by him for which I am most grateful. * * An AES implementation for AMD64 processors using the YASM assembler. This * implementation provides only encryption, decryption and hence requires key * scheduling support in C. It uses 8k bytes of tables but its encryption and * decryption performance is very close to that obtained using large tables. * It can use either MS Windows or Gnu/Linux/OpenSolaris OS calling conventions, * which are as follows: * ms windows gnu/linux/opensolaris os * * in_blk rcx rdi * out_blk rdx rsi * context (cx) r8 rdx * * preserved rsi - + rbx, rbp, rsp, r12, r13, r14 & r15 * registers rdi - on both * * destroyed - rsi + rax, rcx, rdx, r8, r9, r10 & r11 * registers - rdi on both * * The convention used here is that for gnu/linux/opensolaris os. * * This code provides the standard AES block size (128 bits, 16 bytes) and the * three standard AES key sizes (128, 192 and 256 bits). It has the same call * interface as my C implementation. It uses the Microsoft C AMD64 calling * conventions in which the three parameters are placed in rcx, rdx and r8 * respectively. The rbx, rsi, rdi, rbp and r12..r15 registers are preserved. * * OpenSolaris Note: * Modified to use GNU/Linux/Solaris calling conventions. * That is parameters are placed in rdi, rsi, rdx, and rcx, respectively. * * AES_RETURN aes_encrypt(const unsigned char in_blk[], * unsigned char out_blk[], const aes_encrypt_ctx cx[1])/ * * AES_RETURN aes_decrypt(const unsigned char in_blk[], * unsigned char out_blk[], const aes_decrypt_ctx cx[1])/ * * AES_RETURN aes_encrypt_key(const unsigned char key[], * const aes_encrypt_ctx cx[1])/ * * AES_RETURN aes_decrypt_key(const unsigned char key[], * const aes_decrypt_ctx cx[1])/ * * AES_RETURN aes_encrypt_key(const unsigned char key[], * unsigned int len, const aes_decrypt_ctx cx[1])/ * * AES_RETURN aes_decrypt_key(const unsigned char key[], * unsigned int len, const aes_decrypt_ctx cx[1])/ * * where is 128, 102 or 256. In the last two calls the length can be in * either bits or bytes. * * Comment in/out the following lines to obtain the desired subroutines. These * selections MUST match those in the C header file aesopt.h */ #define AES_REV_DKS /* define if key decryption schedule is reversed */ #define LAST_ROUND_TABLES /* define for the faster version using extra tables */ /* * The encryption key schedule has the following in memory layout where N is the * number of rounds (10, 12 or 14): * * lo: | input key (round 0) | / each round is four 32-bit words * | encryption round 1 | * | encryption round 2 | * .... * | encryption round N-1 | * hi: | encryption round N | * * The decryption key schedule is normally set up so that it has the same * layout as above by actually reversing the order of the encryption key * schedule in memory (this happens when AES_REV_DKS is set): * * lo: | decryption round 0 | = | encryption round N | * | decryption round 1 | = INV_MIX_COL[ | encryption round N-1 | ] * | decryption round 2 | = INV_MIX_COL[ | encryption round N-2 | ] * .... .... * | decryption round N-1 | = INV_MIX_COL[ | encryption round 1 | ] * hi: | decryption round N | = | input key (round 0) | * * with rounds except the first and last modified using inv_mix_column() * But if AES_REV_DKS is NOT set the order of keys is left as it is for * encryption so that it has to be accessed in reverse when used for * decryption (although the inverse mix column modifications are done) * * lo: | decryption round 0 | = | input key (round 0) | * | decryption round 1 | = INV_MIX_COL[ | encryption round 1 | ] * | decryption round 2 | = INV_MIX_COL[ | encryption round 2 | ] * .... .... * | decryption round N-1 | = INV_MIX_COL[ | encryption round N-1 | ] * hi: | decryption round N | = | encryption round N | * * This layout is faster when the assembler key scheduling provided here * is used. * * End of user defines */ /* * --------------------------------------------------------------------------- * OpenSolaris OS modifications * * This source originates from Brian Gladman file aes_amd64.asm * in http://fp.gladman.plus.com/AES/aes-src-04-03-08.zip * with these changes: * * 1. Removed MS Windows-specific code within DLL_EXPORT, _SEH_, and * !__GNUC__ ifdefs. Also removed ENCRYPTION, DECRYPTION, * AES_128, AES_192, AES_256, AES_VAR ifdefs. * * 2. Translate yasm/nasm %define and .macro definitions to cpp(1) #define * * 3. Translate yasm/nasm %ifdef/%ifndef to cpp(1) #ifdef * * 4. Translate Intel/yasm/nasm syntax to ATT/OpenSolaris as(1) syntax * (operands reversed, literals prefixed with "$", registers prefixed with "%", * and "[register+offset]", addressing changed to "offset(register)", * parenthesis in constant expressions "()" changed to square brackets "[]", * "." removed from local (numeric) labels, and other changes. * Examples: * Intel/yasm/nasm Syntax ATT/OpenSolaris Syntax * mov rax,(4*20h) mov $[4*0x20],%rax * mov rax,[ebx+20h] mov 0x20(%ebx),%rax * lea rax,[ebx+ecx] lea (%ebx,%ecx),%rax * sub rax,[ebx+ecx*4-20h] sub -0x20(%ebx,%ecx,4),%rax * * 5. Added OpenSolaris ENTRY_NP/SET_SIZE macros from * /usr/include/sys/asm_linkage.h, lint(1B) guards, and dummy C function * definitions for lint. * * 6. Renamed functions and reordered parameters to match OpenSolaris: * Original Gladman interface: * int aes_encrypt(const unsigned char *in, * unsigned char *out, const aes_encrypt_ctx cx[1])/ * int aes_decrypt(const unsigned char *in, * unsigned char *out, const aes_encrypt_ctx cx[1])/ * Note: aes_encrypt_ctx contains ks, a 60 element array of uint32_t, * and a union type, inf., containing inf.l, a uint32_t and * inf.b, a 4-element array of uint32_t. Only b[0] in the array (aka "l") is * used and contains the key schedule length * 16 where key schedule length is * 10, 12, or 14 bytes. * * OpenSolaris OS interface: * void aes_encrypt_amd64(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4])/ * void aes_decrypt_amd64(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4])/ * typedef union {uint64_t ks64[(MAX_AES_NR + 1) * 4]/ * uint32_t ks32[(MAX_AES_NR + 1) * 4]/ } aes_ks_t/ * Note: ks is the AES key schedule, Nr is number of rounds, pt is plain text, * ct is crypto text, and MAX_AES_NR is 14. * For the x86 64-bit architecture, OpenSolaris OS uses ks32 instead of ks64. */ #if defined(lint) || defined(__lint) #include /* ARGSUSED */ void aes_encrypt_amd64(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4]) { } /* ARGSUSED */ void aes_decrypt_amd64(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]) { } #else #include #define KS_LENGTH 60 #define raxd eax #define rdxd edx #define rcxd ecx #define rbxd ebx #define rsid esi #define rdid edi #define raxb al #define rdxb dl #define rcxb cl #define rbxb bl #define rsib sil #define rdib dil / finite field multiplies by {02}, {04} and {08} #define f2(x) [[x<<1]^[[[x>>7]&1]*0x11b]] #define f4(x) [[x<<2]^[[[x>>6]&1]*0x11b]^[[[x>>6]&2]*0x11b]] #define f8(x) [[x<<3]^[[[x>>5]&1]*0x11b]^[[[x>>5]&2]*0x11b]^[[[x>>5]&4]*0x11b]] / finite field multiplies required in table generation #define f3(x) [[f2(x)] ^ [x]] #define f9(x) [[f8(x)] ^ [x]] #define fb(x) [[f8(x)] ^ [f2(x)] ^ [x]] #define fd(x) [[f8(x)] ^ [f4(x)] ^ [x]] #define fe(x) [[f8(x)] ^ [f4(x)] ^ [f2(x)]] / macros for expanding S-box data #define u8(x) [f2(x)], [x], [x], [f3(x)], [f2(x)], [x], [x], [f3(x)] #define v8(x) [fe(x)], [f9(x)], [fd(x)], [fb(x)], [fe(x)], [f9(x)], [fd(x)], [x] #define w8(x) [x], 0, 0, 0, [x], 0, 0, 0 #define enc_vals(x) \ .byte x(0x63),x(0x7c),x(0x77),x(0x7b),x(0xf2),x(0x6b),x(0x6f),x(0xc5); \ .byte x(0x30),x(0x01),x(0x67),x(0x2b),x(0xfe),x(0xd7),x(0xab),x(0x76); \ .byte x(0xca),x(0x82),x(0xc9),x(0x7d),x(0xfa),x(0x59),x(0x47),x(0xf0); \ .byte x(0xad),x(0xd4),x(0xa2),x(0xaf),x(0x9c),x(0xa4),x(0x72),x(0xc0); \ .byte x(0xb7),x(0xfd),x(0x93),x(0x26),x(0x36),x(0x3f),x(0xf7),x(0xcc); \ .byte x(0x34),x(0xa5),x(0xe5),x(0xf1),x(0x71),x(0xd8),x(0x31),x(0x15); \ .byte x(0x04),x(0xc7),x(0x23),x(0xc3),x(0x18),x(0x96),x(0x05),x(0x9a); \ .byte x(0x07),x(0x12),x(0x80),x(0xe2),x(0xeb),x(0x27),x(0xb2),x(0x75); \ .byte x(0x09),x(0x83),x(0x2c),x(0x1a),x(0x1b),x(0x6e),x(0x5a),x(0xa0); \ .byte x(0x52),x(0x3b),x(0xd6),x(0xb3),x(0x29),x(0xe3),x(0x2f),x(0x84); \ .byte x(0x53),x(0xd1),x(0x00),x(0xed),x(0x20),x(0xfc),x(0xb1),x(0x5b); \ .byte x(0x6a),x(0xcb),x(0xbe),x(0x39),x(0x4a),x(0x4c),x(0x58),x(0xcf); \ .byte x(0xd0),x(0xef),x(0xaa),x(0xfb),x(0x43),x(0x4d),x(0x33),x(0x85); \ .byte x(0x45),x(0xf9),x(0x02),x(0x7f),x(0x50),x(0x3c),x(0x9f),x(0xa8); \ .byte x(0x51),x(0xa3),x(0x40),x(0x8f),x(0x92),x(0x9d),x(0x38),x(0xf5); \ .byte x(0xbc),x(0xb6),x(0xda),x(0x21),x(0x10),x(0xff),x(0xf3),x(0xd2); \ .byte x(0xcd),x(0x0c),x(0x13),x(0xec),x(0x5f),x(0x97),x(0x44),x(0x17); \ .byte x(0xc4),x(0xa7),x(0x7e),x(0x3d),x(0x64),x(0x5d),x(0x19),x(0x73); \ .byte x(0x60),x(0x81),x(0x4f),x(0xdc),x(0x22),x(0x2a),x(0x90),x(0x88); \ .byte x(0x46),x(0xee),x(0xb8),x(0x14),x(0xde),x(0x5e),x(0x0b),x(0xdb); \ .byte x(0xe0),x(0x32),x(0x3a),x(0x0a),x(0x49),x(0x06),x(0x24),x(0x5c); \ .byte x(0xc2),x(0xd3),x(0xac),x(0x62),x(0x91),x(0x95),x(0xe4),x(0x79); \ .byte x(0xe7),x(0xc8),x(0x37),x(0x6d),x(0x8d),x(0xd5),x(0x4e),x(0xa9); \ .byte x(0x6c),x(0x56),x(0xf4),x(0xea),x(0x65),x(0x7a),x(0xae),x(0x08); \ .byte x(0xba),x(0x78),x(0x25),x(0x2e),x(0x1c),x(0xa6),x(0xb4),x(0xc6); \ .byte x(0xe8),x(0xdd),x(0x74),x(0x1f),x(0x4b),x(0xbd),x(0x8b),x(0x8a); \ .byte x(0x70),x(0x3e),x(0xb5),x(0x66),x(0x48),x(0x03),x(0xf6),x(0x0e); \ .byte x(0x61),x(0x35),x(0x57),x(0xb9),x(0x86),x(0xc1),x(0x1d),x(0x9e); \ .byte x(0xe1),x(0xf8),x(0x98),x(0x11),x(0x69),x(0xd9),x(0x8e),x(0x94); \ .byte x(0x9b),x(0x1e),x(0x87),x(0xe9),x(0xce),x(0x55),x(0x28),x(0xdf); \ .byte x(0x8c),x(0xa1),x(0x89),x(0x0d),x(0xbf),x(0xe6),x(0x42),x(0x68); \ .byte x(0x41),x(0x99),x(0x2d),x(0x0f),x(0xb0),x(0x54),x(0xbb),x(0x16) #define dec_vals(x) \ .byte x(0x52),x(0x09),x(0x6a),x(0xd5),x(0x30),x(0x36),x(0xa5),x(0x38); \ .byte x(0xbf),x(0x40),x(0xa3),x(0x9e),x(0x81),x(0xf3),x(0xd7),x(0xfb); \ .byte x(0x7c),x(0xe3),x(0x39),x(0x82),x(0x9b),x(0x2f),x(0xff),x(0x87); \ .byte x(0x34),x(0x8e),x(0x43),x(0x44),x(0xc4),x(0xde),x(0xe9),x(0xcb); \ .byte x(0x54),x(0x7b),x(0x94),x(0x32),x(0xa6),x(0xc2),x(0x23),x(0x3d); \ .byte x(0xee),x(0x4c),x(0x95),x(0x0b),x(0x42),x(0xfa),x(0xc3),x(0x4e); \ .byte x(0x08),x(0x2e),x(0xa1),x(0x66),x(0x28),x(0xd9),x(0x24),x(0xb2); \ .byte x(0x76),x(0x5b),x(0xa2),x(0x49),x(0x6d),x(0x8b),x(0xd1),x(0x25); \ .byte x(0x72),x(0xf8),x(0xf6),x(0x64),x(0x86),x(0x68),x(0x98),x(0x16); \ .byte x(0xd4),x(0xa4),x(0x5c),x(0xcc),x(0x5d),x(0x65),x(0xb6),x(0x92); \ .byte x(0x6c),x(0x70),x(0x48),x(0x50),x(0xfd),x(0xed),x(0xb9),x(0xda); \ .byte x(0x5e),x(0x15),x(0x46),x(0x57),x(0xa7),x(0x8d),x(0x9d),x(0x84); \ .byte x(0x90),x(0xd8),x(0xab),x(0x00),x(0x8c),x(0xbc),x(0xd3),x(0x0a); \ .byte x(0xf7),x(0xe4),x(0x58),x(0x05),x(0xb8),x(0xb3),x(0x45),x(0x06); \ .byte x(0xd0),x(0x2c),x(0x1e),x(0x8f),x(0xca),x(0x3f),x(0x0f),x(0x02); \ .byte x(0xc1),x(0xaf),x(0xbd),x(0x03),x(0x01),x(0x13),x(0x8a),x(0x6b); \ .byte x(0x3a),x(0x91),x(0x11),x(0x41),x(0x4f),x(0x67),x(0xdc),x(0xea); \ .byte x(0x97),x(0xf2),x(0xcf),x(0xce),x(0xf0),x(0xb4),x(0xe6),x(0x73); \ .byte x(0x96),x(0xac),x(0x74),x(0x22),x(0xe7),x(0xad),x(0x35),x(0x85); \ .byte x(0xe2),x(0xf9),x(0x37),x(0xe8),x(0x1c),x(0x75),x(0xdf),x(0x6e); \ .byte x(0x47),x(0xf1),x(0x1a),x(0x71),x(0x1d),x(0x29),x(0xc5),x(0x89); \ .byte x(0x6f),x(0xb7),x(0x62),x(0x0e),x(0xaa),x(0x18),x(0xbe),x(0x1b); \ .byte x(0xfc),x(0x56),x(0x3e),x(0x4b),x(0xc6),x(0xd2),x(0x79),x(0x20); \ .byte x(0x9a),x(0xdb),x(0xc0),x(0xfe),x(0x78),x(0xcd),x(0x5a),x(0xf4); \ .byte x(0x1f),x(0xdd),x(0xa8),x(0x33),x(0x88),x(0x07),x(0xc7),x(0x31); \ .byte x(0xb1),x(0x12),x(0x10),x(0x59),x(0x27),x(0x80),x(0xec),x(0x5f); \ .byte x(0x60),x(0x51),x(0x7f),x(0xa9),x(0x19),x(0xb5),x(0x4a),x(0x0d); \ .byte x(0x2d),x(0xe5),x(0x7a),x(0x9f),x(0x93),x(0xc9),x(0x9c),x(0xef); \ .byte x(0xa0),x(0xe0),x(0x3b),x(0x4d),x(0xae),x(0x2a),x(0xf5),x(0xb0); \ .byte x(0xc8),x(0xeb),x(0xbb),x(0x3c),x(0x83),x(0x53),x(0x99),x(0x61); \ .byte x(0x17),x(0x2b),x(0x04),x(0x7e),x(0xba),x(0x77),x(0xd6),x(0x26); \ .byte x(0xe1),x(0x69),x(0x14),x(0x63),x(0x55),x(0x21),x(0x0c),x(0x7d) #define tptr %rbp /* table pointer */ #define kptr %r8 /* key schedule pointer */ #define fofs 128 /* adjust offset in key schedule to keep |disp| < 128 */ #define fk_ref(x, y) -16*x+fofs+4*y(kptr) #ifdef AES_REV_DKS #define rofs 128 #define ik_ref(x, y) -16*x+rofs+4*y(kptr) #else #define rofs -128 #define ik_ref(x, y) 16*x+rofs+4*y(kptr) #endif /* AES_REV_DKS */ #define tab_0(x) (tptr,x,8) #define tab_1(x) 3(tptr,x,8) #define tab_2(x) 2(tptr,x,8) #define tab_3(x) 1(tptr,x,8) #define tab_f(x) 1(tptr,x,8) #define tab_i(x) 7(tptr,x,8) #define ff_rnd(p1, p2, p3, p4, round) /* normal forward round */ \ mov fk_ref(round,0), p1; \ mov fk_ref(round,1), p2; \ mov fk_ref(round,2), p3; \ mov fk_ref(round,3), p4; \ \ movzx %al, %esi; \ movzx %ah, %edi; \ shr $16, %eax; \ xor tab_0(%rsi), p1; \ xor tab_1(%rdi), p4; \ movzx %al, %esi; \ movzx %ah, %edi; \ xor tab_2(%rsi), p3; \ xor tab_3(%rdi), p2; \ \ movzx %bl, %esi; \ movzx %bh, %edi; \ shr $16, %ebx; \ xor tab_0(%rsi), p2; \ xor tab_1(%rdi), p1; \ movzx %bl, %esi; \ movzx %bh, %edi; \ xor tab_2(%rsi), p4; \ xor tab_3(%rdi), p3; \ \ movzx %cl, %esi; \ movzx %ch, %edi; \ shr $16, %ecx; \ xor tab_0(%rsi), p3; \ xor tab_1(%rdi), p2; \ movzx %cl, %esi; \ movzx %ch, %edi; \ xor tab_2(%rsi), p1; \ xor tab_3(%rdi), p4; \ \ movzx %dl, %esi; \ movzx %dh, %edi; \ shr $16, %edx; \ xor tab_0(%rsi), p4; \ xor tab_1(%rdi), p3; \ movzx %dl, %esi; \ movzx %dh, %edi; \ xor tab_2(%rsi), p2; \ xor tab_3(%rdi), p1; \ \ mov p1, %eax; \ mov p2, %ebx; \ mov p3, %ecx; \ mov p4, %edx #ifdef LAST_ROUND_TABLES #define fl_rnd(p1, p2, p3, p4, round) /* last forward round */ \ add $2048, tptr; \ mov fk_ref(round,0), p1; \ mov fk_ref(round,1), p2; \ mov fk_ref(round,2), p3; \ mov fk_ref(round,3), p4; \ \ movzx %al, %esi; \ movzx %ah, %edi; \ shr $16, %eax; \ xor tab_0(%rsi), p1; \ xor tab_1(%rdi), p4; \ movzx %al, %esi; \ movzx %ah, %edi; \ xor tab_2(%rsi), p3; \ xor tab_3(%rdi), p2; \ \ movzx %bl, %esi; \ movzx %bh, %edi; \ shr $16, %ebx; \ xor tab_0(%rsi), p2; \ xor tab_1(%rdi), p1; \ movzx %bl, %esi; \ movzx %bh, %edi; \ xor tab_2(%rsi), p4; \ xor tab_3(%rdi), p3; \ \ movzx %cl, %esi; \ movzx %ch, %edi; \ shr $16, %ecx; \ xor tab_0(%rsi), p3; \ xor tab_1(%rdi), p2; \ movzx %cl, %esi; \ movzx %ch, %edi; \ xor tab_2(%rsi), p1; \ xor tab_3(%rdi), p4; \ \ movzx %dl, %esi; \ movzx %dh, %edi; \ shr $16, %edx; \ xor tab_0(%rsi), p4; \ xor tab_1(%rdi), p3; \ movzx %dl, %esi; \ movzx %dh, %edi; \ xor tab_2(%rsi), p2; \ xor tab_3(%rdi), p1 #else #define fl_rnd(p1, p2, p3, p4, round) /* last forward round */ \ mov fk_ref(round,0), p1; \ mov fk_ref(round,1), p2; \ mov fk_ref(round,2), p3; \ mov fk_ref(round,3), p4; \ \ movzx %al, %esi; \ movzx %ah, %edi; \ shr $16, %eax; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ xor %esi, p1; \ rol $8, %edi; \ xor %edi, p4; \ movzx %al, %esi; \ movzx %ah, %edi; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p3; \ xor %edi, p2; \ \ movzx %bl, %esi; \ movzx %bh, %edi; \ shr $16, %ebx; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ xor %esi, p2; \ rol $8, %edi; \ xor %edi, p1; \ movzx %bl, %esi; \ movzx %bh, %edi; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p4; \ xor %edi, p3; \ \ movzx %cl, %esi; \ movzx %ch, %edi; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ shr $16, %ecx; \ xor %esi, p3; \ rol $8, %edi; \ xor %edi, p2; \ movzx %cl, %esi; \ movzx %ch, %edi; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p1; \ xor %edi, p4; \ \ movzx %dl, %esi; \ movzx %dh, %edi; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ shr $16, %edx; \ xor %esi, p4; \ rol $8, %edi; \ xor %edi, p3; \ movzx %dl, %esi; \ movzx %dh, %edi; \ movzx tab_f(%rsi), %esi; \ movzx tab_f(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p2; \ xor %edi, p1 #endif /* LAST_ROUND_TABLES */ #define ii_rnd(p1, p2, p3, p4, round) /* normal inverse round */ \ mov ik_ref(round,0), p1; \ mov ik_ref(round,1), p2; \ mov ik_ref(round,2), p3; \ mov ik_ref(round,3), p4; \ \ movzx %al, %esi; \ movzx %ah, %edi; \ shr $16, %eax; \ xor tab_0(%rsi), p1; \ xor tab_1(%rdi), p2; \ movzx %al, %esi; \ movzx %ah, %edi; \ xor tab_2(%rsi), p3; \ xor tab_3(%rdi), p4; \ \ movzx %bl, %esi; \ movzx %bh, %edi; \ shr $16, %ebx; \ xor tab_0(%rsi), p2; \ xor tab_1(%rdi), p3; \ movzx %bl, %esi; \ movzx %bh, %edi; \ xor tab_2(%rsi), p4; \ xor tab_3(%rdi), p1; \ \ movzx %cl, %esi; \ movzx %ch, %edi; \ shr $16, %ecx; \ xor tab_0(%rsi), p3; \ xor tab_1(%rdi), p4; \ movzx %cl, %esi; \ movzx %ch, %edi; \ xor tab_2(%rsi), p1; \ xor tab_3(%rdi), p2; \ \ movzx %dl, %esi; \ movzx %dh, %edi; \ shr $16, %edx; \ xor tab_0(%rsi), p4; \ xor tab_1(%rdi), p1; \ movzx %dl, %esi; \ movzx %dh, %edi; \ xor tab_2(%rsi), p2; \ xor tab_3(%rdi), p3; \ \ mov p1, %eax; \ mov p2, %ebx; \ mov p3, %ecx; \ mov p4, %edx #ifdef LAST_ROUND_TABLES #define il_rnd(p1, p2, p3, p4, round) /* last inverse round */ \ add $2048, tptr; \ mov ik_ref(round,0), p1; \ mov ik_ref(round,1), p2; \ mov ik_ref(round,2), p3; \ mov ik_ref(round,3), p4; \ \ movzx %al, %esi; \ movzx %ah, %edi; \ shr $16, %eax; \ xor tab_0(%rsi), p1; \ xor tab_1(%rdi), p2; \ movzx %al, %esi; \ movzx %ah, %edi; \ xor tab_2(%rsi), p3; \ xor tab_3(%rdi), p4; \ \ movzx %bl, %esi; \ movzx %bh, %edi; \ shr $16, %ebx; \ xor tab_0(%rsi), p2; \ xor tab_1(%rdi), p3; \ movzx %bl, %esi; \ movzx %bh, %edi; \ xor tab_2(%rsi), p4; \ xor tab_3(%rdi), p1; \ \ movzx %cl, %esi; \ movzx %ch, %edi; \ shr $16, %ecx; \ xor tab_0(%rsi), p3; \ xor tab_1(%rdi), p4; \ movzx %cl, %esi; \ movzx %ch, %edi; \ xor tab_2(%rsi), p1; \ xor tab_3(%rdi), p2; \ \ movzx %dl, %esi; \ movzx %dh, %edi; \ shr $16, %edx; \ xor tab_0(%rsi), p4; \ xor tab_1(%rdi), p1; \ movzx %dl, %esi; \ movzx %dh, %edi; \ xor tab_2(%rsi), p2; \ xor tab_3(%rdi), p3 #else #define il_rnd(p1, p2, p3, p4, round) /* last inverse round */ \ mov ik_ref(round,0), p1; \ mov ik_ref(round,1), p2; \ mov ik_ref(round,2), p3; \ mov ik_ref(round,3), p4; \ \ movzx %al, %esi; \ movzx %ah, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ shr $16, %eax; \ xor %esi, p1; \ rol $8, %edi; \ xor %edi, p2; \ movzx %al, %esi; \ movzx %ah, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p3; \ xor %edi, p4; \ \ movzx %bl, %esi; \ movzx %bh, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ shr $16, %ebx; \ xor %esi, p2; \ rol $8, %edi; \ xor %edi, p3; \ movzx %bl, %esi; \ movzx %bh, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p4; \ xor %edi, p1; \ \ movzx %cl, %esi; \ movzx %ch, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ shr $16, %ecx; \ xor %esi, p3; \ rol $8, %edi; \ xor %edi, p4; \ movzx %cl, %esi; \ movzx %ch, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p1; \ xor %edi, p2; \ \ movzx %dl, %esi; \ movzx %dh, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ shr $16, %edx; \ xor %esi, p4; \ rol $8, %edi; \ xor %edi, p1; \ movzx %dl, %esi; \ movzx %dh, %edi; \ movzx tab_i(%rsi), %esi; \ movzx tab_i(%rdi), %edi; \ rol $16, %esi; \ rol $24, %edi; \ xor %esi, p2; \ xor %edi, p3 #endif /* LAST_ROUND_TABLES */ /* * OpenSolaris OS: * void aes_encrypt_amd64(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4])/ * * Original interface: * int aes_encrypt(const unsigned char *in, * unsigned char *out, const aes_encrypt_ctx cx[1])/ */ .align 64 enc_tab: enc_vals(u8) #ifdef LAST_ROUND_TABLES / Last Round Tables: enc_vals(w8) #endif ENTRY_NP(aes_encrypt_amd64) #ifdef GLADMAN_INTERFACE / Original interface sub $[4*8], %rsp / gnu/linux/opensolaris binary interface mov %rsi, (%rsp) / output pointer (P2) mov %rdx, %r8 / context (P3) mov %rbx, 1*8(%rsp) / P1: input pointer in rdi mov %rbp, 2*8(%rsp) / P2: output pointer in (rsp) mov %r12, 3*8(%rsp) / P3: context in r8 movzx 4*KS_LENGTH(kptr), %esi / Get byte key length * 16 #else / OpenSolaris OS interface sub $[4*8], %rsp / Make room on stack to save registers mov %rcx, (%rsp) / Save output pointer (P4) on stack mov %rdi, %r8 / context (P1) mov %rdx, %rdi / P3: save input pointer shl $4, %esi / P2: esi byte key length * 16 mov %rbx, 1*8(%rsp) / Save registers mov %rbp, 2*8(%rsp) mov %r12, 3*8(%rsp) / P1: context in r8 / P2: byte key length * 16 in esi / P3: input pointer in rdi / P4: output pointer in (rsp) #endif /* GLADMAN_INTERFACE */ lea enc_tab(%rip), tptr sub $fofs, kptr / Load input block into registers mov (%rdi), %eax mov 1*4(%rdi), %ebx mov 2*4(%rdi), %ecx mov 3*4(%rdi), %edx xor fofs(kptr), %eax xor fofs+4(kptr), %ebx xor fofs+8(kptr), %ecx xor fofs+12(kptr), %edx lea (kptr,%rsi), kptr / Jump based on byte key length * 16: cmp $[10*16], %esi je 3f cmp $[12*16], %esi je 2f cmp $[14*16], %esi je 1f mov $-1, %rax / error jmp 4f / Perform normal forward rounds 1: ff_rnd(%r9d, %r10d, %r11d, %r12d, 13) ff_rnd(%r9d, %r10d, %r11d, %r12d, 12) 2: ff_rnd(%r9d, %r10d, %r11d, %r12d, 11) ff_rnd(%r9d, %r10d, %r11d, %r12d, 10) 3: ff_rnd(%r9d, %r10d, %r11d, %r12d, 9) ff_rnd(%r9d, %r10d, %r11d, %r12d, 8) ff_rnd(%r9d, %r10d, %r11d, %r12d, 7) ff_rnd(%r9d, %r10d, %r11d, %r12d, 6) ff_rnd(%r9d, %r10d, %r11d, %r12d, 5) ff_rnd(%r9d, %r10d, %r11d, %r12d, 4) ff_rnd(%r9d, %r10d, %r11d, %r12d, 3) ff_rnd(%r9d, %r10d, %r11d, %r12d, 2) ff_rnd(%r9d, %r10d, %r11d, %r12d, 1) fl_rnd(%r9d, %r10d, %r11d, %r12d, 0) / Copy results mov (%rsp), %rbx mov %r9d, (%rbx) mov %r10d, 4(%rbx) mov %r11d, 8(%rbx) mov %r12d, 12(%rbx) xor %rax, %rax 4: / Restore registers mov 1*8(%rsp), %rbx mov 2*8(%rsp), %rbp mov 3*8(%rsp), %r12 add $[4*8], %rsp ret SET_SIZE(aes_encrypt_amd64) /* * OpenSolaris OS: * void aes_decrypt_amd64(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4])/ * * Original interface: * int aes_decrypt(const unsigned char *in, * unsigned char *out, const aes_encrypt_ctx cx[1])/ */ .align 64 dec_tab: dec_vals(v8) #ifdef LAST_ROUND_TABLES / Last Round Tables: dec_vals(w8) #endif ENTRY_NP(aes_decrypt_amd64) #ifdef GLADMAN_INTERFACE / Original interface sub $[4*8], %rsp / gnu/linux/opensolaris binary interface mov %rsi, (%rsp) / output pointer (P2) mov %rdx, %r8 / context (P3) mov %rbx, 1*8(%rsp) / P1: input pointer in rdi mov %rbp, 2*8(%rsp) / P2: output pointer in (rsp) mov %r12, 3*8(%rsp) / P3: context in r8 movzx 4*KS_LENGTH(kptr), %esi / Get byte key length * 16 #else / OpenSolaris OS interface sub $[4*8], %rsp / Make room on stack to save registers mov %rcx, (%rsp) / Save output pointer (P4) on stack mov %rdi, %r8 / context (P1) mov %rdx, %rdi / P3: save input pointer shl $4, %esi / P2: esi byte key length * 16 mov %rbx, 1*8(%rsp) / Save registers mov %rbp, 2*8(%rsp) mov %r12, 3*8(%rsp) / P1: context in r8 / P2: byte key length * 16 in esi / P3: input pointer in rdi / P4: output pointer in (rsp) #endif /* GLADMAN_INTERFACE */ lea dec_tab(%rip), tptr sub $rofs, kptr / Load input block into registers mov (%rdi), %eax mov 1*4(%rdi), %ebx mov 2*4(%rdi), %ecx mov 3*4(%rdi), %edx #ifdef AES_REV_DKS mov kptr, %rdi lea (kptr,%rsi), kptr #else lea (kptr,%rsi), %rdi #endif xor rofs(%rdi), %eax xor rofs+4(%rdi), %ebx xor rofs+8(%rdi), %ecx xor rofs+12(%rdi), %edx / Jump based on byte key length * 16: cmp $[10*16], %esi je 3f cmp $[12*16], %esi je 2f cmp $[14*16], %esi je 1f mov $-1, %rax / error jmp 4f / Perform normal inverse rounds 1: ii_rnd(%r9d, %r10d, %r11d, %r12d, 13) ii_rnd(%r9d, %r10d, %r11d, %r12d, 12) 2: ii_rnd(%r9d, %r10d, %r11d, %r12d, 11) ii_rnd(%r9d, %r10d, %r11d, %r12d, 10) 3: ii_rnd(%r9d, %r10d, %r11d, %r12d, 9) ii_rnd(%r9d, %r10d, %r11d, %r12d, 8) ii_rnd(%r9d, %r10d, %r11d, %r12d, 7) ii_rnd(%r9d, %r10d, %r11d, %r12d, 6) ii_rnd(%r9d, %r10d, %r11d, %r12d, 5) ii_rnd(%r9d, %r10d, %r11d, %r12d, 4) ii_rnd(%r9d, %r10d, %r11d, %r12d, 3) ii_rnd(%r9d, %r10d, %r11d, %r12d, 2) ii_rnd(%r9d, %r10d, %r11d, %r12d, 1) il_rnd(%r9d, %r10d, %r11d, %r12d, 0) / Copy results mov (%rsp), %rbx mov %r9d, (%rbx) mov %r10d, 4(%rbx) mov %r11d, 8(%rbx) mov %r12d, 12(%rbx) xor %rax, %rax 4: / Restore registers mov 1*8(%rsp), %rbx mov 2*8(%rsp), %rbp mov 3*8(%rsp), %r12 add $[4*8], %rsp ret SET_SIZE(aes_decrypt_amd64) #endif /* lint || __lint */ /* * ==================================================================== * Written by Intel Corporation for the OpenSSL project to add support * for Intel AES-NI instructions. Rights for redistribution and usage * in source and binary forms are granted according to the OpenSSL * license. * * Author: Huang Ying * Vinodh Gopal * Kahraman Akdemir * * Intel AES-NI is a new set of Single Instruction Multiple Data (SIMD) * instructions that are going to be introduced in the next generation * of Intel processor, as of 2009. These instructions enable fast and * secure data encryption and decryption, using the Advanced Encryption * Standard (AES), defined by FIPS Publication number 197. The * architecture introduces six instructions that offer full hardware * support for AES. Four of them support high performance data * encryption and decryption, and the other two instructions support * the AES key expansion procedure. * ==================================================================== */ /* * ==================================================================== * Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ /* * ==================================================================== * OpenSolaris OS modifications * * This source originates as files aes-intel.S and eng_aesni_asm.pl, in * patches sent sent Dec. 9, 2008 and Dec. 24, 2008, respectively, by * Huang Ying of Intel to the openssl-dev mailing list under the subject * of "Add support to Intel AES-NI instruction set for x86_64 platform". * * This OpenSolaris version has these major changes from the original source: * * 1. Added OpenSolaris ENTRY_NP/SET_SIZE macros from * /usr/include/sys/asm_linkage.h, lint(1B) guards, and dummy C function * definitions for lint. * * 2. Formatted code, added comments, and added #includes and #defines. * * 3. If bit CR0.TS is set, clear and set the TS bit, after and before * calling kpreempt_disable() and kpreempt_enable(). * If the TS bit is not set, Save and restore %xmm registers at the beginning * and end of function calls (%xmm* registers are not saved and restored by * during kernel thread preemption). * * 4. Renamed functions, reordered parameters, and changed return value * to match OpenSolaris: * * OpenSSL interface: * int intel_AES_set_encrypt_key(const unsigned char *userKey, * const int bits, AES_KEY *key); * int intel_AES_set_decrypt_key(const unsigned char *userKey, * const int bits, AES_KEY *key); * Return values for above are non-zero on error, 0 on success. * * void intel_AES_encrypt(const unsigned char *in, unsigned char *out, * const AES_KEY *key); * void intel_AES_decrypt(const unsigned char *in, unsigned char *out, * const AES_KEY *key); * typedef struct aes_key_st { * unsigned int rd_key[4 *(AES_MAXNR + 1)]; * int rounds; * unsigned int pad[3]; * } AES_KEY; * Note: AES_LONG is undefined (that is, Intel uses 32-bit key schedules * (ks32) instead of 64-bit (ks64). * Number of rounds (aka round count) is at offset 240 of AES_KEY. * * OpenSolaris OS interface (#ifdefs removed for readability): * int rijndael_key_setup_dec_intel(uint32_t rk[], * const uint32_t cipherKey[], uint64_t keyBits); * int rijndael_key_setup_enc_intel(uint32_t rk[], * const uint32_t cipherKey[], uint64_t keyBits); * Return values for above are 0 on error, number of rounds on success. * * void aes_encrypt_intel(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4]); * void aes_decrypt_intel(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4]); * typedef union {uint64_t ks64[(MAX_AES_NR + 1) * 4]; * uint32_t ks32[(MAX_AES_NR + 1) * 4]; } aes_ks_t; * * typedef union { * uint32_t ks32[((MAX_AES_NR) + 1) * (MAX_AES_NB)]; * } aes_ks_t; * typedef struct aes_key { * aes_ks_t encr_ks, decr_ks; * long double align128; * int flags, nr, type; * } aes_key_t; * * Note: ks is the AES key schedule, Nr is number of rounds, pt is plain text, * ct is crypto text, and MAX_AES_NR is 14. * For the x86 64-bit architecture, OpenSolaris OS uses ks32 instead of ks64. * * Note2: aes_ks_t must be aligned on a 0 mod 128 byte boundary. * * ==================================================================== */ #if defined(lint) || defined(__lint) #include /* ARGSUSED */ void aes_encrypt_intel(const uint32_t rk[], int Nr, const uint32_t pt[4], uint32_t ct[4]) { } /* ARGSUSED */ void aes_decrypt_intel(const uint32_t rk[], int Nr, const uint32_t ct[4], uint32_t pt[4]) { } /* ARGSUSED */ int rijndael_key_setup_enc_intel(uint32_t rk[], const uint32_t cipherKey[], uint64_t keyBits) { return (0); } /* ARGSUSED */ int rijndael_key_setup_dec_intel(uint32_t rk[], const uint32_t cipherKey[], uint64_t keyBits) { return (0); } #else /* lint */ #include #include #ifdef _KERNEL #include #endif #ifdef _KERNEL /* * Note: the CLTS macro clobbers P2 (%rsi) under i86xpv. That is, * it calls HYPERVISOR_fpu_taskswitch() which modifies %rsi when it * uses it to pass P2 to syscall. * This also occurs with the STTS macro, but we don't care if * P2 (%rsi) is modified just before function exit. * The CLTS and STTS macros push and pop P1 (%rdi) already. */ #ifdef __xpv #define PROTECTED_CLTS \ push %rsi; \ CLTS; \ pop %rsi #else #define PROTECTED_CLTS \ CLTS #endif /* __xpv */ #define CLEAR_TS_OR_PUSH_XMM0_XMM1(tmpreg) \ push %rbp; \ mov %rsp, %rbp; \ movq %cr0, tmpreg; \ testq $CR0_TS, tmpreg; \ jnz 1f; \ and $-XMM_ALIGN, %rsp; \ sub $[XMM_SIZE * 2], %rsp; \ movaps %xmm0, 16(%rsp); \ movaps %xmm1, (%rsp); \ jmp 2f; \ 1: \ PROTECTED_CLTS; \ 2: /* * If CR0_TS was not set above, pop %xmm0 and %xmm1 off stack, * otherwise set CR0_TS. */ #define SET_TS_OR_POP_XMM0_XMM1(tmpreg) \ testq $CR0_TS, tmpreg; \ jnz 1f; \ movaps (%rsp), %xmm1; \ movaps 16(%rsp), %xmm0; \ jmp 2f; \ 1: \ STTS(tmpreg); \ 2: \ mov %rbp, %rsp; \ pop %rbp /* * If CR0_TS is not set, align stack (with push %rbp) and push * %xmm0 - %xmm6 on stack, otherwise clear CR0_TS */ #define CLEAR_TS_OR_PUSH_XMM0_TO_XMM6(tmpreg) \ push %rbp; \ mov %rsp, %rbp; \ movq %cr0, tmpreg; \ testq $CR0_TS, tmpreg; \ jnz 1f; \ and $-XMM_ALIGN, %rsp; \ sub $[XMM_SIZE * 7], %rsp; \ movaps %xmm0, 96(%rsp); \ movaps %xmm1, 80(%rsp); \ movaps %xmm2, 64(%rsp); \ movaps %xmm3, 48(%rsp); \ movaps %xmm4, 32(%rsp); \ movaps %xmm5, 16(%rsp); \ movaps %xmm6, (%rsp); \ jmp 2f; \ 1: \ PROTECTED_CLTS; \ 2: /* * If CR0_TS was not set above, pop %xmm0 - %xmm6 off stack, * otherwise set CR0_TS. */ #define SET_TS_OR_POP_XMM0_TO_XMM6(tmpreg) \ testq $CR0_TS, tmpreg; \ jnz 1f; \ movaps (%rsp), %xmm6; \ movaps 16(%rsp), %xmm5; \ movaps 32(%rsp), %xmm4; \ movaps 48(%rsp), %xmm3; \ movaps 64(%rsp), %xmm2; \ movaps 80(%rsp), %xmm1; \ movaps 96(%rsp), %xmm0; \ jmp 2f; \ 1: \ STTS(tmpreg); \ 2: \ mov %rbp, %rsp; \ pop %rbp #else #define PROTECTED_CLTS #define CLEAR_TS_OR_PUSH_XMM0_XMM1(tmpreg) #define SET_TS_OR_POP_XMM0_XMM1(tmpreg) #define CLEAR_TS_OR_PUSH_XMM0_TO_XMM6(tmpreg) #define SET_TS_OR_POP_XMM0_TO_XMM6(tmpreg) #endif /* _KERNEL */ /* * _key_expansion_128(), * _key_expansion_192a(), _key_expansion_192b(), * _key_expansion_256a(), _key_expansion_256b() * * Helper functions called by rijndael_key_setup_inc_intel(). * Also used indirectly by rijndael_key_setup_dec_intel(). * * Input: * %xmm0 User-provided cipher key * %xmm1 Round constant * Output: * (%rcx) AES key */ .align 16 _key_expansion_128: _key_expansion_256a: pshufd $0b11111111, %xmm1, %xmm1 shufps $0b00010000, %xmm0, %xmm4 pxor %xmm4, %xmm0 shufps $0b10001100, %xmm0, %xmm4 pxor %xmm4, %xmm0 pxor %xmm1, %xmm0 movaps %xmm0, (%rcx) add $0x10, %rcx ret SET_SIZE(_key_expansion_128) SET_SIZE(_key_expansion_256a) .align 16 _key_expansion_192a: pshufd $0b01010101, %xmm1, %xmm1 shufps $0b00010000, %xmm0, %xmm4 pxor %xmm4, %xmm0 shufps $0b10001100, %xmm0, %xmm4 pxor %xmm4, %xmm0 pxor %xmm1, %xmm0 movaps %xmm2, %xmm5 movaps %xmm2, %xmm6 pslldq $4, %xmm5 pshufd $0b11111111, %xmm0, %xmm3 pxor %xmm3, %xmm2 pxor %xmm5, %xmm2 movaps %xmm0, %xmm1 shufps $0b01000100, %xmm0, %xmm6 movaps %xmm6, (%rcx) shufps $0b01001110, %xmm2, %xmm1 movaps %xmm1, 0x10(%rcx) add $0x20, %rcx ret SET_SIZE(_key_expansion_192a) .align 16 _key_expansion_192b: pshufd $0b01010101, %xmm1, %xmm1 shufps $0b00010000, %xmm0, %xmm4 pxor %xmm4, %xmm0 shufps $0b10001100, %xmm0, %xmm4 pxor %xmm4, %xmm0 pxor %xmm1, %xmm0 movaps %xmm2, %xmm5 pslldq $4, %xmm5 pshufd $0b11111111, %xmm0, %xmm3 pxor %xmm3, %xmm2 pxor %xmm5, %xmm2 movaps %xmm0, (%rcx) add $0x10, %rcx ret SET_SIZE(_key_expansion_192b) .align 16 _key_expansion_256b: pshufd $0b10101010, %xmm1, %xmm1 shufps $0b00010000, %xmm2, %xmm4 pxor %xmm4, %xmm2 shufps $0b10001100, %xmm2, %xmm4 pxor %xmm4, %xmm2 pxor %xmm1, %xmm2 movaps %xmm2, (%rcx) add $0x10, %rcx ret SET_SIZE(_key_expansion_256b) /* * rijndael_key_setup_enc_intel() * Expand the cipher key into the encryption key schedule. * * For kernel code, caller is responsible for ensuring kpreempt_disable() * has been called. This is because %xmm registers are not saved/restored. * Clear and set the CR0.TS bit on entry and exit, respectively, if TS is set * on entry. Otherwise, if TS is not set, save and restore %xmm registers * on the stack. * * OpenSolaris interface: * int rijndael_key_setup_enc_intel(uint32_t rk[], const uint32_t cipherKey[], * uint64_t keyBits); * Return value is 0 on error, number of rounds on success. * * Original Intel OpenSSL interface: * int intel_AES_set_encrypt_key(const unsigned char *userKey, * const int bits, AES_KEY *key); * Return value is non-zero on error, 0 on success. */ #ifdef OPENSSL_INTERFACE #define rijndael_key_setup_enc_intel intel_AES_set_encrypt_key #define rijndael_key_setup_dec_intel intel_AES_set_decrypt_key #define USERCIPHERKEY rdi /* P1, 64 bits */ #define KEYSIZE32 esi /* P2, 32 bits */ #define KEYSIZE64 rsi /* P2, 64 bits */ #define AESKEY rdx /* P3, 64 bits */ #else /* OpenSolaris Interface */ #define AESKEY rdi /* P1, 64 bits */ #define USERCIPHERKEY rsi /* P2, 64 bits */ #define KEYSIZE32 edx /* P3, 32 bits */ #define KEYSIZE64 rdx /* P3, 64 bits */ #endif /* OPENSSL_INTERFACE */ #define ROUNDS32 KEYSIZE32 /* temp */ #define ROUNDS64 KEYSIZE64 /* temp */ #define ENDAESKEY USERCIPHERKEY /* temp */ ENTRY_NP(rijndael_key_setup_enc_intel) CLEAR_TS_OR_PUSH_XMM0_TO_XMM6(%r10) / NULL pointer sanity check test %USERCIPHERKEY, %USERCIPHERKEY jz .Lenc_key_invalid_param test %AESKEY, %AESKEY jz .Lenc_key_invalid_param movups (%USERCIPHERKEY), %xmm0 / user key (first 16 bytes) movaps %xmm0, (%AESKEY) lea 0x10(%AESKEY), %rcx / key addr pxor %xmm4, %xmm4 / xmm4 is assumed 0 in _key_expansion_x cmp $256, %KEYSIZE32 jnz .Lenc_key192 / AES 256: 14 rounds in encryption key schedule #ifdef OPENSSL_INTERFACE mov $14, %ROUNDS32 movl %ROUNDS32, 240(%AESKEY) / key.rounds = 14 #endif /* OPENSSL_INTERFACE */ movups 0x10(%USERCIPHERKEY), %xmm2 / other user key (2nd 16 bytes) movaps %xmm2, (%rcx) add $0x10, %rcx aeskeygenassist $0x1, %xmm2, %xmm1 / expand the key call _key_expansion_256a aeskeygenassist $0x1, %xmm0, %xmm1 call _key_expansion_256b aeskeygenassist $0x2, %xmm2, %xmm1 / expand the key call _key_expansion_256a aeskeygenassist $0x2, %xmm0, %xmm1 call _key_expansion_256b aeskeygenassist $0x4, %xmm2, %xmm1 / expand the key call _key_expansion_256a aeskeygenassist $0x4, %xmm0, %xmm1 call _key_expansion_256b aeskeygenassist $0x8, %xmm2, %xmm1 / expand the key call _key_expansion_256a aeskeygenassist $0x8, %xmm0, %xmm1 call _key_expansion_256b aeskeygenassist $0x10, %xmm2, %xmm1 / expand the key call _key_expansion_256a aeskeygenassist $0x10, %xmm0, %xmm1 call _key_expansion_256b aeskeygenassist $0x20, %xmm2, %xmm1 / expand the key call _key_expansion_256a aeskeygenassist $0x20, %xmm0, %xmm1 call _key_expansion_256b aeskeygenassist $0x40, %xmm2, %xmm1 / expand the key call _key_expansion_256a SET_TS_OR_POP_XMM0_TO_XMM6(%r10) #ifdef OPENSSL_INTERFACE xor %rax, %rax / return 0 (OK) #else /* Open Solaris Interface */ mov $14, %rax / return # rounds = 14 #endif ret .align 4 .Lenc_key192: cmp $192, %KEYSIZE32 jnz .Lenc_key128 / AES 192: 12 rounds in encryption key schedule #ifdef OPENSSL_INTERFACE mov $12, %ROUNDS32 movl %ROUNDS32, 240(%AESKEY) / key.rounds = 12 #endif /* OPENSSL_INTERFACE */ movq 0x10(%USERCIPHERKEY), %xmm2 / other user key aeskeygenassist $0x1, %xmm2, %xmm1 / expand the key call _key_expansion_192a aeskeygenassist $0x2, %xmm2, %xmm1 / expand the key call _key_expansion_192b aeskeygenassist $0x4, %xmm2, %xmm1 / expand the key call _key_expansion_192a aeskeygenassist $0x8, %xmm2, %xmm1 / expand the key call _key_expansion_192b aeskeygenassist $0x10, %xmm2, %xmm1 / expand the key call _key_expansion_192a aeskeygenassist $0x20, %xmm2, %xmm1 / expand the key call _key_expansion_192b aeskeygenassist $0x40, %xmm2, %xmm1 / expand the key call _key_expansion_192a aeskeygenassist $0x80, %xmm2, %xmm1 / expand the key call _key_expansion_192b SET_TS_OR_POP_XMM0_TO_XMM6(%r10) #ifdef OPENSSL_INTERFACE xor %rax, %rax / return 0 (OK) #else /* OpenSolaris Interface */ mov $12, %rax / return # rounds = 12 #endif ret .align 4 .Lenc_key128: cmp $128, %KEYSIZE32 jnz .Lenc_key_invalid_key_bits / AES 128: 10 rounds in encryption key schedule #ifdef OPENSSL_INTERFACE mov $10, %ROUNDS32 movl %ROUNDS32, 240(%AESKEY) / key.rounds = 10 #endif /* OPENSSL_INTERFACE */ aeskeygenassist $0x1, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x2, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x4, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x8, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x10, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x20, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x40, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x80, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x1b, %xmm0, %xmm1 / expand the key call _key_expansion_128 aeskeygenassist $0x36, %xmm0, %xmm1 / expand the key call _key_expansion_128 SET_TS_OR_POP_XMM0_TO_XMM6(%r10) #ifdef OPENSSL_INTERFACE xor %rax, %rax / return 0 (OK) #else /* OpenSolaris Interface */ mov $10, %rax / return # rounds = 10 #endif ret .Lenc_key_invalid_param: #ifdef OPENSSL_INTERFACE SET_TS_OR_POP_XMM0_TO_XMM6(%r10) mov $-1, %rax / user key or AES key pointer is NULL ret #else /* FALLTHROUGH */ #endif /* OPENSSL_INTERFACE */ .Lenc_key_invalid_key_bits: SET_TS_OR_POP_XMM0_TO_XMM6(%r10) #ifdef OPENSSL_INTERFACE mov $-2, %rax / keysize is invalid #else /* Open Solaris Interface */ xor %rax, %rax / a key pointer is NULL or invalid keysize #endif /* OPENSSL_INTERFACE */ ret SET_SIZE(rijndael_key_setup_enc_intel) /* * rijndael_key_setup_dec_intel() * Expand the cipher key into the decryption key schedule. * * For kernel code, caller is responsible for ensuring kpreempt_disable() * has been called. This is because %xmm registers are not saved/restored. * Clear and set the CR0.TS bit on entry and exit, respectively, if TS is set * on entry. Otherwise, if TS is not set, save and restore %xmm registers * on the stack. * * OpenSolaris interface: * int rijndael_key_setup_dec_intel(uint32_t rk[], const uint32_t cipherKey[], * uint64_t keyBits); * Return value is 0 on error, number of rounds on success. * P1->P2, P2->P3, P3->P1 * * Original Intel OpenSSL interface: * int intel_AES_set_decrypt_key(const unsigned char *userKey, * const int bits, AES_KEY *key); * Return value is non-zero on error, 0 on success. */ ENTRY_NP(rijndael_key_setup_dec_intel) / Generate round keys used for encryption call rijndael_key_setup_enc_intel@PLT test %rax, %rax #ifdef OPENSSL_INTERFACE jnz .Ldec_key_exit / Failed if returned non-0 #else /* OpenSolaris Interface */ jz .Ldec_key_exit / Failed if returned 0 #endif /* OPENSSL_INTERFACE */ CLEAR_TS_OR_PUSH_XMM0_XMM1(%r10) /* * Convert round keys used for encryption * to a form usable for decryption */ #ifndef OPENSSL_INTERFACE /* OpenSolaris Interface */ mov %rax, %ROUNDS64 / set # rounds (10, 12, or 14) / (already set for OpenSSL) #endif lea 0x10(%AESKEY), %rcx / key addr shl $4, %ROUNDS32 add %AESKEY, %ROUNDS64 mov %ROUNDS64, %ENDAESKEY .align 4 .Ldec_key_reorder_loop: movaps (%AESKEY), %xmm0 movaps (%ROUNDS64), %xmm1 movaps %xmm0, (%ROUNDS64) movaps %xmm1, (%AESKEY) lea 0x10(%AESKEY), %AESKEY lea -0x10(%ROUNDS64), %ROUNDS64 cmp %AESKEY, %ROUNDS64 ja .Ldec_key_reorder_loop .align 4 .Ldec_key_inv_loop: movaps (%rcx), %xmm0 / Convert an encryption round key to a form usable for decryption / with the "AES Inverse Mix Columns" instruction aesimc %xmm0, %xmm1 movaps %xmm1, (%rcx) lea 0x10(%rcx), %rcx cmp %ENDAESKEY, %rcx jnz .Ldec_key_inv_loop SET_TS_OR_POP_XMM0_XMM1(%r10) .Ldec_key_exit: / OpenSolaris: rax = # rounds (10, 12, or 14) or 0 for error / OpenSSL: rax = 0 for OK, or non-zero for error ret SET_SIZE(rijndael_key_setup_dec_intel) /* * aes_encrypt_intel() * Encrypt a single block (in and out can overlap). * * For kernel code, caller is responsible for ensuring kpreempt_disable() * has been called. This is because %xmm registers are not saved/restored. * Clear and set the CR0.TS bit on entry and exit, respectively, if TS is set * on entry. Otherwise, if TS is not set, save and restore %xmm registers * on the stack. * * Temporary register usage: * %xmm0 State * %xmm1 Key * * Original OpenSolaris Interface: * void aes_encrypt_intel(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4]) * * Original Intel OpenSSL Interface: * void intel_AES_encrypt(const unsigned char *in, unsigned char *out, * const AES_KEY *key) */ #ifdef OPENSSL_INTERFACE #define aes_encrypt_intel intel_AES_encrypt #define aes_decrypt_intel intel_AES_decrypt #define INP rdi /* P1, 64 bits */ #define OUTP rsi /* P2, 64 bits */ #define KEYP rdx /* P3, 64 bits */ /* No NROUNDS parameter--offset 240 from KEYP saved in %ecx: */ #define NROUNDS32 ecx /* temporary, 32 bits */ #define NROUNDS cl /* temporary, 8 bits */ #else /* OpenSolaris Interface */ #define KEYP rdi /* P1, 64 bits */ #define NROUNDS esi /* P2, 32 bits */ #define INP rdx /* P3, 64 bits */ #define OUTP rcx /* P4, 64 bits */ #endif /* OPENSSL_INTERFACE */ #define STATE xmm0 /* temporary, 128 bits */ #define KEY xmm1 /* temporary, 128 bits */ ENTRY_NP(aes_encrypt_intel) CLEAR_TS_OR_PUSH_XMM0_XMM1(%r10) movups (%INP), %STATE / input movaps (%KEYP), %KEY / key #ifdef OPENSSL_INTERFACE mov 240(%KEYP), %NROUNDS32 / round count #else /* OpenSolaris Interface */ /* Round count is already present as P2 in %rsi/%esi */ #endif /* OPENSSL_INTERFACE */ pxor %KEY, %STATE / round 0 lea 0x30(%KEYP), %KEYP cmp $12, %NROUNDS jb .Lenc128 lea 0x20(%KEYP), %KEYP je .Lenc192 / AES 256 lea 0x20(%KEYP), %KEYP movaps -0x60(%KEYP), %KEY aesenc %KEY, %STATE movaps -0x50(%KEYP), %KEY aesenc %KEY, %STATE .align 4 .Lenc192: / AES 192 and 256 movaps -0x40(%KEYP), %KEY aesenc %KEY, %STATE movaps -0x30(%KEYP), %KEY aesenc %KEY, %STATE .align 4 .Lenc128: / AES 128, 192, and 256 movaps -0x20(%KEYP), %KEY aesenc %KEY, %STATE movaps -0x10(%KEYP), %KEY aesenc %KEY, %STATE movaps (%KEYP), %KEY aesenc %KEY, %STATE movaps 0x10(%KEYP), %KEY aesenc %KEY, %STATE movaps 0x20(%KEYP), %KEY aesenc %KEY, %STATE movaps 0x30(%KEYP), %KEY aesenc %KEY, %STATE movaps 0x40(%KEYP), %KEY aesenc %KEY, %STATE movaps 0x50(%KEYP), %KEY aesenc %KEY, %STATE movaps 0x60(%KEYP), %KEY aesenc %KEY, %STATE movaps 0x70(%KEYP), %KEY aesenclast %KEY, %STATE / last round movups %STATE, (%OUTP) / output SET_TS_OR_POP_XMM0_XMM1(%r10) ret SET_SIZE(aes_encrypt_intel) /* * aes_decrypt_intel() * Decrypt a single block (in and out can overlap). * * For kernel code, caller is responsible for ensuring kpreempt_disable() * has been called. This is because %xmm registers are not saved/restored. * Clear and set the CR0.TS bit on entry and exit, respectively, if TS is set * on entry. Otherwise, if TS is not set, save and restore %xmm registers * on the stack. * * Temporary register usage: * %xmm0 State * %xmm1 Key * * Original OpenSolaris Interface: * void aes_decrypt_intel(const aes_ks_t *ks, int Nr, * const uint32_t pt[4], uint32_t ct[4])/ * * Original Intel OpenSSL Interface: * void intel_AES_decrypt(const unsigned char *in, unsigned char *out, * const AES_KEY *key); */ ENTRY_NP(aes_decrypt_intel) CLEAR_TS_OR_PUSH_XMM0_XMM1(%r10) movups (%INP), %STATE / input movaps (%KEYP), %KEY / key #ifdef OPENSSL_INTERFACE mov 240(%KEYP), %NROUNDS32 / round count #else /* OpenSolaris Interface */ /* Round count is already present as P2 in %rsi/%esi */ #endif /* OPENSSL_INTERFACE */ pxor %KEY, %STATE / round 0 lea 0x30(%KEYP), %KEYP cmp $12, %NROUNDS jb .Ldec128 lea 0x20(%KEYP), %KEYP je .Ldec192 / AES 256 lea 0x20(%KEYP), %KEYP movaps -0x60(%KEYP), %KEY aesdec %KEY, %STATE movaps -0x50(%KEYP), %KEY aesdec %KEY, %STATE .align 4 .Ldec192: / AES 192 and 256 movaps -0x40(%KEYP), %KEY aesdec %KEY, %STATE movaps -0x30(%KEYP), %KEY aesdec %KEY, %STATE .align 4 .Ldec128: / AES 128, 192, and 256 movaps -0x20(%KEYP), %KEY aesdec %KEY, %STATE movaps -0x10(%KEYP), %KEY aesdec %KEY, %STATE movaps (%KEYP), %KEY aesdec %KEY, %STATE movaps 0x10(%KEYP), %KEY aesdec %KEY, %STATE movaps 0x20(%KEYP), %KEY aesdec %KEY, %STATE movaps 0x30(%KEYP), %KEY aesdec %KEY, %STATE movaps 0x40(%KEYP), %KEY aesdec %KEY, %STATE movaps 0x50(%KEYP), %KEY aesdec %KEY, %STATE movaps 0x60(%KEYP), %KEY aesdec %KEY, %STATE movaps 0x70(%KEYP), %KEY aesdeclast %KEY, %STATE / last round movups %STATE, (%OUTP) / output SET_TS_OR_POP_XMM0_XMM1(%r10) ret SET_SIZE(aes_decrypt_intel) #endif /* lint || __lint */ /* * --------------------------------------------------------------------------- * Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. * * LICENSE TERMS * * The free distribution and use of this software is allowed (with or without * changes) provided that: * * 1. source code distributions include the above copyright notice, this * list of conditions and the following disclaimer; * * 2. binary distributions include the above copyright notice, this list * of conditions and the following disclaimer in their documentation; * * 3. the name of the copyright holder is not used to endorse products * built using this software without specific written permission. * * DISCLAIMER * * This software is provided 'as is' with no explicit or implied warranties * in respect of its properties, including, but not limited to, correctness * and/or fitness for purpose. * --------------------------------------------------------------------------- * Issue Date: 20/12/2007 */ #include "aes_impl.h" #include "aesopt.h" #include "aestab.h" #include "aestab2.h" /* * Initialise the key schedule from the user supplied key. The key * length can be specified in bytes, with legal values of 16, 24 * and 32, or in bits, with legal values of 128, 192 and 256. These * values correspond with Nk values of 4, 6 and 8 respectively. * * The following macros implement a single cycle in the key * schedule generation process. The number of cycles needed * for each cx->n_col and nk value is: * * nk = 4 5 6 7 8 * ------------------------------ * cx->n_col = 4 10 9 8 7 7 * cx->n_col = 5 14 11 10 9 9 * cx->n_col = 6 19 15 12 11 11 * cx->n_col = 7 21 19 16 13 14 * cx->n_col = 8 29 23 19 17 14 */ /* * OpenSolaris changes * 1. Added header files aes_impl.h and aestab2.h * 2. Changed uint_8t and uint_32t to uint8_t and uint32_t * 3. Remove code under ifdef USE_VIA_ACE_IF_PRESENT (always undefined) * 4. Removed always-defined ifdefs FUNCS_IN_C, ENC_KEYING_IN_C, * AES_128, AES_192, AES_256, AES_VAR defines * 5. Changed aes_encrypt_key* aes_decrypt_key* functions to "static void" * 6. Changed N_COLS to MAX_AES_NB * 7. Replaced functions aes_encrypt_key and aes_decrypt_key with * OpenSolaris-compatible functions rijndael_key_setup_enc_amd64 and * rijndael_key_setup_dec_amd64 * 8. cstyled code and removed lint warnings */ #if defined(REDUCE_CODE_SIZE) #define ls_box ls_sub uint32_t ls_sub(const uint32_t t, const uint32_t n); #define inv_mcol im_sub uint32_t im_sub(const uint32_t x); #ifdef ENC_KS_UNROLL #undef ENC_KS_UNROLL #endif #ifdef DEC_KS_UNROLL #undef DEC_KS_UNROLL #endif #endif /* REDUCE_CODE_SIZE */ #define ke4(k, i) \ { k[4 * (i) + 4] = ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \ k[4 * (i) + 5] = ss[1] ^= ss[0]; \ k[4 * (i) + 6] = ss[2] ^= ss[1]; \ k[4 * (i) + 7] = ss[3] ^= ss[2]; \ } static void aes_encrypt_key128(const unsigned char *key, uint32_t rk[]) { uint32_t ss[4]; rk[0] = ss[0] = word_in(key, 0); rk[1] = ss[1] = word_in(key, 1); rk[2] = ss[2] = word_in(key, 2); rk[3] = ss[3] = word_in(key, 3); #ifdef ENC_KS_UNROLL ke4(rk, 0); ke4(rk, 1); ke4(rk, 2); ke4(rk, 3); ke4(rk, 4); ke4(rk, 5); ke4(rk, 6); ke4(rk, 7); ke4(rk, 8); #else { uint32_t i; for (i = 0; i < 9; ++i) ke4(rk, i); } #endif /* ENC_KS_UNROLL */ ke4(rk, 9); } #define kef6(k, i) \ { k[6 * (i) + 6] = ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \ k[6 * (i) + 7] = ss[1] ^= ss[0]; \ k[6 * (i) + 8] = ss[2] ^= ss[1]; \ k[6 * (i) + 9] = ss[3] ^= ss[2]; \ } #define ke6(k, i) \ { kef6(k, i); \ k[6 * (i) + 10] = ss[4] ^= ss[3]; \ k[6 * (i) + 11] = ss[5] ^= ss[4]; \ } static void aes_encrypt_key192(const unsigned char *key, uint32_t rk[]) { uint32_t ss[6]; rk[0] = ss[0] = word_in(key, 0); rk[1] = ss[1] = word_in(key, 1); rk[2] = ss[2] = word_in(key, 2); rk[3] = ss[3] = word_in(key, 3); rk[4] = ss[4] = word_in(key, 4); rk[5] = ss[5] = word_in(key, 5); #ifdef ENC_KS_UNROLL ke6(rk, 0); ke6(rk, 1); ke6(rk, 2); ke6(rk, 3); ke6(rk, 4); ke6(rk, 5); ke6(rk, 6); #else { uint32_t i; for (i = 0; i < 7; ++i) ke6(rk, i); } #endif /* ENC_KS_UNROLL */ kef6(rk, 7); } #define kef8(k, i) \ { k[8 * (i) + 8] = ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \ k[8 * (i) + 9] = ss[1] ^= ss[0]; \ k[8 * (i) + 10] = ss[2] ^= ss[1]; \ k[8 * (i) + 11] = ss[3] ^= ss[2]; \ } #define ke8(k, i) \ { kef8(k, i); \ k[8 * (i) + 12] = ss[4] ^= ls_box(ss[3], 0); \ k[8 * (i) + 13] = ss[5] ^= ss[4]; \ k[8 * (i) + 14] = ss[6] ^= ss[5]; \ k[8 * (i) + 15] = ss[7] ^= ss[6]; \ } static void aes_encrypt_key256(const unsigned char *key, uint32_t rk[]) { uint32_t ss[8]; rk[0] = ss[0] = word_in(key, 0); rk[1] = ss[1] = word_in(key, 1); rk[2] = ss[2] = word_in(key, 2); rk[3] = ss[3] = word_in(key, 3); rk[4] = ss[4] = word_in(key, 4); rk[5] = ss[5] = word_in(key, 5); rk[6] = ss[6] = word_in(key, 6); rk[7] = ss[7] = word_in(key, 7); #ifdef ENC_KS_UNROLL ke8(rk, 0); ke8(rk, 1); ke8(rk, 2); ke8(rk, 3); ke8(rk, 4); ke8(rk, 5); #else { uint32_t i; for (i = 0; i < 6; ++i) ke8(rk, i); } #endif /* ENC_KS_UNROLL */ kef8(rk, 6); } /* * Expand the cipher key into the encryption key schedule. * * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4 * (Nr + 1). * * Parameters: * rk AES key schedule 32-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ int rijndael_key_setup_enc_amd64(uint32_t rk[], const uint32_t cipherKey[], int keyBits) { switch (keyBits) { case 128: aes_encrypt_key128((unsigned char *)&cipherKey[0], rk); return (10); case 192: aes_encrypt_key192((unsigned char *)&cipherKey[0], rk); return (12); case 256: aes_encrypt_key256((unsigned char *)&cipherKey[0], rk); return (14); default: /* should never get here */ break; } return (0); } /* this is used to store the decryption round keys */ /* in forward or reverse order */ #ifdef AES_REV_DKS #define v(n, i) ((n) - (i) + 2 * ((i) & 3)) #else #define v(n, i) (i) #endif #if DEC_ROUND == NO_TABLES #define ff(x) (x) #else #define ff(x) inv_mcol(x) #if defined(dec_imvars) #define d_vars dec_imvars #endif #endif /* FUNCS_IN_C & DEC_KEYING_IN_C */ #define k4e(k, i) \ { k[v(40, (4 * (i)) + 4)] = ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \ k[v(40, (4 * (i)) + 5)] = ss[1] ^= ss[0]; \ k[v(40, (4 * (i)) + 6)] = ss[2] ^= ss[1]; \ k[v(40, (4 * (i)) + 7)] = ss[3] ^= ss[2]; \ } #if 1 #define kdf4(k, i) \ { ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ ss[1] = ss[1] ^ ss[3]; \ ss[2] = ss[2] ^ ss[3]; \ ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ t_use(r, c)[i]; \ ss[i % 4] ^= ss[4]; \ ss[4] ^= k[v(40, (4 * (i)))]; k[v(40, (4 * (i)) + 4)] = ff(ss[4]); \ ss[4] ^= k[v(40, (4 * (i)) + 1)]; k[v(40, (4 * (i)) + 5)] = ff(ss[4]); \ ss[4] ^= k[v(40, (4 * (i)) + 2)]; k[v(40, (4 * (i)) + 6)] = ff(ss[4]); \ ss[4] ^= k[v(40, (4 * (i)) + 3)]; k[v(40, (4 * (i)) + 7)] = ff(ss[4]); \ } #define kd4(k, i) \ { ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ t_use(r, c)[i]; \ ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ k[v(40, (4 * (i)) + 4)] = ss[4] ^= k[v(40, (4 * (i)))]; \ k[v(40, (4 * (i)) + 5)] = ss[4] ^= k[v(40, (4 * (i)) + 1)]; \ k[v(40, (4 * (i)) + 6)] = ss[4] ^= k[v(40, (4 * (i)) + 2)]; \ k[v(40, (4 * (i)) + 7)] = ss[4] ^= k[v(40, (4 * (i)) + 3)]; \ } #define kdl4(k, i) \ { ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ t_use(r, c)[i]; \ ss[i % 4] ^= ss[4]; \ k[v(40, (4 * (i)) + 4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ k[v(40, (4 * (i)) + 5)] = ss[1] ^ ss[3]; \ k[v(40, (4 * (i)) + 6)] = ss[0]; \ k[v(40, (4 * (i)) + 7)] = ss[1]; \ } #else #define kdf4(k, i) \ { ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \ k[v(40, (4 * (i)) + 4)] = ff(ss[0]); \ ss[1] ^= ss[0]; k[v(40, (4 * (i)) + 5)] = ff(ss[1]); \ ss[2] ^= ss[1]; k[v(40, (4 * (i)) + 6)] = ff(ss[2]); \ ss[3] ^= ss[2]; k[v(40, (4 * (i)) + 7)] = ff(ss[3]); \ } #define kd4(k, i) \ { ss[4] = ls_box(ss[3], 3) ^ t_use(r, c)[i]; \ ss[0] ^= ss[4]; \ ss[4] = ff(ss[4]); \ k[v(40, (4 * (i)) + 4)] = ss[4] ^= k[v(40, (4 * (i)))]; \ ss[1] ^= ss[0]; \ k[v(40, (4 * (i)) + 5)] = ss[4] ^= k[v(40, (4 * (i)) + 1)]; \ ss[2] ^= ss[1]; \ k[v(40, (4 * (i)) + 6)] = ss[4] ^= k[v(40, (4 * (i)) + 2)]; \ ss[3] ^= ss[2]; \ k[v(40, (4 * (i)) + 7)] = ss[4] ^= k[v(40, (4 * (i)) + 3)]; \ } #define kdl4(k, i) \ { ss[0] ^= ls_box(ss[3], 3) ^ t_use(r, c)[i]; \ k[v(40, (4 * (i)) + 4)] = ss[0]; \ ss[1] ^= ss[0]; k[v(40, (4 * (i)) + 5)] = ss[1]; \ ss[2] ^= ss[1]; k[v(40, (4 * (i)) + 6)] = ss[2]; \ ss[3] ^= ss[2]; k[v(40, (4 * (i)) + 7)] = ss[3]; \ } #endif static void aes_decrypt_key128(const unsigned char *key, uint32_t rk[]) { uint32_t ss[5]; #if defined(d_vars) d_vars; #endif rk[v(40, (0))] = ss[0] = word_in(key, 0); rk[v(40, (1))] = ss[1] = word_in(key, 1); rk[v(40, (2))] = ss[2] = word_in(key, 2); rk[v(40, (3))] = ss[3] = word_in(key, 3); #ifdef DEC_KS_UNROLL kdf4(rk, 0); kd4(rk, 1); kd4(rk, 2); kd4(rk, 3); kd4(rk, 4); kd4(rk, 5); kd4(rk, 6); kd4(rk, 7); kd4(rk, 8); kdl4(rk, 9); #else { uint32_t i; for (i = 0; i < 10; ++i) k4e(rk, i); #if !(DEC_ROUND == NO_TABLES) for (i = MAX_AES_NB; i < 10 * MAX_AES_NB; ++i) rk[i] = inv_mcol(rk[i]); #endif } #endif /* DEC_KS_UNROLL */ } #define k6ef(k, i) \ { k[v(48, (6 * (i)) + 6)] = ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \ k[v(48, (6 * (i)) + 7)] = ss[1] ^= ss[0]; \ k[v(48, (6 * (i)) + 8)] = ss[2] ^= ss[1]; \ k[v(48, (6 * (i)) + 9)] = ss[3] ^= ss[2]; \ } #define k6e(k, i) \ { k6ef(k, i); \ k[v(48, (6 * (i)) + 10)] = ss[4] ^= ss[3]; \ k[v(48, (6 * (i)) + 11)] = ss[5] ^= ss[4]; \ } #define kdf6(k, i) \ { ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \ k[v(48, (6 * (i)) + 6)] = ff(ss[0]); \ ss[1] ^= ss[0]; k[v(48, (6 * (i)) + 7)] = ff(ss[1]); \ ss[2] ^= ss[1]; k[v(48, (6 * (i)) + 8)] = ff(ss[2]); \ ss[3] ^= ss[2]; k[v(48, (6 * (i)) + 9)] = ff(ss[3]); \ ss[4] ^= ss[3]; k[v(48, (6 * (i)) + 10)] = ff(ss[4]); \ ss[5] ^= ss[4]; k[v(48, (6 * (i)) + 11)] = ff(ss[5]); \ } #define kd6(k, i) \ { ss[6] = ls_box(ss[5], 3) ^ t_use(r, c)[i]; \ ss[0] ^= ss[6]; ss[6] = ff(ss[6]); \ k[v(48, (6 * (i)) + 6)] = ss[6] ^= k[v(48, (6 * (i)))]; \ ss[1] ^= ss[0]; \ k[v(48, (6 * (i)) + 7)] = ss[6] ^= k[v(48, (6 * (i)) + 1)]; \ ss[2] ^= ss[1]; \ k[v(48, (6 * (i)) + 8)] = ss[6] ^= k[v(48, (6 * (i)) + 2)]; \ ss[3] ^= ss[2]; \ k[v(48, (6 * (i)) + 9)] = ss[6] ^= k[v(48, (6 * (i)) + 3)]; \ ss[4] ^= ss[3]; \ k[v(48, (6 * (i)) + 10)] = ss[6] ^= k[v(48, (6 * (i)) + 4)]; \ ss[5] ^= ss[4]; \ k[v(48, (6 * (i)) + 11)] = ss[6] ^= k[v(48, (6 * (i)) + 5)]; \ } #define kdl6(k, i) \ { ss[0] ^= ls_box(ss[5], 3) ^ t_use(r, c)[i]; \ k[v(48, (6 * (i)) + 6)] = ss[0]; \ ss[1] ^= ss[0]; k[v(48, (6 * (i)) + 7)] = ss[1]; \ ss[2] ^= ss[1]; k[v(48, (6 * (i)) + 8)] = ss[2]; \ ss[3] ^= ss[2]; k[v(48, (6 * (i)) + 9)] = ss[3]; \ } static void aes_decrypt_key192(const unsigned char *key, uint32_t rk[]) { uint32_t ss[7]; #if defined(d_vars) d_vars; #endif rk[v(48, (0))] = ss[0] = word_in(key, 0); rk[v(48, (1))] = ss[1] = word_in(key, 1); rk[v(48, (2))] = ss[2] = word_in(key, 2); rk[v(48, (3))] = ss[3] = word_in(key, 3); #ifdef DEC_KS_UNROLL ss[4] = word_in(key, 4); rk[v(48, (4))] = ff(ss[4]); ss[5] = word_in(key, 5); rk[v(48, (5))] = ff(ss[5]); kdf6(rk, 0); kd6(rk, 1); kd6(rk, 2); kd6(rk, 3); kd6(rk, 4); kd6(rk, 5); kd6(rk, 6); kdl6(rk, 7); #else rk[v(48, (4))] = ss[4] = word_in(key, 4); rk[v(48, (5))] = ss[5] = word_in(key, 5); { uint32_t i; for (i = 0; i < 7; ++i) k6e(rk, i); k6ef(rk, 7); #if !(DEC_ROUND == NO_TABLES) for (i = MAX_AES_NB; i < 12 * MAX_AES_NB; ++i) rk[i] = inv_mcol(rk[i]); #endif } #endif } #define k8ef(k, i) \ { k[v(56, (8 * (i)) + 8)] = ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \ k[v(56, (8 * (i)) + 9)] = ss[1] ^= ss[0]; \ k[v(56, (8 * (i)) + 10)] = ss[2] ^= ss[1]; \ k[v(56, (8 * (i)) + 11)] = ss[3] ^= ss[2]; \ } #define k8e(k, i) \ { k8ef(k, i); \ k[v(56, (8 * (i)) + 12)] = ss[4] ^= ls_box(ss[3], 0); \ k[v(56, (8 * (i)) + 13)] = ss[5] ^= ss[4]; \ k[v(56, (8 * (i)) + 14)] = ss[6] ^= ss[5]; \ k[v(56, (8 * (i)) + 15)] = ss[7] ^= ss[6]; \ } #define kdf8(k, i) \ { ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \ k[v(56, (8 * (i)) + 8)] = ff(ss[0]); \ ss[1] ^= ss[0]; k[v(56, (8 * (i)) + 9)] = ff(ss[1]); \ ss[2] ^= ss[1]; k[v(56, (8 * (i)) + 10)] = ff(ss[2]); \ ss[3] ^= ss[2]; k[v(56, (8 * (i)) + 11)] = ff(ss[3]); \ ss[4] ^= ls_box(ss[3], 0); k[v(56, (8 * (i)) + 12)] = ff(ss[4]); \ ss[5] ^= ss[4]; k[v(56, (8 * (i)) + 13)] = ff(ss[5]); \ ss[6] ^= ss[5]; k[v(56, (8 * (i)) + 14)] = ff(ss[6]); \ ss[7] ^= ss[6]; k[v(56, (8 * (i)) + 15)] = ff(ss[7]); \ } #define kd8(k, i) \ { ss[8] = ls_box(ss[7], 3) ^ t_use(r, c)[i]; \ ss[0] ^= ss[8]; \ ss[8] = ff(ss[8]); \ k[v(56, (8 * (i)) + 8)] = ss[8] ^= k[v(56, (8 * (i)))]; \ ss[1] ^= ss[0]; \ k[v(56, (8 * (i)) + 9)] = ss[8] ^= k[v(56, (8 * (i)) + 1)]; \ ss[2] ^= ss[1]; \ k[v(56, (8 * (i)) + 10)] = ss[8] ^= k[v(56, (8 * (i)) + 2)]; \ ss[3] ^= ss[2]; \ k[v(56, (8 * (i)) + 11)] = ss[8] ^= k[v(56, (8 * (i)) + 3)]; \ ss[8] = ls_box(ss[3], 0); \ ss[4] ^= ss[8]; \ ss[8] = ff(ss[8]); \ k[v(56, (8 * (i)) + 12)] = ss[8] ^= k[v(56, (8 * (i)) + 4)]; \ ss[5] ^= ss[4]; \ k[v(56, (8 * (i)) + 13)] = ss[8] ^= k[v(56, (8 * (i)) + 5)]; \ ss[6] ^= ss[5]; \ k[v(56, (8 * (i)) + 14)] = ss[8] ^= k[v(56, (8 * (i)) + 6)]; \ ss[7] ^= ss[6]; \ k[v(56, (8 * (i)) + 15)] = ss[8] ^= k[v(56, (8 * (i)) + 7)]; \ } #define kdl8(k, i) \ { ss[0] ^= ls_box(ss[7], 3) ^ t_use(r, c)[i]; \ k[v(56, (8 * (i)) + 8)] = ss[0]; \ ss[1] ^= ss[0]; k[v(56, (8 * (i)) + 9)] = ss[1]; \ ss[2] ^= ss[1]; k[v(56, (8 * (i)) + 10)] = ss[2]; \ ss[3] ^= ss[2]; k[v(56, (8 * (i)) + 11)] = ss[3]; \ } static void aes_decrypt_key256(const unsigned char *key, uint32_t rk[]) { uint32_t ss[9]; #if defined(d_vars) d_vars; #endif rk[v(56, (0))] = ss[0] = word_in(key, 0); rk[v(56, (1))] = ss[1] = word_in(key, 1); rk[v(56, (2))] = ss[2] = word_in(key, 2); rk[v(56, (3))] = ss[3] = word_in(key, 3); #ifdef DEC_KS_UNROLL ss[4] = word_in(key, 4); rk[v(56, (4))] = ff(ss[4]); ss[5] = word_in(key, 5); rk[v(56, (5))] = ff(ss[5]); ss[6] = word_in(key, 6); rk[v(56, (6))] = ff(ss[6]); ss[7] = word_in(key, 7); rk[v(56, (7))] = ff(ss[7]); kdf8(rk, 0); kd8(rk, 1); kd8(rk, 2); kd8(rk, 3); kd8(rk, 4); kd8(rk, 5); kdl8(rk, 6); #else rk[v(56, (4))] = ss[4] = word_in(key, 4); rk[v(56, (5))] = ss[5] = word_in(key, 5); rk[v(56, (6))] = ss[6] = word_in(key, 6); rk[v(56, (7))] = ss[7] = word_in(key, 7); { uint32_t i; for (i = 0; i < 6; ++i) k8e(rk, i); k8ef(rk, 6); #if !(DEC_ROUND == NO_TABLES) for (i = MAX_AES_NB; i < 14 * MAX_AES_NB; ++i) rk[i] = inv_mcol(rk[i]); #endif } #endif /* DEC_KS_UNROLL */ } /* * Expand the cipher key into the decryption key schedule. * * Return the number of rounds for the given cipher key size. * The size of the key schedule depends on the number of rounds * (which can be computed from the size of the key), i.e. 4 * (Nr + 1). * * Parameters: * rk AES key schedule 32-bit array to be initialized * cipherKey User key * keyBits AES key size (128, 192, or 256 bits) */ int rijndael_key_setup_dec_amd64(uint32_t rk[], const uint32_t cipherKey[], int keyBits) { switch (keyBits) { case 128: aes_decrypt_key128((unsigned char *)&cipherKey[0], rk); return (10); case 192: aes_decrypt_key192((unsigned char *)&cipherKey[0], rk); return (12); case 256: aes_decrypt_key256((unsigned char *)&cipherKey[0], rk); return (14); default: /* should never get here */ break; } return (0); } /* * --------------------------------------------------------------------------- * Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. * * LICENSE TERMS * * The free distribution and use of this software is allowed (with or without * changes) provided that: * * 1. source code distributions include the above copyright notice, this * list of conditions and the following disclaimer; * * 2. binary distributions include the above copyright notice, this list * of conditions and the following disclaimer in their documentation; * * 3. the name of the copyright holder is not used to endorse products * built using this software without specific written permission. * * DISCLAIMER * * This software is provided 'as is' with no explicit or implied warranties * in respect of its properties, including, but not limited to, correctness * and/or fitness for purpose. * --------------------------------------------------------------------------- * Issue Date: 20/12/2007 * * This file contains the compilation options for AES (Rijndael) and code * that is common across encryption, key scheduling and table generation. * * OPERATION * * These source code files implement the AES algorithm Rijndael designed by * Joan Daemen and Vincent Rijmen. This version is designed for the standard * block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 * and 32 bytes). * * This version is designed for flexibility and speed using operations on * 32-bit words rather than operations on bytes. It can be compiled with * either big or little endian internal byte order but is faster when the * native byte order for the processor is used. * * THE CIPHER INTERFACE * * The cipher interface is implemented as an array of bytes in which lower * AES bit sequence indexes map to higher numeric significance within bytes. */ /* * OpenSolaris changes * 1. Added __cplusplus and _AESTAB_H header guards * 2. Added header files sys/types.h and aes_impl.h * 3. Added defines for AES_ENCRYPT, AES_DECRYPT, AES_REV_DKS, and ASM_AMD64_C * 4. Moved defines for IS_BIG_ENDIAN, IS_LITTLE_ENDIAN, PLATFORM_BYTE_ORDER * from brg_endian.h * 5. Undefined VIA_ACE_POSSIBLE and ASSUME_VIA_ACE_PRESENT * 6. Changed uint_8t and uint_32t to uint8_t and uint32_t * 7. Defined aes_sw32 as htonl() for byte swapping * 8. Cstyled and hdrchk code * */ #ifndef _AESOPT_H #define _AESOPT_H #ifdef __cplusplus extern "C" { #endif #include #include #include /* SUPPORT FEATURES */ #define AES_ENCRYPT /* if support for encryption is needed */ #define AES_DECRYPT /* if support for decryption is needed */ /* PLATFORM-SPECIFIC FEATURES */ #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ #define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #define AES_REV_DKS /* define to reverse decryption key schedule */ /* * CONFIGURATION - THE USE OF DEFINES * Later in this section there are a number of defines that control the * operation of the code. In each section, the purpose of each define is * explained so that the relevant form can be included or excluded by * setting either 1's or 0's respectively on the branches of the related * #if clauses. The following local defines should not be changed. */ #define ENCRYPTION_IN_C 1 #define DECRYPTION_IN_C 2 #define ENC_KEYING_IN_C 4 #define DEC_KEYING_IN_C 8 #define NO_TABLES 0 #define ONE_TABLE 1 #define FOUR_TABLES 4 #define NONE 0 #define PARTIAL 1 #define FULL 2 /* --- START OF USER CONFIGURED OPTIONS --- */ /* * 1. BYTE ORDER WITHIN 32 BIT WORDS * * The fundamental data processing units in Rijndael are 8-bit bytes. The * input, output and key input are all enumerated arrays of bytes in which * bytes are numbered starting at zero and increasing to one less than the * number of bytes in the array in question. This enumeration is only used * for naming bytes and does not imply any adjacency or order relationship * from one byte to another. When these inputs and outputs are considered * as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to * byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. * In this implementation bits are numbered from 0 to 7 starting at the * numerically least significant end of each byte. Bit n represents 2^n. * * However, Rijndael can be implemented more efficiently using 32-bit * words by packing bytes into words so that bytes 4*n to 4*n+3 are placed * into word[n]. While in principle these bytes can be assembled into words * in any positions, this implementation only supports the two formats in * which bytes in adjacent positions within words also have adjacent byte * numbers. This order is called big-endian if the lowest numbered bytes * in words have the highest numeric significance and little-endian if the * opposite applies. * * This code can work in either order irrespective of the order used by the * machine on which it runs. Normally the internal byte order will be set * to the order of the processor on which the code is to be run but this * define can be used to reverse this in special situations * * WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. * This define will hence be redefined later (in section 4) if necessary */ #if 1 #define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER #elif 0 #define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN #elif 0 #define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN #else #error The algorithm byte order is not defined #endif /* 2. VIA ACE SUPPORT */ #if defined(__GNUC__) && defined(__i386__) || \ defined(_WIN32) && defined(_M_IX86) && \ !(defined(_WIN64) || defined(_WIN32_WCE) || \ defined(_MSC_VER) && (_MSC_VER <= 800)) #define VIA_ACE_POSSIBLE #endif /* * Define this option if support for the VIA ACE is required. This uses * inline assembler instructions and is only implemented for the Microsoft, * Intel and GCC compilers. If VIA ACE is known to be present, then defining * ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption * code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if * it is detected (both present and enabled) but the normal AES code will * also be present. * * When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte * aligned; other input/output buffers do not need to be 16 byte aligned * but there are very large performance gains if this can be arranged. * VIA ACE also requires the decryption key schedule to be in reverse * order (which later checks below ensure). */ /* VIA ACE is not used here for OpenSolaris: */ #undef VIA_ACE_POSSIBLE #undef ASSUME_VIA_ACE_PRESENT #if 0 && defined(VIA_ACE_POSSIBLE) && !defined(USE_VIA_ACE_IF_PRESENT) #define USE_VIA_ACE_IF_PRESENT #endif #if 0 && defined(VIA_ACE_POSSIBLE) && !defined(ASSUME_VIA_ACE_PRESENT) #define ASSUME_VIA_ACE_PRESENT #endif /* * 3. ASSEMBLER SUPPORT * * This define (which can be on the command line) enables the use of the * assembler code routines for encryption, decryption and key scheduling * as follows: * * ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for * encryption and decryption and but with key scheduling in C * ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for * encryption, decryption and key scheduling * ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for * encryption and decryption and but with key scheduling in C * ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for * encryption and decryption and but with key scheduling in C * * Change one 'if 0' below to 'if 1' to select the version or define * as a compilation option. */ #if 0 && !defined(ASM_X86_V1C) #define ASM_X86_V1C #elif 0 && !defined(ASM_X86_V2) #define ASM_X86_V2 #elif 0 && !defined(ASM_X86_V2C) #define ASM_X86_V2C #elif 1 && !defined(ASM_AMD64_C) #define ASM_AMD64_C #endif #if (defined(ASM_X86_V1C) || defined(ASM_X86_V2) || defined(ASM_X86_V2C)) && \ !defined(_M_IX86) || defined(ASM_AMD64_C) && !defined(_M_X64) && \ !defined(__amd64) #error Assembler code is only available for x86 and AMD64 systems #endif /* * 4. FAST INPUT/OUTPUT OPERATIONS. * * On some machines it is possible to improve speed by transferring the * bytes in the input and output arrays to and from the internal 32-bit * variables by addressing these arrays as if they are arrays of 32-bit * words. On some machines this will always be possible but there may * be a large performance penalty if the byte arrays are not aligned on * the normal word boundaries. On other machines this technique will * lead to memory access errors when such 32-bit word accesses are not * properly aligned. The option SAFE_IO avoids such problems but will * often be slower on those machines that support misaligned access * (especially so if care is taken to align the input and output byte * arrays on 32-bit word boundaries). If SAFE_IO is not defined it is * assumed that access to byte arrays as if they are arrays of 32-bit * words will not cause problems when such accesses are misaligned. */ #if 1 && !defined(_MSC_VER) #define SAFE_IO #endif /* * 5. LOOP UNROLLING * * The code for encryption and decryption cycles through a number of rounds * that can be implemented either in a loop or by expanding the code into a * long sequence of instructions, the latter producing a larger program but * one that will often be much faster. The latter is called loop unrolling. * There are also potential speed advantages in expanding two iterations in * a loop with half the number of iterations, which is called partial loop * unrolling. The following options allow partial or full loop unrolling * to be set independently for encryption and decryption */ #if 1 #define ENC_UNROLL FULL #elif 0 #define ENC_UNROLL PARTIAL #else #define ENC_UNROLL NONE #endif #if 1 #define DEC_UNROLL FULL #elif 0 #define DEC_UNROLL PARTIAL #else #define DEC_UNROLL NONE #endif #if 1 #define ENC_KS_UNROLL #endif #if 1 #define DEC_KS_UNROLL #endif /* * 6. FAST FINITE FIELD OPERATIONS * * If this section is included, tables are used to provide faster finite * field arithmetic. This has no effect if FIXED_TABLES is defined. */ #if 1 #define FF_TABLES #endif /* * 7. INTERNAL STATE VARIABLE FORMAT * * The internal state of Rijndael is stored in a number of local 32-bit * word variables which can be defined either as an array or as individual * names variables. Include this section if you want to store these local * variables in arrays. Otherwise individual local variables will be used. */ #if 1 #define ARRAYS #endif /* * 8. FIXED OR DYNAMIC TABLES * * When this section is included the tables used by the code are compiled * statically into the binary file. Otherwise the subroutine aes_init() * must be called to compute them before the code is first used. */ #if 1 && !(defined(_MSC_VER) && (_MSC_VER <= 800)) #define FIXED_TABLES #endif /* * 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES * * In some systems it is better to mask longer values to extract bytes * rather than using a cast. This option allows this choice. */ #if 0 #define to_byte(x) ((uint8_t)(x)) #else #define to_byte(x) ((x) & 0xff) #endif /* * 10. TABLE ALIGNMENT * * On some systems speed will be improved by aligning the AES large lookup * tables on particular boundaries. This define should be set to a power of * two giving the desired alignment. It can be left undefined if alignment * is not needed. This option is specific to the Micrsoft VC++ compiler - * it seems to sometimes cause trouble for the VC++ version 6 compiler. */ #if 1 && defined(_MSC_VER) && (_MSC_VER >= 1300) #define TABLE_ALIGN 32 #endif /* * 11. REDUCE CODE AND TABLE SIZE * * This replaces some expanded macros with function calls if AES_ASM_V2 or * AES_ASM_V2C are defined */ #if 1 && (defined(ASM_X86_V2) || defined(ASM_X86_V2C)) #define REDUCE_CODE_SIZE #endif /* * 12. TABLE OPTIONS * * This cipher proceeds by repeating in a number of cycles known as rounds * which are implemented by a round function which is optionally be speeded * up using tables. The basic tables are 256 32-bit words, with either * one or four tables being required for each round function depending on * how much speed is required. Encryption and decryption round functions * are different and the last encryption and decryption round functions are * different again making four different round functions in all. * * This means that: * 1. Normal encryption and decryption rounds can each use either 0, 1 * or 4 tables and table spaces of 0, 1024 or 4096 bytes each. * 2. The last encryption and decryption rounds can also use either 0, 1 * or 4 tables and table spaces of 0, 1024 or 4096 bytes each. * * Include or exclude the appropriate definitions below to set the number * of tables used by this implementation. */ #if 1 /* set tables for the normal encryption round */ #define ENC_ROUND FOUR_TABLES #elif 0 #define ENC_ROUND ONE_TABLE #else #define ENC_ROUND NO_TABLES #endif #if 1 /* set tables for the last encryption round */ #define LAST_ENC_ROUND FOUR_TABLES #elif 0 #define LAST_ENC_ROUND ONE_TABLE #else #define LAST_ENC_ROUND NO_TABLES #endif #if 1 /* set tables for the normal decryption round */ #define DEC_ROUND FOUR_TABLES #elif 0 #define DEC_ROUND ONE_TABLE #else #define DEC_ROUND NO_TABLES #endif #if 1 /* set tables for the last decryption round */ #define LAST_DEC_ROUND FOUR_TABLES #elif 0 #define LAST_DEC_ROUND ONE_TABLE #else #define LAST_DEC_ROUND NO_TABLES #endif /* * The decryption key schedule can be speeded up with tables in the same * way that the round functions can. Include or exclude the following * defines to set this requirement. */ #if 1 #define KEY_SCHED FOUR_TABLES #elif 0 #define KEY_SCHED ONE_TABLE #else #define KEY_SCHED NO_TABLES #endif /* ---- END OF USER CONFIGURED OPTIONS ---- */ /* VIA ACE support is only available for VC++ and GCC */ #if !defined(_MSC_VER) && !defined(__GNUC__) #if defined(ASSUME_VIA_ACE_PRESENT) #undef ASSUME_VIA_ACE_PRESENT #endif #if defined(USE_VIA_ACE_IF_PRESENT) #undef USE_VIA_ACE_IF_PRESENT #endif #endif #if defined(ASSUME_VIA_ACE_PRESENT) && !defined(USE_VIA_ACE_IF_PRESENT) #define USE_VIA_ACE_IF_PRESENT #endif #if defined(USE_VIA_ACE_IF_PRESENT) && !defined(AES_REV_DKS) #define AES_REV_DKS #endif /* Assembler support requires the use of platform byte order */ #if (defined(ASM_X86_V1C) || defined(ASM_X86_V2C) || defined(ASM_AMD64_C)) && \ (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) #undef ALGORITHM_BYTE_ORDER #define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER #endif /* * In this implementation the columns of the state array are each held in * 32-bit words. The state array can be held in various ways: in an array * of words, in a number of individual word variables or in a number of * processor registers. The following define maps a variable name x and * a column number c to the way the state array variable is to be held. * The first define below maps the state into an array x[c] whereas the * second form maps the state into a number of individual variables x0, * x1, etc. Another form could map individual state columns to machine * register names. */ #if defined(ARRAYS) #define s(x, c) x[c] #else #define s(x, c) x##c #endif /* * This implementation provides subroutines for encryption, decryption * and for setting the three key lengths (separately) for encryption * and decryption. Since not all functions are needed, masks are set * up here to determine which will be implemented in C */ #if !defined(AES_ENCRYPT) #define EFUNCS_IN_C 0 #elif defined(ASSUME_VIA_ACE_PRESENT) || defined(ASM_X86_V1C) || \ defined(ASM_X86_V2C) || defined(ASM_AMD64_C) #define EFUNCS_IN_C ENC_KEYING_IN_C #elif !defined(ASM_X86_V2) #define EFUNCS_IN_C (ENCRYPTION_IN_C | ENC_KEYING_IN_C) #else #define EFUNCS_IN_C 0 #endif #if !defined(AES_DECRYPT) #define DFUNCS_IN_C 0 #elif defined(ASSUME_VIA_ACE_PRESENT) || defined(ASM_X86_V1C) || \ defined(ASM_X86_V2C) || defined(ASM_AMD64_C) #define DFUNCS_IN_C DEC_KEYING_IN_C #elif !defined(ASM_X86_V2) #define DFUNCS_IN_C (DECRYPTION_IN_C | DEC_KEYING_IN_C) #else #define DFUNCS_IN_C 0 #endif #define FUNCS_IN_C (EFUNCS_IN_C | DFUNCS_IN_C) /* END OF CONFIGURATION OPTIONS */ /* Disable or report errors on some combinations of options */ #if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES #undef LAST_ENC_ROUND #define LAST_ENC_ROUND NO_TABLES #elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES #undef LAST_ENC_ROUND #define LAST_ENC_ROUND ONE_TABLE #endif #if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE #undef ENC_UNROLL #define ENC_UNROLL NONE #endif #if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES #undef LAST_DEC_ROUND #define LAST_DEC_ROUND NO_TABLES #elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES #undef LAST_DEC_ROUND #define LAST_DEC_ROUND ONE_TABLE #endif #if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE #undef DEC_UNROLL #define DEC_UNROLL NONE #endif #if (ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN) #define aes_sw32 htonl #elif defined(bswap32) #define aes_sw32 bswap32 #elif defined(bswap_32) #define aes_sw32 bswap_32 #else #define brot(x, n) (((uint32_t)(x) << (n)) | ((uint32_t)(x) >> (32 - (n)))) #define aes_sw32(x) ((brot((x), 8) & 0x00ff00ff) | (brot((x), 24) & 0xff00ff00)) #endif /* * upr(x, n): rotates bytes within words by n positions, moving bytes to * higher index positions with wrap around into low positions * ups(x, n): moves bytes by n positions to higher index positions in * words but without wrap around * bval(x, n): extracts a byte from a word * * WARNING: The definitions given here are intended only for use with * unsigned variables and with shift counts that are compile * time constants */ #if (ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN) #define upr(x, n) (((uint32_t)(x) << (8 * (n))) | \ ((uint32_t)(x) >> (32 - 8 * (n)))) #define ups(x, n) ((uint32_t)(x) << (8 * (n))) #define bval(x, n) to_byte((x) >> (8 * (n))) #define bytes2word(b0, b1, b2, b3) \ (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | \ ((uint32_t)(b1) << 8) | (b0)) #endif #if (ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN) #define upr(x, n) (((uint32_t)(x) >> (8 * (n))) | \ ((uint32_t)(x) << (32 - 8 * (n)))) #define ups(x, n) ((uint32_t)(x) >> (8 * (n))) #define bval(x, n) to_byte((x) >> (24 - 8 * (n))) #define bytes2word(b0, b1, b2, b3) \ (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | \ ((uint32_t)(b2) << 8) | (b3)) #endif #if defined(SAFE_IO) #define word_in(x, c) bytes2word(((const uint8_t *)(x) + 4 * c)[0], \ ((const uint8_t *)(x) + 4 * c)[1], \ ((const uint8_t *)(x) + 4 * c)[2], \ ((const uint8_t *)(x) + 4 * c)[3]) #define word_out(x, c, v) { ((uint8_t *)(x) + 4 * c)[0] = bval(v, 0); \ ((uint8_t *)(x) + 4 * c)[1] = bval(v, 1); \ ((uint8_t *)(x) + 4 * c)[2] = bval(v, 2); \ ((uint8_t *)(x) + 4 * c)[3] = bval(v, 3); } #elif (ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER) #define word_in(x, c) (*((uint32_t *)(x) + (c))) #define word_out(x, c, v) (*((uint32_t *)(x) + (c)) = (v)) #else #define word_in(x, c) aes_sw32(*((uint32_t *)(x) + (c))) #define word_out(x, c, v) (*((uint32_t *)(x) + (c)) = aes_sw32(v)) #endif /* the finite field modular polynomial and elements */ #define WPOLY 0x011b #define BPOLY 0x1b /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ #define m1 0x80808080 #define m2 0x7f7f7f7f #define gf_mulx(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) /* * The following defines provide alternative definitions of gf_mulx that might * give improved performance if a fast 32-bit multiply is not available. Note * that a temporary variable u needs to be defined where gf_mulx is used. * * #define gf_mulx(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ \ * ((u >> 3) | (u >> 6)) * #define m4 (0x01010101 * BPOLY) * #define gf_mulx(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) \ * & m4) */ /* Work out which tables are needed for the different options */ #if defined(ASM_X86_V1C) #if defined(ENC_ROUND) #undef ENC_ROUND #endif #define ENC_ROUND FOUR_TABLES #if defined(LAST_ENC_ROUND) #undef LAST_ENC_ROUND #endif #define LAST_ENC_ROUND FOUR_TABLES #if defined(DEC_ROUND) #undef DEC_ROUND #endif #define DEC_ROUND FOUR_TABLES #if defined(LAST_DEC_ROUND) #undef LAST_DEC_ROUND #endif #define LAST_DEC_ROUND FOUR_TABLES #if defined(KEY_SCHED) #undef KEY_SCHED #define KEY_SCHED FOUR_TABLES #endif #endif #if (FUNCS_IN_C & ENCRYPTION_IN_C) || defined(ASM_X86_V1C) #if ENC_ROUND == ONE_TABLE #define FT1_SET #elif ENC_ROUND == FOUR_TABLES #define FT4_SET #else #define SBX_SET #endif #if LAST_ENC_ROUND == ONE_TABLE #define FL1_SET #elif LAST_ENC_ROUND == FOUR_TABLES #define FL4_SET #elif !defined(SBX_SET) #define SBX_SET #endif #endif #if (FUNCS_IN_C & DECRYPTION_IN_C) || defined(ASM_X86_V1C) #if DEC_ROUND == ONE_TABLE #define IT1_SET #elif DEC_ROUND == FOUR_TABLES #define IT4_SET #else #define ISB_SET #endif #if LAST_DEC_ROUND == ONE_TABLE #define IL1_SET #elif LAST_DEC_ROUND == FOUR_TABLES #define IL4_SET #elif !defined(ISB_SET) #define ISB_SET #endif #endif #if !(defined(REDUCE_CODE_SIZE) && (defined(ASM_X86_V2) || \ defined(ASM_X86_V2C))) #if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C)) #if KEY_SCHED == ONE_TABLE #if !defined(FL1_SET) && !defined(FL4_SET) #define LS1_SET #endif #elif KEY_SCHED == FOUR_TABLES #if !defined(FL4_SET) #define LS4_SET #endif #elif !defined(SBX_SET) #define SBX_SET #endif #endif #if (FUNCS_IN_C & DEC_KEYING_IN_C) #if KEY_SCHED == ONE_TABLE #define IM1_SET #elif KEY_SCHED == FOUR_TABLES #define IM4_SET #elif !defined(SBX_SET) #define SBX_SET #endif #endif #endif /* generic definitions of Rijndael macros that use tables */ #define no_table(x, box, vf, rf, c) bytes2word(\ box[bval(vf(x, 0, c), rf(0, c))], \ box[bval(vf(x, 1, c), rf(1, c))], \ box[bval(vf(x, 2, c), rf(2, c))], \ box[bval(vf(x, 3, c), rf(3, c))]) #define one_table(x, op, tab, vf, rf, c) \ (tab[bval(vf(x, 0, c), rf(0, c))] \ ^ op(tab[bval(vf(x, 1, c), rf(1, c))], 1) \ ^ op(tab[bval(vf(x, 2, c), rf(2, c))], 2) \ ^ op(tab[bval(vf(x, 3, c), rf(3, c))], 3)) #define four_tables(x, tab, vf, rf, c) \ (tab[0][bval(vf(x, 0, c), rf(0, c))] \ ^ tab[1][bval(vf(x, 1, c), rf(1, c))] \ ^ tab[2][bval(vf(x, 2, c), rf(2, c))] \ ^ tab[3][bval(vf(x, 3, c), rf(3, c))]) #define vf1(x, r, c) (x) #define rf1(r, c) (r) #define rf2(r, c) ((8+r-c)&3) /* * Perform forward and inverse column mix operation on four bytes in long word * x in parallel. NOTE: x must be a simple variable, NOT an expression in * these macros. */ #if !(defined(REDUCE_CODE_SIZE) && (defined(ASM_X86_V2) || \ defined(ASM_X86_V2C))) #if defined(FM4_SET) /* not currently used */ #define fwd_mcol(x) four_tables(x, t_use(f, m), vf1, rf1, 0) #elif defined(FM1_SET) /* not currently used */ #define fwd_mcol(x) one_table(x, upr, t_use(f, m), vf1, rf1, 0) #else #define dec_fmvars uint32_t g2 #define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ \ upr((x), 2) ^ upr((x), 1)) #endif #if defined(IM4_SET) #define inv_mcol(x) four_tables(x, t_use(i, m), vf1, rf1, 0) #elif defined(IM1_SET) #define inv_mcol(x) one_table(x, upr, t_use(i, m), vf1, rf1, 0) #else #define dec_imvars uint32_t g2, g4, g9 #define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = \ (x) ^ gf_mulx(g4), g4 ^= g9, \ (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ \ upr(g4, 2) ^ upr(g9, 1)) #endif #if defined(FL4_SET) #define ls_box(x, c) four_tables(x, t_use(f, l), vf1, rf2, c) #elif defined(LS4_SET) #define ls_box(x, c) four_tables(x, t_use(l, s), vf1, rf2, c) #elif defined(FL1_SET) #define ls_box(x, c) one_table(x, upr, t_use(f, l), vf1, rf2, c) #elif defined(LS1_SET) #define ls_box(x, c) one_table(x, upr, t_use(l, s), vf1, rf2, c) #else #define ls_box(x, c) no_table(x, t_use(s, box), vf1, rf2, c) #endif #endif #if defined(ASM_X86_V1C) && defined(AES_DECRYPT) && !defined(ISB_SET) #define ISB_SET #endif #ifdef __cplusplus } #endif #endif /* _AESOPT_H */ /* * --------------------------------------------------------------------------- * Copyright (c) 1998-2007, Brian Gladman, Worcester, UK. All rights reserved. * * LICENSE TERMS * * The free distribution and use of this software is allowed (with or without * changes) provided that: * * 1. source code distributions include the above copyright notice, this * list of conditions and the following disclaimer; * * 2. binary distributions include the above copyright notice, this list * of conditions and the following disclaimer in their documentation; * * 3. the name of the copyright holder is not used to endorse products * built using this software without specific written permission. * * DISCLAIMER * * This software is provided 'as is' with no explicit or implied warranties * in respect of its properties, including, but not limited to, correctness * and/or fitness for purpose. * --------------------------------------------------------------------------- * Issue Date: 20/12/2007 * * This file contains the code for declaring the tables needed to implement * AES. The file aesopt.h is assumed to be included before this header file. * If there are no global variables, the definitions here can be used to put * the AES tables in a structure so that a pointer can then be added to the * AES context to pass them to the AES routines that need them. If this * facility is used, the calling program has to ensure that this pointer is * managed appropriately. In particular, the value of the t_dec(in, it) item * in the table structure must be set to zero in order to ensure that the * tables are initialised. In practice the three code sequences in aeskey.c * that control the calls to aes_init() and the aes_init() routine itself will * have to be changed for a specific implementation. If global variables are * available it will generally be preferable to use them with the precomputed * FIXED_TABLES option that uses static global tables. * * The following defines can be used to control the way the tables * are defined, initialised and used in embedded environments that * require special features for these purposes * * the 't_dec' construction is used to declare fixed table arrays * the 't_set' construction is used to set fixed table values * the 't_use' construction is used to access fixed table values * * 256 byte tables: * * t_xxx(s, box) => forward S box * t_xxx(i, box) => inverse S box * * 256 32-bit word OR 4 x 256 32-bit word tables: * * t_xxx(f, n) => forward normal round * t_xxx(f, l) => forward last round * t_xxx(i, n) => inverse normal round * t_xxx(i, l) => inverse last round * t_xxx(l, s) => key schedule table * t_xxx(i, m) => key schedule table * * Other variables and tables: * * t_xxx(r, c) => the rcon table */ /* * OpenSolaris OS modifications * * 1. Added __cplusplus and _AESTAB_H header guards * 2. Added header file sys/types.h * 3. Remove code defined for _MSC_VER * 4. Changed all variables to "static const" * 5. Changed uint_8t and uint_32t to uint8_t and uint32_t * 6. Cstyled and hdrchk code */ #ifndef _AESTAB_H #define _AESTAB_H #ifdef __cplusplus extern "C" { #endif #include #define t_dec(m, n) t_##m##n #define t_set(m, n) t_##m##n #define t_use(m, n) t_##m##n #if defined(DO_TABLES) && defined(FIXED_TABLES) #define d_1(t, n, b, e) static const t n[256] = b(e) #define d_4(t, n, b, e, f, g, h) static const t n[4][256] = \ {b(e), b(f), b(g), b(h)} static const uint32_t t_dec(r, c)[RC_LENGTH] = rc_data(w0); #else #define d_1(t, n, b, e) static const t n[256] #define d_4(t, n, b, e, f, g, h) static const t n[4][256] static const uint32_t t_dec(r, c)[RC_LENGTH]; #endif #if defined(SBX_SET) d_1(uint8_t, t_dec(s, box), sb_data, h0); #endif #if defined(ISB_SET) d_1(uint8_t, t_dec(i, box), isb_data, h0); #endif #if defined(FT1_SET) d_1(uint32_t, t_dec(f, n), sb_data, u0); #endif #if defined(FT4_SET) d_4(uint32_t, t_dec(f, n), sb_data, u0, u1, u2, u3); #endif #if defined(FL1_SET) d_1(uint32_t, t_dec(f, l), sb_data, w0); #endif #if defined(FL4_SET) d_4(uint32_t, t_dec(f, l), sb_data, w0, w1, w2, w3); #endif #if defined(IT1_SET) d_1(uint32_t, t_dec(i, n), isb_data, v0); #endif #if defined(IT4_SET) d_4(uint32_t, t_dec(i, n), isb_data, v0, v1, v2, v3); #endif #if defined(IL1_SET) d_1(uint32_t, t_dec(i, l), isb_data, w0); #endif #if defined(IL4_SET) d_4(uint32_t, t_dec(i, l), isb_data, w0, w1, w2, w3); #endif #if defined(LS1_SET) #if defined(FL1_SET) #undef LS1_SET #else d_1(uint32_t, t_dec(l, s), sb_data, w0); #endif #endif #if defined(LS4_SET) #if defined(FL4_SET) #undef LS4_SET #else d_4(uint32_t, t_dec(l, s), sb_data, w0, w1, w2, w3); #endif #endif #if defined(IM1_SET) d_1(uint32_t, t_dec(i, m), mm_data, v0); #endif #if defined(IM4_SET) d_4(uint32_t, t_dec(i, m), mm_data, v0, v1, v2, v3); #endif #ifdef __cplusplus } #endif #endif /* _AESTAB_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _AESTAB2_H #define _AESTAB2_H #ifdef __cplusplus extern "C" { #endif /* * To create this file for OpenSolaris: * 1. Compile and run tablegen.c, from aes-src-04-03-08.zip, * after defining ASM_AMD64_C * 2. mv aestab2.c aestab2.h * 3. Add __cplusplus and _AESTAB2_H header guards * 3. Add #include * 4. Change "uint_32t" to "uint32_t" * 5. Change all variables to "static const" * 6. Cstyle and hdrchk this file */ #include static const uint32_t t_rc[RC_LENGTH] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x0000001b, 0x00000036 }; static const uint32_t t_ls[4][256] = { { 0x00000063, 0x0000007c, 0x00000077, 0x0000007b, 0x000000f2, 0x0000006b, 0x0000006f, 0x000000c5, 0x00000030, 0x00000001, 0x00000067, 0x0000002b, 0x000000fe, 0x000000d7, 0x000000ab, 0x00000076, 0x000000ca, 0x00000082, 0x000000c9, 0x0000007d, 0x000000fa, 0x00000059, 0x00000047, 0x000000f0, 0x000000ad, 0x000000d4, 0x000000a2, 0x000000af, 0x0000009c, 0x000000a4, 0x00000072, 0x000000c0, 0x000000b7, 0x000000fd, 0x00000093, 0x00000026, 0x00000036, 0x0000003f, 0x000000f7, 0x000000cc, 0x00000034, 0x000000a5, 0x000000e5, 0x000000f1, 0x00000071, 0x000000d8, 0x00000031, 0x00000015, 0x00000004, 0x000000c7, 0x00000023, 0x000000c3, 0x00000018, 0x00000096, 0x00000005, 0x0000009a, 0x00000007, 0x00000012, 0x00000080, 0x000000e2, 0x000000eb, 0x00000027, 0x000000b2, 0x00000075, 0x00000009, 0x00000083, 0x0000002c, 0x0000001a, 0x0000001b, 0x0000006e, 0x0000005a, 0x000000a0, 0x00000052, 0x0000003b, 0x000000d6, 0x000000b3, 0x00000029, 0x000000e3, 0x0000002f, 0x00000084, 0x00000053, 0x000000d1, 0x00000000, 0x000000ed, 0x00000020, 0x000000fc, 0x000000b1, 0x0000005b, 0x0000006a, 0x000000cb, 0x000000be, 0x00000039, 0x0000004a, 0x0000004c, 0x00000058, 0x000000cf, 0x000000d0, 0x000000ef, 0x000000aa, 0x000000fb, 0x00000043, 0x0000004d, 0x00000033, 0x00000085, 0x00000045, 0x000000f9, 0x00000002, 0x0000007f, 0x00000050, 0x0000003c, 0x0000009f, 0x000000a8, 0x00000051, 0x000000a3, 0x00000040, 0x0000008f, 0x00000092, 0x0000009d, 0x00000038, 0x000000f5, 0x000000bc, 0x000000b6, 0x000000da, 0x00000021, 0x00000010, 0x000000ff, 0x000000f3, 0x000000d2, 0x000000cd, 0x0000000c, 0x00000013, 0x000000ec, 0x0000005f, 0x00000097, 0x00000044, 0x00000017, 0x000000c4, 0x000000a7, 0x0000007e, 0x0000003d, 0x00000064, 0x0000005d, 0x00000019, 0x00000073, 0x00000060, 0x00000081, 0x0000004f, 0x000000dc, 0x00000022, 0x0000002a, 0x00000090, 0x00000088, 0x00000046, 0x000000ee, 0x000000b8, 0x00000014, 0x000000de, 0x0000005e, 0x0000000b, 0x000000db, 0x000000e0, 0x00000032, 0x0000003a, 0x0000000a, 0x00000049, 0x00000006, 0x00000024, 0x0000005c, 0x000000c2, 0x000000d3, 0x000000ac, 0x00000062, 0x00000091, 0x00000095, 0x000000e4, 0x00000079, 0x000000e7, 0x000000c8, 0x00000037, 0x0000006d, 0x0000008d, 0x000000d5, 0x0000004e, 0x000000a9, 0x0000006c, 0x00000056, 0x000000f4, 0x000000ea, 0x00000065, 0x0000007a, 0x000000ae, 0x00000008, 0x000000ba, 0x00000078, 0x00000025, 0x0000002e, 0x0000001c, 0x000000a6, 0x000000b4, 0x000000c6, 0x000000e8, 0x000000dd, 0x00000074, 0x0000001f, 0x0000004b, 0x000000bd, 0x0000008b, 0x0000008a, 0x00000070, 0x0000003e, 0x000000b5, 0x00000066, 0x00000048, 0x00000003, 0x000000f6, 0x0000000e, 0x00000061, 0x00000035, 0x00000057, 0x000000b9, 0x00000086, 0x000000c1, 0x0000001d, 0x0000009e, 0x000000e1, 0x000000f8, 0x00000098, 0x00000011, 0x00000069, 0x000000d9, 0x0000008e, 0x00000094, 0x0000009b, 0x0000001e, 0x00000087, 0x000000e9, 0x000000ce, 0x00000055, 0x00000028, 0x000000df, 0x0000008c, 0x000000a1, 0x00000089, 0x0000000d, 0x000000bf, 0x000000e6, 0x00000042, 0x00000068, 0x00000041, 0x00000099, 0x0000002d, 0x0000000f, 0x000000b0, 0x00000054, 0x000000bb, 0x00000016 }, { 0x00006300, 0x00007c00, 0x00007700, 0x00007b00, 0x0000f200, 0x00006b00, 0x00006f00, 0x0000c500, 0x00003000, 0x00000100, 0x00006700, 0x00002b00, 0x0000fe00, 0x0000d700, 0x0000ab00, 0x00007600, 0x0000ca00, 0x00008200, 0x0000c900, 0x00007d00, 0x0000fa00, 0x00005900, 0x00004700, 0x0000f000, 0x0000ad00, 0x0000d400, 0x0000a200, 0x0000af00, 0x00009c00, 0x0000a400, 0x00007200, 0x0000c000, 0x0000b700, 0x0000fd00, 0x00009300, 0x00002600, 0x00003600, 0x00003f00, 0x0000f700, 0x0000cc00, 0x00003400, 0x0000a500, 0x0000e500, 0x0000f100, 0x00007100, 0x0000d800, 0x00003100, 0x00001500, 0x00000400, 0x0000c700, 0x00002300, 0x0000c300, 0x00001800, 0x00009600, 0x00000500, 0x00009a00, 0x00000700, 0x00001200, 0x00008000, 0x0000e200, 0x0000eb00, 0x00002700, 0x0000b200, 0x00007500, 0x00000900, 0x00008300, 0x00002c00, 0x00001a00, 0x00001b00, 0x00006e00, 0x00005a00, 0x0000a000, 0x00005200, 0x00003b00, 0x0000d600, 0x0000b300, 0x00002900, 0x0000e300, 0x00002f00, 0x00008400, 0x00005300, 0x0000d100, 0x00000000, 0x0000ed00, 0x00002000, 0x0000fc00, 0x0000b100, 0x00005b00, 0x00006a00, 0x0000cb00, 0x0000be00, 0x00003900, 0x00004a00, 0x00004c00, 0x00005800, 0x0000cf00, 0x0000d000, 0x0000ef00, 0x0000aa00, 0x0000fb00, 0x00004300, 0x00004d00, 0x00003300, 0x00008500, 0x00004500, 0x0000f900, 0x00000200, 0x00007f00, 0x00005000, 0x00003c00, 0x00009f00, 0x0000a800, 0x00005100, 0x0000a300, 0x00004000, 0x00008f00, 0x00009200, 0x00009d00, 0x00003800, 0x0000f500, 0x0000bc00, 0x0000b600, 0x0000da00, 0x00002100, 0x00001000, 0x0000ff00, 0x0000f300, 0x0000d200, 0x0000cd00, 0x00000c00, 0x00001300, 0x0000ec00, 0x00005f00, 0x00009700, 0x00004400, 0x00001700, 0x0000c400, 0x0000a700, 0x00007e00, 0x00003d00, 0x00006400, 0x00005d00, 0x00001900, 0x00007300, 0x00006000, 0x00008100, 0x00004f00, 0x0000dc00, 0x00002200, 0x00002a00, 0x00009000, 0x00008800, 0x00004600, 0x0000ee00, 0x0000b800, 0x00001400, 0x0000de00, 0x00005e00, 0x00000b00, 0x0000db00, 0x0000e000, 0x00003200, 0x00003a00, 0x00000a00, 0x00004900, 0x00000600, 0x00002400, 0x00005c00, 0x0000c200, 0x0000d300, 0x0000ac00, 0x00006200, 0x00009100, 0x00009500, 0x0000e400, 0x00007900, 0x0000e700, 0x0000c800, 0x00003700, 0x00006d00, 0x00008d00, 0x0000d500, 0x00004e00, 0x0000a900, 0x00006c00, 0x00005600, 0x0000f400, 0x0000ea00, 0x00006500, 0x00007a00, 0x0000ae00, 0x00000800, 0x0000ba00, 0x00007800, 0x00002500, 0x00002e00, 0x00001c00, 0x0000a600, 0x0000b400, 0x0000c600, 0x0000e800, 0x0000dd00, 0x00007400, 0x00001f00, 0x00004b00, 0x0000bd00, 0x00008b00, 0x00008a00, 0x00007000, 0x00003e00, 0x0000b500, 0x00006600, 0x00004800, 0x00000300, 0x0000f600, 0x00000e00, 0x00006100, 0x00003500, 0x00005700, 0x0000b900, 0x00008600, 0x0000c100, 0x00001d00, 0x00009e00, 0x0000e100, 0x0000f800, 0x00009800, 0x00001100, 0x00006900, 0x0000d900, 0x00008e00, 0x00009400, 0x00009b00, 0x00001e00, 0x00008700, 0x0000e900, 0x0000ce00, 0x00005500, 0x00002800, 0x0000df00, 0x00008c00, 0x0000a100, 0x00008900, 0x00000d00, 0x0000bf00, 0x0000e600, 0x00004200, 0x00006800, 0x00004100, 0x00009900, 0x00002d00, 0x00000f00, 0x0000b000, 0x00005400, 0x0000bb00, 0x00001600 }, { 0x00630000, 0x007c0000, 0x00770000, 0x007b0000, 0x00f20000, 0x006b0000, 0x006f0000, 0x00c50000, 0x00300000, 0x00010000, 0x00670000, 0x002b0000, 0x00fe0000, 0x00d70000, 0x00ab0000, 0x00760000, 0x00ca0000, 0x00820000, 0x00c90000, 0x007d0000, 0x00fa0000, 0x00590000, 0x00470000, 0x00f00000, 0x00ad0000, 0x00d40000, 0x00a20000, 0x00af0000, 0x009c0000, 0x00a40000, 0x00720000, 0x00c00000, 0x00b70000, 0x00fd0000, 0x00930000, 0x00260000, 0x00360000, 0x003f0000, 0x00f70000, 0x00cc0000, 0x00340000, 0x00a50000, 0x00e50000, 0x00f10000, 0x00710000, 0x00d80000, 0x00310000, 0x00150000, 0x00040000, 0x00c70000, 0x00230000, 0x00c30000, 0x00180000, 0x00960000, 0x00050000, 0x009a0000, 0x00070000, 0x00120000, 0x00800000, 0x00e20000, 0x00eb0000, 0x00270000, 0x00b20000, 0x00750000, 0x00090000, 0x00830000, 0x002c0000, 0x001a0000, 0x001b0000, 0x006e0000, 0x005a0000, 0x00a00000, 0x00520000, 0x003b0000, 0x00d60000, 0x00b30000, 0x00290000, 0x00e30000, 0x002f0000, 0x00840000, 0x00530000, 0x00d10000, 0x00000000, 0x00ed0000, 0x00200000, 0x00fc0000, 0x00b10000, 0x005b0000, 0x006a0000, 0x00cb0000, 0x00be0000, 0x00390000, 0x004a0000, 0x004c0000, 0x00580000, 0x00cf0000, 0x00d00000, 0x00ef0000, 0x00aa0000, 0x00fb0000, 0x00430000, 0x004d0000, 0x00330000, 0x00850000, 0x00450000, 0x00f90000, 0x00020000, 0x007f0000, 0x00500000, 0x003c0000, 0x009f0000, 0x00a80000, 0x00510000, 0x00a30000, 0x00400000, 0x008f0000, 0x00920000, 0x009d0000, 0x00380000, 0x00f50000, 0x00bc0000, 0x00b60000, 0x00da0000, 0x00210000, 0x00100000, 0x00ff0000, 0x00f30000, 0x00d20000, 0x00cd0000, 0x000c0000, 0x00130000, 0x00ec0000, 0x005f0000, 0x00970000, 0x00440000, 0x00170000, 0x00c40000, 0x00a70000, 0x007e0000, 0x003d0000, 0x00640000, 0x005d0000, 0x00190000, 0x00730000, 0x00600000, 0x00810000, 0x004f0000, 0x00dc0000, 0x00220000, 0x002a0000, 0x00900000, 0x00880000, 0x00460000, 0x00ee0000, 0x00b80000, 0x00140000, 0x00de0000, 0x005e0000, 0x000b0000, 0x00db0000, 0x00e00000, 0x00320000, 0x003a0000, 0x000a0000, 0x00490000, 0x00060000, 0x00240000, 0x005c0000, 0x00c20000, 0x00d30000, 0x00ac0000, 0x00620000, 0x00910000, 0x00950000, 0x00e40000, 0x00790000, 0x00e70000, 0x00c80000, 0x00370000, 0x006d0000, 0x008d0000, 0x00d50000, 0x004e0000, 0x00a90000, 0x006c0000, 0x00560000, 0x00f40000, 0x00ea0000, 0x00650000, 0x007a0000, 0x00ae0000, 0x00080000, 0x00ba0000, 0x00780000, 0x00250000, 0x002e0000, 0x001c0000, 0x00a60000, 0x00b40000, 0x00c60000, 0x00e80000, 0x00dd0000, 0x00740000, 0x001f0000, 0x004b0000, 0x00bd0000, 0x008b0000, 0x008a0000, 0x00700000, 0x003e0000, 0x00b50000, 0x00660000, 0x00480000, 0x00030000, 0x00f60000, 0x000e0000, 0x00610000, 0x00350000, 0x00570000, 0x00b90000, 0x00860000, 0x00c10000, 0x001d0000, 0x009e0000, 0x00e10000, 0x00f80000, 0x00980000, 0x00110000, 0x00690000, 0x00d90000, 0x008e0000, 0x00940000, 0x009b0000, 0x001e0000, 0x00870000, 0x00e90000, 0x00ce0000, 0x00550000, 0x00280000, 0x00df0000, 0x008c0000, 0x00a10000, 0x00890000, 0x000d0000, 0x00bf0000, 0x00e60000, 0x00420000, 0x00680000, 0x00410000, 0x00990000, 0x002d0000, 0x000f0000, 0x00b00000, 0x00540000, 0x00bb0000, 0x00160000 }, { 0x63000000, 0x7c000000, 0x77000000, 0x7b000000, 0xf2000000, 0x6b000000, 0x6f000000, 0xc5000000, 0x30000000, 0x01000000, 0x67000000, 0x2b000000, 0xfe000000, 0xd7000000, 0xab000000, 0x76000000, 0xca000000, 0x82000000, 0xc9000000, 0x7d000000, 0xfa000000, 0x59000000, 0x47000000, 0xf0000000, 0xad000000, 0xd4000000, 0xa2000000, 0xaf000000, 0x9c000000, 0xa4000000, 0x72000000, 0xc0000000, 0xb7000000, 0xfd000000, 0x93000000, 0x26000000, 0x36000000, 0x3f000000, 0xf7000000, 0xcc000000, 0x34000000, 0xa5000000, 0xe5000000, 0xf1000000, 0x71000000, 0xd8000000, 0x31000000, 0x15000000, 0x04000000, 0xc7000000, 0x23000000, 0xc3000000, 0x18000000, 0x96000000, 0x05000000, 0x9a000000, 0x07000000, 0x12000000, 0x80000000, 0xe2000000, 0xeb000000, 0x27000000, 0xb2000000, 0x75000000, 0x09000000, 0x83000000, 0x2c000000, 0x1a000000, 0x1b000000, 0x6e000000, 0x5a000000, 0xa0000000, 0x52000000, 0x3b000000, 0xd6000000, 0xb3000000, 0x29000000, 0xe3000000, 0x2f000000, 0x84000000, 0x53000000, 0xd1000000, 0x00000000, 0xed000000, 0x20000000, 0xfc000000, 0xb1000000, 0x5b000000, 0x6a000000, 0xcb000000, 0xbe000000, 0x39000000, 0x4a000000, 0x4c000000, 0x58000000, 0xcf000000, 0xd0000000, 0xef000000, 0xaa000000, 0xfb000000, 0x43000000, 0x4d000000, 0x33000000, 0x85000000, 0x45000000, 0xf9000000, 0x02000000, 0x7f000000, 0x50000000, 0x3c000000, 0x9f000000, 0xa8000000, 0x51000000, 0xa3000000, 0x40000000, 0x8f000000, 0x92000000, 0x9d000000, 0x38000000, 0xf5000000, 0xbc000000, 0xb6000000, 0xda000000, 0x21000000, 0x10000000, 0xff000000, 0xf3000000, 0xd2000000, 0xcd000000, 0x0c000000, 0x13000000, 0xec000000, 0x5f000000, 0x97000000, 0x44000000, 0x17000000, 0xc4000000, 0xa7000000, 0x7e000000, 0x3d000000, 0x64000000, 0x5d000000, 0x19000000, 0x73000000, 0x60000000, 0x81000000, 0x4f000000, 0xdc000000, 0x22000000, 0x2a000000, 0x90000000, 0x88000000, 0x46000000, 0xee000000, 0xb8000000, 0x14000000, 0xde000000, 0x5e000000, 0x0b000000, 0xdb000000, 0xe0000000, 0x32000000, 0x3a000000, 0x0a000000, 0x49000000, 0x06000000, 0x24000000, 0x5c000000, 0xc2000000, 0xd3000000, 0xac000000, 0x62000000, 0x91000000, 0x95000000, 0xe4000000, 0x79000000, 0xe7000000, 0xc8000000, 0x37000000, 0x6d000000, 0x8d000000, 0xd5000000, 0x4e000000, 0xa9000000, 0x6c000000, 0x56000000, 0xf4000000, 0xea000000, 0x65000000, 0x7a000000, 0xae000000, 0x08000000, 0xba000000, 0x78000000, 0x25000000, 0x2e000000, 0x1c000000, 0xa6000000, 0xb4000000, 0xc6000000, 0xe8000000, 0xdd000000, 0x74000000, 0x1f000000, 0x4b000000, 0xbd000000, 0x8b000000, 0x8a000000, 0x70000000, 0x3e000000, 0xb5000000, 0x66000000, 0x48000000, 0x03000000, 0xf6000000, 0x0e000000, 0x61000000, 0x35000000, 0x57000000, 0xb9000000, 0x86000000, 0xc1000000, 0x1d000000, 0x9e000000, 0xe1000000, 0xf8000000, 0x98000000, 0x11000000, 0x69000000, 0xd9000000, 0x8e000000, 0x94000000, 0x9b000000, 0x1e000000, 0x87000000, 0xe9000000, 0xce000000, 0x55000000, 0x28000000, 0xdf000000, 0x8c000000, 0xa1000000, 0x89000000, 0x0d000000, 0xbf000000, 0xe6000000, 0x42000000, 0x68000000, 0x41000000, 0x99000000, 0x2d000000, 0x0f000000, 0xb0000000, 0x54000000, 0xbb000000, 0x16000000 } }; static const uint32_t t_im[4][256] = { { 0x00000000, 0x0b0d090e, 0x161a121c, 0x1d171b12, 0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a, 0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362, 0x745c6c48, 0x7f516546, 0x62467e54, 0x694b775a, 0xb0d090e0, 0xbbdd99ee, 0xa6ca82fc, 0xadc78bf2, 0x9ce4b4d8, 0x97e9bdd6, 0x8afea6c4, 0x81f3afca, 0xe8b8d890, 0xe3b5d19e, 0xfea2ca8c, 0xf5afc382, 0xc48cfca8, 0xcf81f5a6, 0xd296eeb4, 0xd99be7ba, 0x7bbb3bdb, 0x70b632d5, 0x6da129c7, 0x66ac20c9, 0x578f1fe3, 0x5c8216ed, 0x41950dff, 0x4a9804f1, 0x23d373ab, 0x28de7aa5, 0x35c961b7, 0x3ec468b9, 0x0fe75793, 0x04ea5e9d, 0x19fd458f, 0x12f04c81, 0xcb6bab3b, 0xc066a235, 0xdd71b927, 0xd67cb029, 0xe75f8f03, 0xec52860d, 0xf1459d1f, 0xfa489411, 0x9303e34b, 0x980eea45, 0x8519f157, 0x8e14f859, 0xbf37c773, 0xb43ace7d, 0xa92dd56f, 0xa220dc61, 0xf66d76ad, 0xfd607fa3, 0xe07764b1, 0xeb7a6dbf, 0xda595295, 0xd1545b9b, 0xcc434089, 0xc74e4987, 0xae053edd, 0xa50837d3, 0xb81f2cc1, 0xb31225cf, 0x82311ae5, 0x893c13eb, 0x942b08f9, 0x9f2601f7, 0x46bde64d, 0x4db0ef43, 0x50a7f451, 0x5baafd5f, 0x6a89c275, 0x6184cb7b, 0x7c93d069, 0x779ed967, 0x1ed5ae3d, 0x15d8a733, 0x08cfbc21, 0x03c2b52f, 0x32e18a05, 0x39ec830b, 0x24fb9819, 0x2ff69117, 0x8dd64d76, 0x86db4478, 0x9bcc5f6a, 0x90c15664, 0xa1e2694e, 0xaaef6040, 0xb7f87b52, 0xbcf5725c, 0xd5be0506, 0xdeb30c08, 0xc3a4171a, 0xc8a91e14, 0xf98a213e, 0xf2872830, 0xef903322, 0xe49d3a2c, 0x3d06dd96, 0x360bd498, 0x2b1ccf8a, 0x2011c684, 0x1132f9ae, 0x1a3ff0a0, 0x0728ebb2, 0x0c25e2bc, 0x656e95e6, 0x6e639ce8, 0x737487fa, 0x78798ef4, 0x495ab1de, 0x4257b8d0, 0x5f40a3c2, 0x544daacc, 0xf7daec41, 0xfcd7e54f, 0xe1c0fe5d, 0xeacdf753, 0xdbeec879, 0xd0e3c177, 0xcdf4da65, 0xc6f9d36b, 0xafb2a431, 0xa4bfad3f, 0xb9a8b62d, 0xb2a5bf23, 0x83868009, 0x888b8907, 0x959c9215, 0x9e919b1b, 0x470a7ca1, 0x4c0775af, 0x51106ebd, 0x5a1d67b3, 0x6b3e5899, 0x60335197, 0x7d244a85, 0x7629438b, 0x1f6234d1, 0x146f3ddf, 0x097826cd, 0x02752fc3, 0x335610e9, 0x385b19e7, 0x254c02f5, 0x2e410bfb, 0x8c61d79a, 0x876cde94, 0x9a7bc586, 0x9176cc88, 0xa055f3a2, 0xab58faac, 0xb64fe1be, 0xbd42e8b0, 0xd4099fea, 0xdf0496e4, 0xc2138df6, 0xc91e84f8, 0xf83dbbd2, 0xf330b2dc, 0xee27a9ce, 0xe52aa0c0, 0x3cb1477a, 0x37bc4e74, 0x2aab5566, 0x21a65c68, 0x10856342, 0x1b886a4c, 0x069f715e, 0x0d927850, 0x64d90f0a, 0x6fd40604, 0x72c31d16, 0x79ce1418, 0x48ed2b32, 0x43e0223c, 0x5ef7392e, 0x55fa3020, 0x01b79aec, 0x0aba93e2, 0x17ad88f0, 0x1ca081fe, 0x2d83bed4, 0x268eb7da, 0x3b99acc8, 0x3094a5c6, 0x59dfd29c, 0x52d2db92, 0x4fc5c080, 0x44c8c98e, 0x75ebf6a4, 0x7ee6ffaa, 0x63f1e4b8, 0x68fcedb6, 0xb1670a0c, 0xba6a0302, 0xa77d1810, 0xac70111e, 0x9d532e34, 0x965e273a, 0x8b493c28, 0x80443526, 0xe90f427c, 0xe2024b72, 0xff155060, 0xf418596e, 0xc53b6644, 0xce366f4a, 0xd3217458, 0xd82c7d56, 0x7a0ca137, 0x7101a839, 0x6c16b32b, 0x671bba25, 0x5638850f, 0x5d358c01, 0x40229713, 0x4b2f9e1d, 0x2264e947, 0x2969e049, 0x347efb5b, 0x3f73f255, 0x0e50cd7f, 0x055dc471, 0x184adf63, 0x1347d66d, 0xcadc31d7, 0xc1d138d9, 0xdcc623cb, 0xd7cb2ac5, 0xe6e815ef, 0xede51ce1, 0xf0f207f3, 0xfbff0efd, 0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5, 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d }, { 0x00000000, 0x0d090e0b, 0x1a121c16, 0x171b121d, 0x3424382c, 0x392d3627, 0x2e36243a, 0x233f2a31, 0x68487058, 0x65417e53, 0x725a6c4e, 0x7f536245, 0x5c6c4874, 0x5165467f, 0x467e5462, 0x4b775a69, 0xd090e0b0, 0xdd99eebb, 0xca82fca6, 0xc78bf2ad, 0xe4b4d89c, 0xe9bdd697, 0xfea6c48a, 0xf3afca81, 0xb8d890e8, 0xb5d19ee3, 0xa2ca8cfe, 0xafc382f5, 0x8cfca8c4, 0x81f5a6cf, 0x96eeb4d2, 0x9be7bad9, 0xbb3bdb7b, 0xb632d570, 0xa129c76d, 0xac20c966, 0x8f1fe357, 0x8216ed5c, 0x950dff41, 0x9804f14a, 0xd373ab23, 0xde7aa528, 0xc961b735, 0xc468b93e, 0xe757930f, 0xea5e9d04, 0xfd458f19, 0xf04c8112, 0x6bab3bcb, 0x66a235c0, 0x71b927dd, 0x7cb029d6, 0x5f8f03e7, 0x52860dec, 0x459d1ff1, 0x489411fa, 0x03e34b93, 0x0eea4598, 0x19f15785, 0x14f8598e, 0x37c773bf, 0x3ace7db4, 0x2dd56fa9, 0x20dc61a2, 0x6d76adf6, 0x607fa3fd, 0x7764b1e0, 0x7a6dbfeb, 0x595295da, 0x545b9bd1, 0x434089cc, 0x4e4987c7, 0x053eddae, 0x0837d3a5, 0x1f2cc1b8, 0x1225cfb3, 0x311ae582, 0x3c13eb89, 0x2b08f994, 0x2601f79f, 0xbde64d46, 0xb0ef434d, 0xa7f45150, 0xaafd5f5b, 0x89c2756a, 0x84cb7b61, 0x93d0697c, 0x9ed96777, 0xd5ae3d1e, 0xd8a73315, 0xcfbc2108, 0xc2b52f03, 0xe18a0532, 0xec830b39, 0xfb981924, 0xf691172f, 0xd64d768d, 0xdb447886, 0xcc5f6a9b, 0xc1566490, 0xe2694ea1, 0xef6040aa, 0xf87b52b7, 0xf5725cbc, 0xbe0506d5, 0xb30c08de, 0xa4171ac3, 0xa91e14c8, 0x8a213ef9, 0x872830f2, 0x903322ef, 0x9d3a2ce4, 0x06dd963d, 0x0bd49836, 0x1ccf8a2b, 0x11c68420, 0x32f9ae11, 0x3ff0a01a, 0x28ebb207, 0x25e2bc0c, 0x6e95e665, 0x639ce86e, 0x7487fa73, 0x798ef478, 0x5ab1de49, 0x57b8d042, 0x40a3c25f, 0x4daacc54, 0xdaec41f7, 0xd7e54ffc, 0xc0fe5de1, 0xcdf753ea, 0xeec879db, 0xe3c177d0, 0xf4da65cd, 0xf9d36bc6, 0xb2a431af, 0xbfad3fa4, 0xa8b62db9, 0xa5bf23b2, 0x86800983, 0x8b890788, 0x9c921595, 0x919b1b9e, 0x0a7ca147, 0x0775af4c, 0x106ebd51, 0x1d67b35a, 0x3e58996b, 0x33519760, 0x244a857d, 0x29438b76, 0x6234d11f, 0x6f3ddf14, 0x7826cd09, 0x752fc302, 0x5610e933, 0x5b19e738, 0x4c02f525, 0x410bfb2e, 0x61d79a8c, 0x6cde9487, 0x7bc5869a, 0x76cc8891, 0x55f3a2a0, 0x58faacab, 0x4fe1beb6, 0x42e8b0bd, 0x099fead4, 0x0496e4df, 0x138df6c2, 0x1e84f8c9, 0x3dbbd2f8, 0x30b2dcf3, 0x27a9ceee, 0x2aa0c0e5, 0xb1477a3c, 0xbc4e7437, 0xab55662a, 0xa65c6821, 0x85634210, 0x886a4c1b, 0x9f715e06, 0x9278500d, 0xd90f0a64, 0xd406046f, 0xc31d1672, 0xce141879, 0xed2b3248, 0xe0223c43, 0xf7392e5e, 0xfa302055, 0xb79aec01, 0xba93e20a, 0xad88f017, 0xa081fe1c, 0x83bed42d, 0x8eb7da26, 0x99acc83b, 0x94a5c630, 0xdfd29c59, 0xd2db9252, 0xc5c0804f, 0xc8c98e44, 0xebf6a475, 0xe6ffaa7e, 0xf1e4b863, 0xfcedb668, 0x670a0cb1, 0x6a0302ba, 0x7d1810a7, 0x70111eac, 0x532e349d, 0x5e273a96, 0x493c288b, 0x44352680, 0x0f427ce9, 0x024b72e2, 0x155060ff, 0x18596ef4, 0x3b6644c5, 0x366f4ace, 0x217458d3, 0x2c7d56d8, 0x0ca1377a, 0x01a83971, 0x16b32b6c, 0x1bba2567, 0x38850f56, 0x358c015d, 0x22971340, 0x2f9e1d4b, 0x64e94722, 0x69e04929, 0x7efb5b34, 0x73f2553f, 0x50cd7f0e, 0x5dc47105, 0x4adf6318, 0x47d66d13, 0xdc31d7ca, 0xd138d9c1, 0xc623cbdc, 0xcb2ac5d7, 0xe815efe6, 0xe51ce1ed, 0xf207f3f0, 0xff0efdfb, 0xb479a792, 0xb970a999, 0xae6bbb84, 0xa362b58f, 0x805d9fbe, 0x8d5491b5, 0x9a4f83a8, 0x97468da3 }, { 0x00000000, 0x090e0b0d, 0x121c161a, 0x1b121d17, 0x24382c34, 0x2d362739, 0x36243a2e, 0x3f2a3123, 0x48705868, 0x417e5365, 0x5a6c4e72, 0x5362457f, 0x6c48745c, 0x65467f51, 0x7e546246, 0x775a694b, 0x90e0b0d0, 0x99eebbdd, 0x82fca6ca, 0x8bf2adc7, 0xb4d89ce4, 0xbdd697e9, 0xa6c48afe, 0xafca81f3, 0xd890e8b8, 0xd19ee3b5, 0xca8cfea2, 0xc382f5af, 0xfca8c48c, 0xf5a6cf81, 0xeeb4d296, 0xe7bad99b, 0x3bdb7bbb, 0x32d570b6, 0x29c76da1, 0x20c966ac, 0x1fe3578f, 0x16ed5c82, 0x0dff4195, 0x04f14a98, 0x73ab23d3, 0x7aa528de, 0x61b735c9, 0x68b93ec4, 0x57930fe7, 0x5e9d04ea, 0x458f19fd, 0x4c8112f0, 0xab3bcb6b, 0xa235c066, 0xb927dd71, 0xb029d67c, 0x8f03e75f, 0x860dec52, 0x9d1ff145, 0x9411fa48, 0xe34b9303, 0xea45980e, 0xf1578519, 0xf8598e14, 0xc773bf37, 0xce7db43a, 0xd56fa92d, 0xdc61a220, 0x76adf66d, 0x7fa3fd60, 0x64b1e077, 0x6dbfeb7a, 0x5295da59, 0x5b9bd154, 0x4089cc43, 0x4987c74e, 0x3eddae05, 0x37d3a508, 0x2cc1b81f, 0x25cfb312, 0x1ae58231, 0x13eb893c, 0x08f9942b, 0x01f79f26, 0xe64d46bd, 0xef434db0, 0xf45150a7, 0xfd5f5baa, 0xc2756a89, 0xcb7b6184, 0xd0697c93, 0xd967779e, 0xae3d1ed5, 0xa73315d8, 0xbc2108cf, 0xb52f03c2, 0x8a0532e1, 0x830b39ec, 0x981924fb, 0x91172ff6, 0x4d768dd6, 0x447886db, 0x5f6a9bcc, 0x566490c1, 0x694ea1e2, 0x6040aaef, 0x7b52b7f8, 0x725cbcf5, 0x0506d5be, 0x0c08deb3, 0x171ac3a4, 0x1e14c8a9, 0x213ef98a, 0x2830f287, 0x3322ef90, 0x3a2ce49d, 0xdd963d06, 0xd498360b, 0xcf8a2b1c, 0xc6842011, 0xf9ae1132, 0xf0a01a3f, 0xebb20728, 0xe2bc0c25, 0x95e6656e, 0x9ce86e63, 0x87fa7374, 0x8ef47879, 0xb1de495a, 0xb8d04257, 0xa3c25f40, 0xaacc544d, 0xec41f7da, 0xe54ffcd7, 0xfe5de1c0, 0xf753eacd, 0xc879dbee, 0xc177d0e3, 0xda65cdf4, 0xd36bc6f9, 0xa431afb2, 0xad3fa4bf, 0xb62db9a8, 0xbf23b2a5, 0x80098386, 0x8907888b, 0x9215959c, 0x9b1b9e91, 0x7ca1470a, 0x75af4c07, 0x6ebd5110, 0x67b35a1d, 0x58996b3e, 0x51976033, 0x4a857d24, 0x438b7629, 0x34d11f62, 0x3ddf146f, 0x26cd0978, 0x2fc30275, 0x10e93356, 0x19e7385b, 0x02f5254c, 0x0bfb2e41, 0xd79a8c61, 0xde94876c, 0xc5869a7b, 0xcc889176, 0xf3a2a055, 0xfaacab58, 0xe1beb64f, 0xe8b0bd42, 0x9fead409, 0x96e4df04, 0x8df6c213, 0x84f8c91e, 0xbbd2f83d, 0xb2dcf330, 0xa9ceee27, 0xa0c0e52a, 0x477a3cb1, 0x4e7437bc, 0x55662aab, 0x5c6821a6, 0x63421085, 0x6a4c1b88, 0x715e069f, 0x78500d92, 0x0f0a64d9, 0x06046fd4, 0x1d1672c3, 0x141879ce, 0x2b3248ed, 0x223c43e0, 0x392e5ef7, 0x302055fa, 0x9aec01b7, 0x93e20aba, 0x88f017ad, 0x81fe1ca0, 0xbed42d83, 0xb7da268e, 0xacc83b99, 0xa5c63094, 0xd29c59df, 0xdb9252d2, 0xc0804fc5, 0xc98e44c8, 0xf6a475eb, 0xffaa7ee6, 0xe4b863f1, 0xedb668fc, 0x0a0cb167, 0x0302ba6a, 0x1810a77d, 0x111eac70, 0x2e349d53, 0x273a965e, 0x3c288b49, 0x35268044, 0x427ce90f, 0x4b72e202, 0x5060ff15, 0x596ef418, 0x6644c53b, 0x6f4ace36, 0x7458d321, 0x7d56d82c, 0xa1377a0c, 0xa8397101, 0xb32b6c16, 0xba25671b, 0x850f5638, 0x8c015d35, 0x97134022, 0x9e1d4b2f, 0xe9472264, 0xe0492969, 0xfb5b347e, 0xf2553f73, 0xcd7f0e50, 0xc471055d, 0xdf63184a, 0xd66d1347, 0x31d7cadc, 0x38d9c1d1, 0x23cbdcc6, 0x2ac5d7cb, 0x15efe6e8, 0x1ce1ede5, 0x07f3f0f2, 0x0efdfbff, 0x79a792b4, 0x70a999b9, 0x6bbb84ae, 0x62b58fa3, 0x5d9fbe80, 0x5491b58d, 0x4f83a89a, 0x468da397 }, { 0x00000000, 0x0e0b0d09, 0x1c161a12, 0x121d171b, 0x382c3424, 0x3627392d, 0x243a2e36, 0x2a31233f, 0x70586848, 0x7e536541, 0x6c4e725a, 0x62457f53, 0x48745c6c, 0x467f5165, 0x5462467e, 0x5a694b77, 0xe0b0d090, 0xeebbdd99, 0xfca6ca82, 0xf2adc78b, 0xd89ce4b4, 0xd697e9bd, 0xc48afea6, 0xca81f3af, 0x90e8b8d8, 0x9ee3b5d1, 0x8cfea2ca, 0x82f5afc3, 0xa8c48cfc, 0xa6cf81f5, 0xb4d296ee, 0xbad99be7, 0xdb7bbb3b, 0xd570b632, 0xc76da129, 0xc966ac20, 0xe3578f1f, 0xed5c8216, 0xff41950d, 0xf14a9804, 0xab23d373, 0xa528de7a, 0xb735c961, 0xb93ec468, 0x930fe757, 0x9d04ea5e, 0x8f19fd45, 0x8112f04c, 0x3bcb6bab, 0x35c066a2, 0x27dd71b9, 0x29d67cb0, 0x03e75f8f, 0x0dec5286, 0x1ff1459d, 0x11fa4894, 0x4b9303e3, 0x45980eea, 0x578519f1, 0x598e14f8, 0x73bf37c7, 0x7db43ace, 0x6fa92dd5, 0x61a220dc, 0xadf66d76, 0xa3fd607f, 0xb1e07764, 0xbfeb7a6d, 0x95da5952, 0x9bd1545b, 0x89cc4340, 0x87c74e49, 0xddae053e, 0xd3a50837, 0xc1b81f2c, 0xcfb31225, 0xe582311a, 0xeb893c13, 0xf9942b08, 0xf79f2601, 0x4d46bde6, 0x434db0ef, 0x5150a7f4, 0x5f5baafd, 0x756a89c2, 0x7b6184cb, 0x697c93d0, 0x67779ed9, 0x3d1ed5ae, 0x3315d8a7, 0x2108cfbc, 0x2f03c2b5, 0x0532e18a, 0x0b39ec83, 0x1924fb98, 0x172ff691, 0x768dd64d, 0x7886db44, 0x6a9bcc5f, 0x6490c156, 0x4ea1e269, 0x40aaef60, 0x52b7f87b, 0x5cbcf572, 0x06d5be05, 0x08deb30c, 0x1ac3a417, 0x14c8a91e, 0x3ef98a21, 0x30f28728, 0x22ef9033, 0x2ce49d3a, 0x963d06dd, 0x98360bd4, 0x8a2b1ccf, 0x842011c6, 0xae1132f9, 0xa01a3ff0, 0xb20728eb, 0xbc0c25e2, 0xe6656e95, 0xe86e639c, 0xfa737487, 0xf478798e, 0xde495ab1, 0xd04257b8, 0xc25f40a3, 0xcc544daa, 0x41f7daec, 0x4ffcd7e5, 0x5de1c0fe, 0x53eacdf7, 0x79dbeec8, 0x77d0e3c1, 0x65cdf4da, 0x6bc6f9d3, 0x31afb2a4, 0x3fa4bfad, 0x2db9a8b6, 0x23b2a5bf, 0x09838680, 0x07888b89, 0x15959c92, 0x1b9e919b, 0xa1470a7c, 0xaf4c0775, 0xbd51106e, 0xb35a1d67, 0x996b3e58, 0x97603351, 0x857d244a, 0x8b762943, 0xd11f6234, 0xdf146f3d, 0xcd097826, 0xc302752f, 0xe9335610, 0xe7385b19, 0xf5254c02, 0xfb2e410b, 0x9a8c61d7, 0x94876cde, 0x869a7bc5, 0x889176cc, 0xa2a055f3, 0xacab58fa, 0xbeb64fe1, 0xb0bd42e8, 0xead4099f, 0xe4df0496, 0xf6c2138d, 0xf8c91e84, 0xd2f83dbb, 0xdcf330b2, 0xceee27a9, 0xc0e52aa0, 0x7a3cb147, 0x7437bc4e, 0x662aab55, 0x6821a65c, 0x42108563, 0x4c1b886a, 0x5e069f71, 0x500d9278, 0x0a64d90f, 0x046fd406, 0x1672c31d, 0x1879ce14, 0x3248ed2b, 0x3c43e022, 0x2e5ef739, 0x2055fa30, 0xec01b79a, 0xe20aba93, 0xf017ad88, 0xfe1ca081, 0xd42d83be, 0xda268eb7, 0xc83b99ac, 0xc63094a5, 0x9c59dfd2, 0x9252d2db, 0x804fc5c0, 0x8e44c8c9, 0xa475ebf6, 0xaa7ee6ff, 0xb863f1e4, 0xb668fced, 0x0cb1670a, 0x02ba6a03, 0x10a77d18, 0x1eac7011, 0x349d532e, 0x3a965e27, 0x288b493c, 0x26804435, 0x7ce90f42, 0x72e2024b, 0x60ff1550, 0x6ef41859, 0x44c53b66, 0x4ace366f, 0x58d32174, 0x56d82c7d, 0x377a0ca1, 0x397101a8, 0x2b6c16b3, 0x25671bba, 0x0f563885, 0x015d358c, 0x13402297, 0x1d4b2f9e, 0x472264e9, 0x492969e0, 0x5b347efb, 0x553f73f2, 0x7f0e50cd, 0x71055dc4, 0x63184adf, 0x6d1347d6, 0xd7cadc31, 0xd9c1d138, 0xcbdcc623, 0xc5d7cb2a, 0xefe6e815, 0xe1ede51c, 0xf3f0f207, 0xfdfbff0e, 0xa792b479, 0xa999b970, 0xbb84ae6b, 0xb58fa362, 0x9fbe805d, 0x91b58d54, 0x83a89a4f, 0x8da39746 } }; #ifdef __cplusplus } #endif #endif /* _AESTAB2_H */