diff --git a/cipher/bithelp.h b/cipher/bithelp.h index 785701e3..734dcbb5 100644 --- a/cipher/bithelp.h +++ b/cipher/bithelp.h @@ -1,56 +1,96 @@ /* bithelp.h - Some bit manipulation helpers * Copyright (C) 1999, 2002 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef G10_BITHELP_H #define G10_BITHELP_H +#include "types.h" + /**************** * Rotate the 32 bit unsigned integer X by N bits left/right */ #if defined(__GNUC__) && defined(__i386__) static inline u32 rol( u32 x, int n) { __asm__("roll %%cl,%0" :"=r" (x) :"0" (x),"c" (n) :"cc"); return x; } #else #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) #endif #if defined(__GNUC__) && defined(__i386__) static inline u32 ror(u32 x, int n) { __asm__("rorl %%cl,%0" :"=r" (x) :"0" (x),"c" (n) :"cc"); return x; } #else #define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) ) #endif +/* Byte swap for 32-bit and 64-bit integers. If available, use compiler + provided helpers. */ +#ifdef HAVE_BUILTIN_BSWAP32 +# define bswap32 __builtin_bswap32 +#else +static inline u32 bswap32(u32 x) +{ + return ((rol(x, 8) & 0x00ff00ffL) | (ror(x, 8) & 0xff00ff00L)); +} +#endif + +#ifdef HAVE_U64_TYPEDEF +# ifdef HAVE_BUILTIN_BSWAP64 +# define bswap64 __builtin_bswap64 +# else +static inline u64 bswap64(u64 x) +{ + return ((u64)bswap32(x) << 32) | (bswap32(x >> 32)); +} +# endif +#endif + +/* Endian dependent byte swap operations. */ +#ifdef WORDS_BIGENDIAN +# define le_bswap32(x) bswap32(x) +# define be_bswap32(x) ((u32)(x)) +# ifdef HAVE_U64_TYPEDEF +# define le_bswap64(x) bswap64(x) +# define be_bswap64(x) ((u64)(x)) +# endif +#else +# define le_bswap32(x) ((u32)(x)) +# define be_bswap32(x) bswap32(x) +# ifdef HAVE_U64_TYPEDEF +# define le_bswap64(x) ((u64)(x)) +# define be_bswap64(x) bswap64(x) +# endif +#endif #endif /*G10_BITHELP_H*/ diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 80e1ec74..61042ed9 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -1,985 +1,966 @@ /* blowfish.c - Blowfish encryption * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * For a description of the algorithm, see: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. * ISBN 0-471-11709-9. Pages 336 ff. */ /* Test values: * key "abcdefghijklmnopqrstuvwxyz"; * plain "BLOWFISH" * cipher 32 4E D0 FE F4 13 A2 03 * */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "cipher-selftest.h" #define BLOWFISH_BLOCKSIZE 8 #define BLOWFISH_ROUNDS 16 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ (BLOWFISH_ROUNDS == 16) # define USE_AMD64_ASM 1 #endif /* USE_ARMV6_ASM indicates whether to use ARMv6 assembly code. */ #undef USE_ARMV6_ASM #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) # if (BLOWFISH_ROUNDS == 16) && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) # define USE_ARMV6_ASM 1 # endif #endif typedef struct { u32 s0[256]; u32 s1[256]; u32 s2[256]; u32 s3[256]; u32 p[BLOWFISH_ROUNDS+2]; } BLOWFISH_context; static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen); static unsigned int encrypt_block (void *bc, byte *outbuf, const byte *inbuf); static unsigned int decrypt_block (void *bc, byte *outbuf, const byte *inbuf); /* precomputed S boxes */ static const u32 ks0[256] = { 0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96, 0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16, 0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658, 0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013, 0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E, 0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60, 0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6, 0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A, 0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C, 0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193, 0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1, 0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239, 0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A, 0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3, 0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176, 0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE, 0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706, 0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B, 0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B, 0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463, 0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C, 0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3, 0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A, 0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8, 0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760, 0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB, 0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8, 0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B, 0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33, 0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4, 0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0, 0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C, 0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777, 0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299, 0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705, 0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF, 0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E, 0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA, 0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9, 0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915, 0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F, 0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664, 0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A }; static const u32 ks1[256] = { 0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D, 0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1, 0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65, 0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1, 0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9, 0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737, 0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D, 0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD, 0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC, 0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41, 0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908, 0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF, 0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124, 0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C, 0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908, 0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD, 0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B, 0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E, 0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA, 0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A, 0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D, 0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66, 0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5, 0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84, 0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96, 0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14, 0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA, 0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7, 0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77, 0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99, 0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054, 0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73, 0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA, 0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105, 0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646, 0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285, 0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA, 0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB, 0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E, 0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC, 0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD, 0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20, 0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 }; static const u32 ks2[256] = { 0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7, 0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF, 0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF, 0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504, 0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4, 0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE, 0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC, 0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B, 0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332, 0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527, 0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58, 0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C, 0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22, 0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17, 0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60, 0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115, 0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99, 0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0, 0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74, 0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D, 0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3, 0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3, 0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979, 0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C, 0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA, 0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A, 0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086, 0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC, 0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24, 0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2, 0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84, 0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C, 0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09, 0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10, 0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE, 0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027, 0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0, 0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634, 0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188, 0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC, 0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8, 0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837, 0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 }; static const u32 ks3[256] = { 0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742, 0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B, 0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79, 0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6, 0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A, 0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4, 0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1, 0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59, 0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797, 0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28, 0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6, 0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28, 0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA, 0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A, 0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5, 0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F, 0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE, 0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680, 0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD, 0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB, 0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB, 0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370, 0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC, 0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048, 0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC, 0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9, 0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A, 0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F, 0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A, 0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1, 0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B, 0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E, 0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E, 0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F, 0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623, 0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC, 0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A, 0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6, 0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3, 0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060, 0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C, 0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F, 0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 }; static const u32 ps[BLOWFISH_ROUNDS+2] = { 0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0, 0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C, 0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B }; #ifdef USE_AMD64_ASM /* Assembly implementations of Blowfish. */ extern void _gcry_blowfish_amd64_do_encrypt(BLOWFISH_context *c, u32 *ret_xl, u32 *ret_xr); extern void _gcry_blowfish_amd64_encrypt_block(BLOWFISH_context *c, byte *out, const byte *in); extern void _gcry_blowfish_amd64_decrypt_block(BLOWFISH_context *c, byte *out, const byte *in); /* These assembly implementations process four blocks in parallel. */ extern void _gcry_blowfish_amd64_ctr_enc(BLOWFISH_context *ctx, byte *out, const byte *in, byte *ctr); extern void _gcry_blowfish_amd64_cbc_dec(BLOWFISH_context *ctx, byte *out, const byte *in, byte *iv); extern void _gcry_blowfish_amd64_cfb_dec(BLOWFISH_context *ctx, byte *out, const byte *in, byte *iv); static void do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { _gcry_blowfish_amd64_do_encrypt (bc, ret_xl, ret_xr); } static void do_encrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf) { _gcry_blowfish_amd64_encrypt_block (context, outbuf, inbuf); } static void do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf) { _gcry_blowfish_amd64_decrypt_block (context, outbuf, inbuf); } static unsigned int encrypt_block (void *context , byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_encrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (2*8); } static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_decrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (2*8); } #elif defined(USE_ARMV6_ASM) /* Assembly implementations of Blowfish. */ extern void _gcry_blowfish_armv6_do_encrypt(BLOWFISH_context *c, u32 *ret_xl, u32 *ret_xr); extern void _gcry_blowfish_armv6_encrypt_block(BLOWFISH_context *c, byte *out, const byte *in); extern void _gcry_blowfish_armv6_decrypt_block(BLOWFISH_context *c, byte *out, const byte *in); /* These assembly implementations process two blocks in parallel. */ extern void _gcry_blowfish_armv6_ctr_enc(BLOWFISH_context *ctx, byte *out, const byte *in, byte *ctr); extern void _gcry_blowfish_armv6_cbc_dec(BLOWFISH_context *ctx, byte *out, const byte *in, byte *iv); extern void _gcry_blowfish_armv6_cfb_dec(BLOWFISH_context *ctx, byte *out, const byte *in, byte *iv); static void do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { _gcry_blowfish_armv6_do_encrypt (bc, ret_xl, ret_xr); } static void do_encrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf) { _gcry_blowfish_armv6_encrypt_block (context, outbuf, inbuf); } static void do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf) { _gcry_blowfish_armv6_decrypt_block (context, outbuf, inbuf); } static unsigned int encrypt_block (void *context , byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_encrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (10*4); } static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *c = (BLOWFISH_context *) context; do_decrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (10*4); } #else /*USE_ARMV6_ASM*/ #if BLOWFISH_ROUNDS != 16 static inline u32 function_F( BLOWFISH_context *bc, u32 x ) { u16 a, b, c, d; #ifdef WORDS_BIGENDIAN a = ((byte*)&x)[0]; b = ((byte*)&x)[1]; c = ((byte*)&x)[2]; d = ((byte*)&x)[3]; #else a = ((byte*)&x)[3]; b = ((byte*)&x)[2]; c = ((byte*)&x)[1]; d = ((byte*)&x)[0]; #endif return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d]; } #endif #ifdef WORDS_BIGENDIAN #define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \ ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] ) #else #define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \ ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] ) #endif #define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0) static void do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { #if BLOWFISH_ROUNDS == 16 u32 xl, xr, *s0, *s1, *s2, *s3, *p; xl = *ret_xl; xr = *ret_xr; p = bc->p; s0 = bc->s0; s1 = bc->s1; s2 = bc->s2; s3 = bc->s3; R( xl, xr, 0); R( xr, xl, 1); R( xl, xr, 2); R( xr, xl, 3); R( xl, xr, 4); R( xr, xl, 5); R( xl, xr, 6); R( xr, xl, 7); R( xl, xr, 8); R( xr, xl, 9); R( xl, xr, 10); R( xr, xl, 11); R( xl, xr, 12); R( xr, xl, 13); R( xl, xr, 14); R( xr, xl, 15); xl ^= p[BLOWFISH_ROUNDS]; xr ^= p[BLOWFISH_ROUNDS+1]; *ret_xl = xr; *ret_xr = xl; #else u32 xl, xr, temp, *p; int i; xl = *ret_xl; xr = *ret_xr; p = bc->p; for(i=0; i < BLOWFISH_ROUNDS; i++ ) { xl ^= p[i]; xr ^= function_F(bc, xl); temp = xl; xl = xr; xr = temp; } temp = xl; xl = xr; xr = temp; xr ^= p[BLOWFISH_ROUNDS]; xl ^= p[BLOWFISH_ROUNDS+1]; *ret_xl = xl; *ret_xr = xr; #endif } static void decrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr ) { #if BLOWFISH_ROUNDS == 16 u32 xl, xr, *s0, *s1, *s2, *s3, *p; xl = *ret_xl; xr = *ret_xr; p = bc->p; s0 = bc->s0; s1 = bc->s1; s2 = bc->s2; s3 = bc->s3; R( xl, xr, 17); R( xr, xl, 16); R( xl, xr, 15); R( xr, xl, 14); R( xl, xr, 13); R( xr, xl, 12); R( xl, xr, 11); R( xr, xl, 10); R( xl, xr, 9); R( xr, xl, 8); R( xl, xr, 7); R( xr, xl, 6); R( xl, xr, 5); R( xr, xl, 4); R( xl, xr, 3); R( xr, xl, 2); xl ^= p[1]; xr ^= p[0]; *ret_xl = xr; *ret_xr = xl; #else u32 xl, xr, temp, *p; int i; xl = *ret_xl; xr = *ret_xr; p = bc->p; for (i=BLOWFISH_ROUNDS+1; i > 1; i-- ) { xl ^= p[i]; xr ^= function_F(bc, xl); temp = xl; xl = xr; xr = temp; } temp = xl; xl = xr; xr = temp; xr ^= p[1]; xl ^= p[0]; *ret_xl = xl; *ret_xr = xr; #endif } #undef F #undef R static void do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf ) { u32 d1, d2; - d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + d1 = buf_get_be32(inbuf); + d2 = buf_get_be32(inbuf + 4); do_encrypt( bc, &d1, &d2 ); - outbuf[0] = (d1 >> 24) & 0xff; - outbuf[1] = (d1 >> 16) & 0xff; - outbuf[2] = (d1 >> 8) & 0xff; - outbuf[3] = d1 & 0xff; - outbuf[4] = (d2 >> 24) & 0xff; - outbuf[5] = (d2 >> 16) & 0xff; - outbuf[6] = (d2 >> 8) & 0xff; - outbuf[7] = d2 & 0xff; + buf_put_be32(outbuf, d1); + buf_put_be32(outbuf + 4, d2); } static unsigned int encrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *bc = (BLOWFISH_context *) context; do_encrypt_block (bc, outbuf, inbuf); return /*burn_stack*/ (64); } static void do_decrypt_block (BLOWFISH_context *bc, byte *outbuf, const byte *inbuf) { u32 d1, d2; - d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + d1 = buf_get_be32(inbuf); + d2 = buf_get_be32(inbuf + 4); decrypt( bc, &d1, &d2 ); - outbuf[0] = (d1 >> 24) & 0xff; - outbuf[1] = (d1 >> 16) & 0xff; - outbuf[2] = (d1 >> 8) & 0xff; - outbuf[3] = d1 & 0xff; - outbuf[4] = (d2 >> 24) & 0xff; - outbuf[5] = (d2 >> 16) & 0xff; - outbuf[6] = (d2 >> 8) & 0xff; - outbuf[7] = d2 & 0xff; + buf_put_be32(outbuf, d1); + buf_put_be32(outbuf + 4, d2); } static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { BLOWFISH_context *bc = (BLOWFISH_context *) context; do_decrypt_block (bc, outbuf, inbuf); return /*burn_stack*/ (64); } #endif /*!USE_AMD64_ASM&&!USE_ARMV6_ASM*/ /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size BLOWFISH_BLOCKSIZE. */ void _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[BLOWFISH_BLOCKSIZE]; int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE; int i; #ifdef USE_AMD64_ASM { if (nblocks >= 4) burn_stack_depth += 5 * sizeof(void*); /* Process data in 4 block chunks. */ while (nblocks >= 4) { _gcry_blowfish_amd64_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 4; outbuf += 4 * BLOWFISH_BLOCKSIZE; inbuf += 4 * BLOWFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #elif defined(USE_ARMV6_ASM) { /* Process data in 2 block chunks. */ while (nblocks >= 2) { _gcry_blowfish_armv6_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 2; outbuf += 2 * BLOWFISH_BLOCKSIZE; inbuf += 2 * BLOWFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ do_encrypt_block(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ buf_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE); outbuf += BLOWFISH_BLOCKSIZE; inbuf += BLOWFISH_BLOCKSIZE; /* Increment the counter. */ for (i = BLOWFISH_BLOCKSIZE; i > 0; i--) { ctr[i-1]++; if (ctr[i-1]) break; } } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[BLOWFISH_BLOCKSIZE]; int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE; #ifdef USE_AMD64_ASM { if (nblocks >= 4) burn_stack_depth += 5 * sizeof(void*); /* Process data in 4 block chunks. */ while (nblocks >= 4) { _gcry_blowfish_amd64_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 4; outbuf += 4 * BLOWFISH_BLOCKSIZE; inbuf += 4 * BLOWFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #elif defined(USE_ARMV6_ASM) { /* Process data in 2 block chunks. */ while (nblocks >= 2) { _gcry_blowfish_armv6_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 2; outbuf += 2 * BLOWFISH_BLOCKSIZE; inbuf += 2 * BLOWFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* We need to save INBUF away because it may be identical to OUTBUF. */ memcpy(savebuf, inbuf, BLOWFISH_BLOCKSIZE); do_decrypt_block (ctx, outbuf, inbuf); buf_xor(outbuf, outbuf, iv, BLOWFISH_BLOCKSIZE); memcpy(iv, savebuf, BLOWFISH_BLOCKSIZE); inbuf += BLOWFISH_BLOCKSIZE; outbuf += BLOWFISH_BLOCKSIZE; } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE; #ifdef USE_AMD64_ASM { if (nblocks >= 4) burn_stack_depth += 5 * sizeof(void*); /* Process data in 4 block chunks. */ while (nblocks >= 4) { _gcry_blowfish_amd64_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 4; outbuf += 4 * BLOWFISH_BLOCKSIZE; inbuf += 4 * BLOWFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #elif defined(USE_ARMV6_ASM) { /* Process data in 2 block chunks. */ while (nblocks >= 2) { _gcry_blowfish_armv6_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 2; outbuf += 2 * BLOWFISH_BLOCKSIZE; inbuf += 2 * BLOWFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { do_encrypt_block(ctx, iv, iv); buf_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE); outbuf += BLOWFISH_BLOCKSIZE; inbuf += BLOWFISH_BLOCKSIZE; } _gcry_burn_stack(burn_stack_depth); } /* Run the self-tests for BLOWFISH-CTR, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char * selftest_ctr (void) { const int nblocks = 4+1; const int blocksize = BLOWFISH_BLOCKSIZE; const int context_size = sizeof(BLOWFISH_context); return _gcry_selftest_helper_ctr("BLOWFISH", &bf_setkey, &encrypt_block, &_gcry_blowfish_ctr_enc, nblocks, blocksize, context_size); } /* Run the self-tests for BLOWFISH-CBC, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cbc (void) { const int nblocks = 4+2; const int blocksize = BLOWFISH_BLOCKSIZE; const int context_size = sizeof(BLOWFISH_context); return _gcry_selftest_helper_cbc("BLOWFISH", &bf_setkey, &encrypt_block, &_gcry_blowfish_cbc_dec, nblocks, blocksize, context_size); } /* Run the self-tests for BLOWFISH-CFB, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cfb (void) { const int nblocks = 4+2; const int blocksize = BLOWFISH_BLOCKSIZE; const int context_size = sizeof(BLOWFISH_context); return _gcry_selftest_helper_cfb("BLOWFISH", &bf_setkey, &encrypt_block, &_gcry_blowfish_cfb_dec, nblocks, blocksize, context_size); } static const char* selftest(void) { BLOWFISH_context c; byte plain[] = "BLOWFISH"; byte buffer[8]; byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; const char *r; bf_setkey( (void *) &c, (const unsigned char*)"abcdefghijklmnopqrstuvwxyz", 26 ); encrypt_block( (void *) &c, buffer, plain ); if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) ) return "Blowfish selftest failed (1)."; decrypt_block( (void *) &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) return "Blowfish selftest failed (2)."; bf_setkey( (void *) &c, key3, 8 ); encrypt_block( (void *) &c, buffer, plain3 ); if( memcmp( buffer, cipher3, 8 ) ) return "Blowfish selftest failed (3)."; decrypt_block( (void *) &c, buffer, buffer ); if( memcmp( buffer, plain3, 8 ) ) return "Blowfish selftest failed (4)."; if ( (r = selftest_cbc ()) ) return r; if ( (r = selftest_cfb ()) ) return r; if ( (r = selftest_ctr ()) ) return r; return NULL; } static gcry_err_code_t do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) { int i, j; u32 data, datal, datar; static int initialized; static const char *selftest_failed; if( !initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) log_error ("%s\n", selftest_failed ); } if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) c->p[i] = ps[i]; for(i=0; i < 256; i++ ) { c->s0[i] = ks0[i]; c->s1[i] = ks1[i]; c->s2[i] = ks2[i]; c->s3[i] = ks3[i]; } for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) { -#ifdef WORDS_BIGENDIAN - ((byte*)&data)[0] = key[j]; - ((byte*)&data)[1] = key[(j+1)%keylen]; - ((byte*)&data)[2] = key[(j+2)%keylen]; - ((byte*)&data)[3] = key[(j+3)%keylen]; -#else - ((byte*)&data)[3] = key[j]; - ((byte*)&data)[2] = key[(j+1)%keylen]; - ((byte*)&data)[1] = key[(j+2)%keylen]; - ((byte*)&data)[0] = key[(j+3)%keylen]; -#endif + data = ((u32)key[j] << 24) | + ((u32)key[(j+1)%keylen] << 16) | + ((u32)key[(j+2)%keylen] << 8) | + ((u32)key[(j+3)%keylen]); c->p[i] ^= data; j = (j+4) % keylen; } datal = datar = 0; for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) { do_encrypt( c, &datal, &datar ); c->p[i] = datal; c->p[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s0[i] = datal; c->s0[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s1[i] = datal; c->s1[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s2[i] = datal; c->s2[i+1] = datar; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s3[i] = datal; c->s3[i+1] = datar; } /* Check for weak key. A weak key is a key in which a value in the P-array (here c) occurs more than once per table. */ for(i=0; i < 255; i++ ) { for( j=i+1; j < 256; j++) { if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) || (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) ) return GPG_ERR_WEAK_KEY; } } return GPG_ERR_NO_ERROR; } static gcry_err_code_t bf_setkey (void *context, const byte *key, unsigned keylen) { BLOWFISH_context *c = (BLOWFISH_context *) context; gcry_err_code_t rc = do_bf_setkey (c, key, keylen); _gcry_burn_stack (64); return rc; } gcry_cipher_spec_t _gcry_cipher_spec_blowfish = { "BLOWFISH", NULL, NULL, BLOWFISH_BLOCKSIZE, 128, sizeof (BLOWFISH_context), bf_setkey, encrypt_block, decrypt_block }; diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index d829cf19..c637dac9 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -1,182 +1,325 @@ /* bufhelp.h - Some buffer manipulation helpers * Copyright © 2012 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef G10_BUFHELP_H #define G10_BUFHELP_H +#include + #ifdef HAVE_STDINT_H # include /* uintptr_t */ #elif defined(HAVE_INTTYPES_H) # include #else /* In this case, uintptr_t is provided by config.h. */ #endif +#include "bithelp.h" + #if defined(__i386__) || defined(__x86_64__) || \ (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) /* These architectures are able of unaligned memory accesses and can handle those fast. */ # define BUFHELP_FAST_UNALIGNED_ACCESS 1 #endif /* Optimized function for buffer xoring */ static inline void buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len) { byte *dst = _dst; const byte *src1 = _src1; const byte *src2 = _src2; uintptr_t *ldst; const uintptr_t *lsrc1, *lsrc2; #ifndef BUFHELP_FAST_UNALIGNED_ACCESS const unsigned int longmask = sizeof(uintptr_t) - 1; /* Skip fast processing if alignment of buffers do not match. */ if ((((uintptr_t)dst ^ (uintptr_t)src1) | ((uintptr_t)dst ^ (uintptr_t)src2)) & longmask) goto do_bytes; /* Handle unaligned head. */ for (; len && ((uintptr_t)dst & longmask); len--) *dst++ = *src1++ ^ *src2++; #endif ldst = (uintptr_t *)(void *)dst; lsrc1 = (const uintptr_t *)(const void *)src1; lsrc2 = (const uintptr_t *)(const void *)src2; for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t)) *ldst++ = *lsrc1++ ^ *lsrc2++; dst = (byte *)ldst; src1 = (const byte *)lsrc1; src2 = (const byte *)lsrc2; #ifndef BUFHELP_FAST_UNALIGNED_ACCESS do_bytes: #endif /* Handle tail. */ for (; len; len--) *dst++ = *src1++ ^ *src2++; } /* Optimized function for buffer xoring with two destination buffers. Used mainly by CFB mode encryption. */ static inline void buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len) { byte *dst1 = _dst1; byte *dst2 = _dst2; const byte *src = _src; uintptr_t *ldst1, *ldst2; const uintptr_t *lsrc; #ifndef BUFHELP_FAST_UNALIGNED_ACCESS const unsigned int longmask = sizeof(uintptr_t) - 1; /* Skip fast processing if alignment of buffers do not match. */ if ((((uintptr_t)src ^ (uintptr_t)dst1) | ((uintptr_t)src ^ (uintptr_t)dst2)) & longmask) goto do_bytes; /* Handle unaligned head. */ for (; len && ((uintptr_t)src & longmask); len--) *dst1++ = (*dst2++ ^= *src++); #endif ldst1 = (uintptr_t *)(void *)dst1; ldst2 = (uintptr_t *)(void *)dst2; lsrc = (const uintptr_t *)(const void *)src; for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t)) *ldst1++ = (*ldst2++ ^= *lsrc++); dst1 = (byte *)ldst1; dst2 = (byte *)ldst2; src = (const byte *)lsrc; #ifndef BUFHELP_FAST_UNALIGNED_ACCESS do_bytes: #endif /* Handle tail. */ for (; len; len--) *dst1++ = (*dst2++ ^= *src++); } /* Optimized function for combined buffer xoring and copying. Used by mainly CFB mode decryption. */ static inline void buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len) { byte *dst_xor = _dst_xor; byte *srcdst_cpy = _srcdst_cpy; byte temp; const byte *src = _src; uintptr_t *ldst_xor, *lsrcdst_cpy; const uintptr_t *lsrc; uintptr_t ltemp; #ifndef BUFHELP_FAST_UNALIGNED_ACCESS const unsigned int longmask = sizeof(uintptr_t) - 1; /* Skip fast processing if alignment of buffers do not match. */ if ((((uintptr_t)src ^ (uintptr_t)dst_xor) | ((uintptr_t)src ^ (uintptr_t)srcdst_cpy)) & longmask) goto do_bytes; /* Handle unaligned head. */ for (; len && ((uintptr_t)src & longmask); len--) { temp = *src++; *dst_xor++ = *srcdst_cpy ^ temp; *srcdst_cpy++ = temp; } #endif ldst_xor = (uintptr_t *)(void *)dst_xor; lsrcdst_cpy = (uintptr_t *)(void *)srcdst_cpy; lsrc = (const uintptr_t *)(const void *)src; for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t)) { ltemp = *lsrc++; *ldst_xor++ = *lsrcdst_cpy ^ ltemp; *lsrcdst_cpy++ = ltemp; } dst_xor = (byte *)ldst_xor; srcdst_cpy = (byte *)lsrcdst_cpy; src = (const byte *)lsrc; #ifndef BUFHELP_FAST_UNALIGNED_ACCESS do_bytes: #endif /* Handle tail. */ for (; len; len--) { temp = *src++; *dst_xor++ = *srcdst_cpy ^ temp; *srcdst_cpy++ = temp; } } + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \ + ((u32)in[2] << 8) | (u32)in[3]; +} + +static inline u32 buf_get_le32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \ + ((u32)in[1] << 8) | (u32)in[0]; +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + byte *out = _buf; + out[0] = val >> 24; + out[1] = val >> 16; + out[2] = val >> 8; + out[3] = val; +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + byte *out = _buf; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + +#ifdef HAVE_U64_TYPEDEF +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \ + ((u64)in[2] << 40) | ((u64)in[3] << 32) | \ + ((u64)in[4] << 24) | ((u64)in[5] << 16) | \ + ((u64)in[6] << 8) | (u64)in[7]; +} + +static inline u64 buf_get_le64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \ + ((u64)in[5] << 40) | ((u64)in[4] << 32) | \ + ((u64)in[3] << 24) | ((u64)in[2] << 16) | \ + ((u64)in[1] << 8) | (u64)in[0]; +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + byte *out = _buf; + out[0] = val >> 56; + out[1] = val >> 48; + out[2] = val >> 40; + out[3] = val >> 32; + out[4] = val >> 24; + out[5] = val >> 16; + out[6] = val >> 8; + out[7] = val; +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + byte *out = _buf; + out[7] = val >> 56; + out[6] = val >> 48; + out[5] = val >> 40; + out[4] = val >> 32; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} +#endif /*HAVE_U64_TYPEDEF*/ + +#else /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + return be_bswap32(*(const u32 *)_buf); +} + +static inline u32 buf_get_le32(const void *_buf) +{ + return le_bswap32(*(const u32 *)_buf); +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + u32 *out = _buf; + *out = be_bswap32(val); +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + u32 *out = _buf; + *out = le_bswap32(val); +} + +#ifdef HAVE_U64_TYPEDEF +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + return be_bswap64(*(const u64 *)_buf); +} + +static inline u64 buf_get_le64(const void *_buf) +{ + return le_bswap64(*(const u64 *)_buf); +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + u64 *out = _buf; + *out = be_bswap64(val); +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + u64 *out = _buf; + *out = le_bswap64(val); +} +#endif /*HAVE_U64_TYPEDEF*/ + +#endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + #endif /*G10_BITHELP_H*/ diff --git a/cipher/camellia.c b/cipher/camellia.c index 038d9118..03510a35 100644 --- a/cipher/camellia.c +++ b/cipher/camellia.c @@ -1,1421 +1,1413 @@ /* camellia.h ver 1.2.0 * * Copyright (C) 2006,2007 * NTT (Nippon Telegraph and Telephone Corporation). * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* * Algorithm Specification * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ #include #include +#include "bufhelp.h" #include "camellia.h" /* u32 must be 32bit word */ typedef unsigned int u32; typedef unsigned char u8; /* key constants */ #define CAMELLIA_SIGMA1L (0xA09E667FL) #define CAMELLIA_SIGMA1R (0x3BCC908BL) #define CAMELLIA_SIGMA2L (0xB67AE858L) #define CAMELLIA_SIGMA2R (0x4CAA73B2L) #define CAMELLIA_SIGMA3L (0xC6EF372FL) #define CAMELLIA_SIGMA3R (0xE94F82BEL) #define CAMELLIA_SIGMA4L (0x54FF53A5L) #define CAMELLIA_SIGMA4R (0xF1D36F1CL) #define CAMELLIA_SIGMA5L (0x10E527FAL) #define CAMELLIA_SIGMA5R (0xDE682D1DL) #define CAMELLIA_SIGMA6L (0xB05688C2L) #define CAMELLIA_SIGMA6R (0xB3E6C1FDL) /* * macros */ #if defined(_MSC_VER) # define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) # define GETU32(p) SWAP(*((u32 *)(p))) # define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} #else /* not MS-VC */ -# define GETU32(pt) \ - (((u32)(pt)[0] << 24) \ - ^ ((u32)(pt)[1] << 16) \ - ^ ((u32)(pt)[2] << 8) \ - ^ ((u32)(pt)[3])) - -# define PUTU32(ct, st) { \ - (ct)[0] = (u8)((st) >> 24); \ - (ct)[1] = (u8)((st) >> 16); \ - (ct)[2] = (u8)((st) >> 8); \ - (ct)[3] = (u8)(st); } +# define GETU32(pt) buf_get_be32(pt) +# define PUTU32(ct, st) buf_put_be32(ct, st) #endif #define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) #define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) /* rotation right shift 1byte */ #define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) /* rotation left shift 1bit */ #define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) /* rotation left shift 1byte */ #define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) #define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ do { \ w0 = ll; \ ll = (ll << bits) + (lr >> (32 - bits)); \ lr = (lr << bits) + (rl >> (32 - bits)); \ rl = (rl << bits) + (rr >> (32 - bits)); \ rr = (rr << bits) + (w0 >> (32 - bits)); \ } while(0) #define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ do { \ w0 = ll; \ w1 = lr; \ ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ } while(0) #define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) #define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) #define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) #define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) #define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ do { \ il = xl ^ kl; \ ir = xr ^ kr; \ t0 = il >> 16; \ t1 = ir >> 16; \ yl = CAMELLIA_SP1110(ir & 0xff) \ ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ ^ CAMELLIA_SP3033(t1 & 0xff) \ ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ ^ CAMELLIA_SP0222(t0 & 0xff) \ ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ ^ CAMELLIA_SP4404(il & 0xff); \ yl ^= yr; \ yr = CAMELLIA_RR8(yr); \ yr ^= yl; \ } while(0) /* * for speed up * */ #define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ do { \ t0 = kll; \ t0 &= ll; \ lr ^= CAMELLIA_RL1(t0); \ t1 = klr; \ t1 |= lr; \ ll ^= t1; \ \ t2 = krr; \ t2 |= rr; \ rl ^= t2; \ t3 = krl; \ t3 &= rl; \ rr ^= CAMELLIA_RL1(t3); \ } while(0) #define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ do { \ yl ^= kl; \ yr ^= kr; \ ir = CAMELLIA_SP1110(xr & 0xff) \ ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ ^ CAMELLIA_SP4404(xl & 0xff); \ ir ^= il; \ il = CAMELLIA_RR8(il); \ il ^= ir; \ yl ^= ir; \ yr ^= il; \ } while(0) static const u32 camellia_sp1110[256] = { 0x70707000,0x82828200,0x2c2c2c00,0xececec00, 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, 0xe4e4e400,0x85858500,0x57575700,0x35353500, 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, 0x45454500,0x19191900,0xa5a5a500,0x21212100, 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, 0x74747400,0x12121200,0x2b2b2b00,0x20202000, 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, 0x34343400,0x7e7e7e00,0x76767600,0x05050500, 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, 0x14141400,0x58585800,0x3a3a3a00,0x61616100, 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, 0x53535300,0x18181800,0xf2f2f200,0x22222200, 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, 0x60606000,0xfcfcfc00,0x69696900,0x50505000, 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, 0xa1a1a100,0x89898900,0x62626200,0x97979700, 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, 0x10101000,0xc4c4c400,0x00000000,0x48484800, 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, 0x87878700,0x5c5c5c00,0x83838300,0x02020200, 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, 0x78787800,0x98989800,0x06060600,0x6a6a6a00, 0xe7e7e700,0x46464600,0x71717100,0xbababa00, 0xd4d4d400,0x25252500,0xababab00,0x42424200, 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, 0x72727200,0x07070700,0xb9b9b900,0x55555500, 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, 0x36363600,0x49494900,0x2a2a2a00,0x68686800, 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, }; static const u32 camellia_sp0222[256] = { 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, 0x00e8e8e8,0x00242424,0x00565656,0x00404040, 0x00e1e1e1,0x00636363,0x00090909,0x00333333, 0x00bfbfbf,0x00989898,0x00979797,0x00858585, 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, 0x00dadada,0x006f6f6f,0x00535353,0x00626262, 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, 0x00bdbdbd,0x00363636,0x00222222,0x00383838, 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, 0x00484848,0x00101010,0x00d1d1d1,0x00515151, 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, 0x00202020,0x00898989,0x00000000,0x00909090, 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, 0x009b9b9b,0x00949494,0x00212121,0x00666666, 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, 0x00030303,0x002d2d2d,0x00dedede,0x00969696, 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, 0x00787878,0x00707070,0x00e3e3e3,0x00494949, 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, 0x00777777,0x00939393,0x00868686,0x00838383, 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, }; static const u32 camellia_sp3033[256] = { 0x38003838,0x41004141,0x16001616,0x76007676, 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, 0x75007575,0x06000606,0x57005757,0xa000a0a0, 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, 0xfd00fdfd,0x66006666,0x58005858,0x96009696, 0x3a003a3a,0x09000909,0x95009595,0x10001010, 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, 0xef00efef,0x26002626,0xe500e5e5,0x61006161, 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, 0x12001212,0x04000404,0x74007474,0x54005454, 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, 0x55005555,0x68006868,0x50005050,0xbe00bebe, 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, 0x70007070,0xff00ffff,0x32003232,0x69006969, 0x08000808,0x62006262,0x00000000,0x24002424, 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, 0x45004545,0x81008181,0x73007373,0x6d006d6d, 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, 0xe600e6e6,0x25002525,0x48004848,0x99009999, 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, 0x7c007c7c,0x77007777,0x56005656,0x05000505, 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, }; static const u32 camellia_sp4404[256] = { 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, 0x14140014,0x3a3a003a,0xdede00de,0x11110011, 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, 0x24240024,0xe8e800e8,0x60600060,0x69690069, 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, 0x10100010,0x00000000,0xa3a300a3,0x75750075, 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, 0x87870087,0x83830083,0xcdcd00cd,0x90900090, 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, 0x81810081,0x6f6f006f,0x13130013,0x63630063, 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, 0x78780078,0x06060006,0xe7e700e7,0x71710071, 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, 0x15150015,0xadad00ad,0x77770077,0x80800080, 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, 0x85850085,0x35350035,0x0c0c000c,0x41410041, 0xefef00ef,0x93930093,0x19190019,0x21210021, 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, 0x12120012,0x20200020,0xb1b100b1,0x99990099, 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, 0x0f0f000f,0x16160016,0x18180018,0x22220022, 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, 0x03030003,0xdada00da,0x3f3f003f,0x94940094, 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, 0x49490049,0x68680068,0x38380038,0xa4a400a4, 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, }; /** * Stuff related to the Camellia key schedule */ #define subl(x) subL[(x)] #define subr(x) subR[(x)] void camellia_setup128(const unsigned char *key, u32 *subkey) { u32 kll, klr, krl, krr; u32 il, ir, t0, t1, w0, w1; u32 kw4l, kw4r, dw, tl, tr; u32 subL[26]; u32 subR[26]; /** * k == kll || klr || krl || krr (|| is concatination) */ kll = GETU32(key ); klr = GETU32(key + 4); krl = GETU32(key + 8); krr = GETU32(key + 12); /** * generate KL dependent subkeys */ subl(0) = kll; subr(0) = klr; subl(1) = krl; subr(1) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(4) = kll; subr(4) = klr; subl(5) = krl; subr(5) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); subl(10) = kll; subr(10) = klr; subl(11) = krl; subr(11) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(13) = krl; subr(13) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); subl(16) = kll; subr(16) = klr; subl(17) = krl; subr(17) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); subl(18) = kll; subr(18) = klr; subl(19) = krl; subr(19) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); subl(22) = kll; subr(22) = klr; subl(23) = krl; subr(23) = krr; /* generate KA */ kll = subl(0); klr = subr(0); krl = subl(1); krr = subr(1); CAMELLIA_F(kll, klr, CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, w0, w1, il, ir, t0, t1); krl ^= w0; krr ^= w1; CAMELLIA_F(krl, krr, CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, kll, klr, il, ir, t0, t1); CAMELLIA_F(kll, klr, CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, krl, krr, il, ir, t0, t1); krl ^= w0; krr ^= w1; CAMELLIA_F(krl, krr, CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, w0, w1, il, ir, t0, t1); kll ^= w0; klr ^= w1; /* generate KA dependent subkeys */ subl(2) = kll; subr(2) = klr; subl(3) = krl; subr(3) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(6) = kll; subr(6) = klr; subl(7) = krl; subr(7) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(8) = kll; subr(8) = klr; subl(9) = krl; subr(9) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(12) = kll; subr(12) = klr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(14) = kll; subr(14) = klr; subl(15) = krl; subr(15) = krr; CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); subl(20) = kll; subr(20) = klr; subl(21) = krl; subr(21) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); subl(24) = kll; subr(24) = klr; subl(25) = krl; subr(25) = krr; /* absorb kw2 to other subkeys */ subl(3) ^= subl(1); subr(3) ^= subr(1); subl(5) ^= subl(1); subr(5) ^= subr(1); subl(7) ^= subl(1); subr(7) ^= subr(1); subl(1) ^= subr(1) & ~subr(9); dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); subl(11) ^= subl(1); subr(11) ^= subr(1); subl(13) ^= subl(1); subr(13) ^= subr(1); subl(15) ^= subl(1); subr(15) ^= subr(1); subl(1) ^= subr(1) & ~subr(17); dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); subl(19) ^= subl(1); subr(19) ^= subr(1); subl(21) ^= subl(1); subr(21) ^= subr(1); subl(23) ^= subl(1); subr(23) ^= subr(1); subl(24) ^= subl(1); subr(24) ^= subr(1); /* absorb kw4 to other subkeys */ kw4l = subl(25); kw4r = subr(25); subl(22) ^= kw4l; subr(22) ^= kw4r; subl(20) ^= kw4l; subr(20) ^= kw4r; subl(18) ^= kw4l; subr(18) ^= kw4r; kw4l ^= kw4r & ~subr(16); dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); subl(14) ^= kw4l; subr(14) ^= kw4r; subl(12) ^= kw4l; subr(12) ^= kw4r; subl(10) ^= kw4l; subr(10) ^= kw4r; kw4l ^= kw4r & ~subr(8); dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); subl(6) ^= kw4l; subr(6) ^= kw4r; subl(4) ^= kw4l; subr(4) ^= kw4r; subl(2) ^= kw4l; subr(2) ^= kw4r; subl(0) ^= kw4l; subr(0) ^= kw4r; /* key XOR is end of F-function */ CamelliaSubkeyL(0) = subl(0) ^ subl(2); CamelliaSubkeyR(0) = subr(0) ^ subr(2); CamelliaSubkeyL(2) = subl(3); CamelliaSubkeyR(2) = subr(3); CamelliaSubkeyL(3) = subl(2) ^ subl(4); CamelliaSubkeyR(3) = subr(2) ^ subr(4); CamelliaSubkeyL(4) = subl(3) ^ subl(5); CamelliaSubkeyR(4) = subr(3) ^ subr(5); CamelliaSubkeyL(5) = subl(4) ^ subl(6); CamelliaSubkeyR(5) = subr(4) ^ subr(6); CamelliaSubkeyL(6) = subl(5) ^ subl(7); CamelliaSubkeyR(6) = subr(5) ^ subr(7); tl = subl(10) ^ (subr(10) & ~subr(8)); dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(7) = subl(6) ^ tl; CamelliaSubkeyR(7) = subr(6) ^ tr; CamelliaSubkeyL(8) = subl(8); CamelliaSubkeyR(8) = subr(8); CamelliaSubkeyL(9) = subl(9); CamelliaSubkeyR(9) = subr(9); tl = subl(7) ^ (subr(7) & ~subr(9)); dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(10) = tl ^ subl(11); CamelliaSubkeyR(10) = tr ^ subr(11); CamelliaSubkeyL(11) = subl(10) ^ subl(12); CamelliaSubkeyR(11) = subr(10) ^ subr(12); CamelliaSubkeyL(12) = subl(11) ^ subl(13); CamelliaSubkeyR(12) = subr(11) ^ subr(13); CamelliaSubkeyL(13) = subl(12) ^ subl(14); CamelliaSubkeyR(13) = subr(12) ^ subr(14); CamelliaSubkeyL(14) = subl(13) ^ subl(15); CamelliaSubkeyR(14) = subr(13) ^ subr(15); tl = subl(18) ^ (subr(18) & ~subr(16)); dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(15) = subl(14) ^ tl; CamelliaSubkeyR(15) = subr(14) ^ tr; CamelliaSubkeyL(16) = subl(16); CamelliaSubkeyR(16) = subr(16); CamelliaSubkeyL(17) = subl(17); CamelliaSubkeyR(17) = subr(17); tl = subl(15) ^ (subr(15) & ~subr(17)); dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(18) = tl ^ subl(19); CamelliaSubkeyR(18) = tr ^ subr(19); CamelliaSubkeyL(19) = subl(18) ^ subl(20); CamelliaSubkeyR(19) = subr(18) ^ subr(20); CamelliaSubkeyL(20) = subl(19) ^ subl(21); CamelliaSubkeyR(20) = subr(19) ^ subr(21); CamelliaSubkeyL(21) = subl(20) ^ subl(22); CamelliaSubkeyR(21) = subr(20) ^ subr(22); CamelliaSubkeyL(22) = subl(21) ^ subl(23); CamelliaSubkeyR(22) = subr(21) ^ subr(23); CamelliaSubkeyL(23) = subl(22); CamelliaSubkeyR(23) = subr(22); CamelliaSubkeyL(24) = subl(24) ^ subl(23); CamelliaSubkeyR(24) = subr(24) ^ subr(23); return; } void camellia_setup256(const unsigned char *key, u32 *subkey) { u32 kll,klr,krl,krr; /* left half of key */ u32 krll,krlr,krrl,krrr; /* right half of key */ u32 il, ir, t0, t1, w0, w1; /* temporary variables */ u32 kw4l, kw4r, dw, tl, tr; u32 subL[34]; u32 subR[34]; /** * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) * (|| is concatination) */ kll = GETU32(key ); klr = GETU32(key + 4); krl = GETU32(key + 8); krr = GETU32(key + 12); krll = GETU32(key + 16); krlr = GETU32(key + 20); krrl = GETU32(key + 24); krrr = GETU32(key + 28); /* generate KL dependent subkeys */ subl(0) = kll; subr(0) = klr; subl(1) = krl; subr(1) = krr; CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); subl(12) = kll; subr(12) = klr; subl(13) = krl; subr(13) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(16) = kll; subr(16) = klr; subl(17) = krl; subr(17) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); subl(22) = kll; subr(22) = klr; subl(23) = krl; subr(23) = krr; CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); subl(30) = kll; subr(30) = klr; subl(31) = krl; subr(31) = krr; /* generate KR dependent subkeys */ CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); subl(4) = krll; subr(4) = krlr; subl(5) = krrl; subr(5) = krrr; CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); subl(8) = krll; subr(8) = krlr; subl(9) = krrl; subr(9) = krrr; CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); subl(18) = krll; subr(18) = krlr; subl(19) = krrl; subr(19) = krrr; CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); subl(26) = krll; subr(26) = krlr; subl(27) = krrl; subr(27) = krrr; CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); /* generate KA */ kll = subl(0) ^ krll; klr = subr(0) ^ krlr; krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; CAMELLIA_F(kll, klr, CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, w0, w1, il, ir, t0, t1); krl ^= w0; krr ^= w1; CAMELLIA_F(krl, krr, CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, kll, klr, il, ir, t0, t1); kll ^= krll; klr ^= krlr; CAMELLIA_F(kll, klr, CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, krl, krr, il, ir, t0, t1); krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; CAMELLIA_F(krl, krr, CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, w0, w1, il, ir, t0, t1); kll ^= w0; klr ^= w1; /* generate KB */ krll ^= kll; krlr ^= klr; krrl ^= krl; krrr ^= krr; CAMELLIA_F(krll, krlr, CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, w0, w1, il, ir, t0, t1); krrl ^= w0; krrr ^= w1; CAMELLIA_F(krrl, krrr, CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, w0, w1, il, ir, t0, t1); krll ^= w0; krlr ^= w1; /* generate KA dependent subkeys */ CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); subl(6) = kll; subr(6) = klr; subl(7) = krl; subr(7) = krr; CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); subl(14) = kll; subr(14) = klr; subl(15) = krl; subr(15) = krr; subl(24) = klr; subr(24) = krl; subl(25) = krr; subr(25) = kll; CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); subl(28) = kll; subr(28) = klr; subl(29) = krl; subr(29) = krr; /* generate KB dependent subkeys */ subl(2) = krll; subr(2) = krlr; subl(3) = krrl; subr(3) = krrr; CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); subl(10) = krll; subr(10) = krlr; subl(11) = krrl; subr(11) = krrr; CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); subl(20) = krll; subr(20) = krlr; subl(21) = krrl; subr(21) = krrr; CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); subl(32) = krll; subr(32) = krlr; subl(33) = krrl; subr(33) = krrr; /* absorb kw2 to other subkeys */ subl(3) ^= subl(1); subr(3) ^= subr(1); subl(5) ^= subl(1); subr(5) ^= subr(1); subl(7) ^= subl(1); subr(7) ^= subr(1); subl(1) ^= subr(1) & ~subr(9); dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); subl(11) ^= subl(1); subr(11) ^= subr(1); subl(13) ^= subl(1); subr(13) ^= subr(1); subl(15) ^= subl(1); subr(15) ^= subr(1); subl(1) ^= subr(1) & ~subr(17); dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); subl(19) ^= subl(1); subr(19) ^= subr(1); subl(21) ^= subl(1); subr(21) ^= subr(1); subl(23) ^= subl(1); subr(23) ^= subr(1); subl(1) ^= subr(1) & ~subr(25); dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); subl(27) ^= subl(1); subr(27) ^= subr(1); subl(29) ^= subl(1); subr(29) ^= subr(1); subl(31) ^= subl(1); subr(31) ^= subr(1); subl(32) ^= subl(1); subr(32) ^= subr(1); /* absorb kw4 to other subkeys */ kw4l = subl(33); kw4r = subr(33); subl(30) ^= kw4l; subr(30) ^= kw4r; subl(28) ^= kw4l; subr(28) ^= kw4r; subl(26) ^= kw4l; subr(26) ^= kw4r; kw4l ^= kw4r & ~subr(24); dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); subl(22) ^= kw4l; subr(22) ^= kw4r; subl(20) ^= kw4l; subr(20) ^= kw4r; subl(18) ^= kw4l; subr(18) ^= kw4r; kw4l ^= kw4r & ~subr(16); dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); subl(14) ^= kw4l; subr(14) ^= kw4r; subl(12) ^= kw4l; subr(12) ^= kw4r; subl(10) ^= kw4l; subr(10) ^= kw4r; kw4l ^= kw4r & ~subr(8); dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); subl(6) ^= kw4l; subr(6) ^= kw4r; subl(4) ^= kw4l; subr(4) ^= kw4r; subl(2) ^= kw4l; subr(2) ^= kw4r; subl(0) ^= kw4l; subr(0) ^= kw4r; /* key XOR is end of F-function */ CamelliaSubkeyL(0) = subl(0) ^ subl(2); CamelliaSubkeyR(0) = subr(0) ^ subr(2); CamelliaSubkeyL(2) = subl(3); CamelliaSubkeyR(2) = subr(3); CamelliaSubkeyL(3) = subl(2) ^ subl(4); CamelliaSubkeyR(3) = subr(2) ^ subr(4); CamelliaSubkeyL(4) = subl(3) ^ subl(5); CamelliaSubkeyR(4) = subr(3) ^ subr(5); CamelliaSubkeyL(5) = subl(4) ^ subl(6); CamelliaSubkeyR(5) = subr(4) ^ subr(6); CamelliaSubkeyL(6) = subl(5) ^ subl(7); CamelliaSubkeyR(6) = subr(5) ^ subr(7); tl = subl(10) ^ (subr(10) & ~subr(8)); dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(7) = subl(6) ^ tl; CamelliaSubkeyR(7) = subr(6) ^ tr; CamelliaSubkeyL(8) = subl(8); CamelliaSubkeyR(8) = subr(8); CamelliaSubkeyL(9) = subl(9); CamelliaSubkeyR(9) = subr(9); tl = subl(7) ^ (subr(7) & ~subr(9)); dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(10) = tl ^ subl(11); CamelliaSubkeyR(10) = tr ^ subr(11); CamelliaSubkeyL(11) = subl(10) ^ subl(12); CamelliaSubkeyR(11) = subr(10) ^ subr(12); CamelliaSubkeyL(12) = subl(11) ^ subl(13); CamelliaSubkeyR(12) = subr(11) ^ subr(13); CamelliaSubkeyL(13) = subl(12) ^ subl(14); CamelliaSubkeyR(13) = subr(12) ^ subr(14); CamelliaSubkeyL(14) = subl(13) ^ subl(15); CamelliaSubkeyR(14) = subr(13) ^ subr(15); tl = subl(18) ^ (subr(18) & ~subr(16)); dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(15) = subl(14) ^ tl; CamelliaSubkeyR(15) = subr(14) ^ tr; CamelliaSubkeyL(16) = subl(16); CamelliaSubkeyR(16) = subr(16); CamelliaSubkeyL(17) = subl(17); CamelliaSubkeyR(17) = subr(17); tl = subl(15) ^ (subr(15) & ~subr(17)); dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(18) = tl ^ subl(19); CamelliaSubkeyR(18) = tr ^ subr(19); CamelliaSubkeyL(19) = subl(18) ^ subl(20); CamelliaSubkeyR(19) = subr(18) ^ subr(20); CamelliaSubkeyL(20) = subl(19) ^ subl(21); CamelliaSubkeyR(20) = subr(19) ^ subr(21); CamelliaSubkeyL(21) = subl(20) ^ subl(22); CamelliaSubkeyR(21) = subr(20) ^ subr(22); CamelliaSubkeyL(22) = subl(21) ^ subl(23); CamelliaSubkeyR(22) = subr(21) ^ subr(23); tl = subl(26) ^ (subr(26) & ~subr(24)); dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(23) = subl(22) ^ tl; CamelliaSubkeyR(23) = subr(22) ^ tr; CamelliaSubkeyL(24) = subl(24); CamelliaSubkeyR(24) = subr(24); CamelliaSubkeyL(25) = subl(25); CamelliaSubkeyR(25) = subr(25); tl = subl(23) ^ (subr(23) & ~subr(25)); dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); CamelliaSubkeyL(26) = tl ^ subl(27); CamelliaSubkeyR(26) = tr ^ subr(27); CamelliaSubkeyL(27) = subl(26) ^ subl(28); CamelliaSubkeyR(27) = subr(26) ^ subr(28); CamelliaSubkeyL(28) = subl(27) ^ subl(29); CamelliaSubkeyR(28) = subr(27) ^ subr(29); CamelliaSubkeyL(29) = subl(28) ^ subl(30); CamelliaSubkeyR(29) = subr(28) ^ subr(30); CamelliaSubkeyL(30) = subl(29) ^ subl(31); CamelliaSubkeyR(30) = subr(29) ^ subr(31); CamelliaSubkeyL(31) = subl(30); CamelliaSubkeyR(31) = subr(30); CamelliaSubkeyL(32) = subl(32) ^ subl(31); CamelliaSubkeyR(32) = subr(32) ^ subr(31); return; } void camellia_setup192(const unsigned char *key, u32 *subkey) { unsigned char kk[32]; u32 krll, krlr, krrl,krrr; memcpy(kk, key, 24); memcpy((unsigned char *)&krll, key+16,4); memcpy((unsigned char *)&krlr, key+20,4); krrl = ~krll; krrr = ~krlr; memcpy(kk+24, (unsigned char *)&krrl, 4); memcpy(kk+28, (unsigned char *)&krrr, 4); camellia_setup256(kk, subkey); return; } #ifndef USE_ARMV6_ASM /** * Stuff related to camellia encryption/decryption * * "io" must be 4byte aligned and big-endian data. */ void camellia_encrypt128(const u32 *subkey, u32 *blocks) { u32 il, ir, t0, t1; u32 io[4]; io[0] = blocks[0]; io[1] = blocks[1]; io[2] = blocks[2]; io[3] = blocks[3]; /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(0); io[1] ^= CamelliaSubkeyR(0); /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(2),CamelliaSubkeyR(2), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(3),CamelliaSubkeyR(3), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(4),CamelliaSubkeyR(4), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(5),CamelliaSubkeyR(5), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(6),CamelliaSubkeyR(6), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(7),CamelliaSubkeyR(7), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(8),CamelliaSubkeyR(8), CamelliaSubkeyL(9),CamelliaSubkeyR(9), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(10),CamelliaSubkeyR(10), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(11),CamelliaSubkeyR(11), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(12),CamelliaSubkeyR(12), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(13),CamelliaSubkeyR(13), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(14),CamelliaSubkeyR(14), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(15),CamelliaSubkeyR(15), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(16),CamelliaSubkeyR(16), CamelliaSubkeyL(17),CamelliaSubkeyR(17), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(18),CamelliaSubkeyR(18), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(19),CamelliaSubkeyR(19), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(20),CamelliaSubkeyR(20), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(21),CamelliaSubkeyR(21), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(22),CamelliaSubkeyR(22), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(23),CamelliaSubkeyR(23), io[0],io[1],il,ir,t0,t1); /* post whitening but kw4 */ io[2] ^= CamelliaSubkeyL(24); io[3] ^= CamelliaSubkeyR(24); t0 = io[0]; t1 = io[1]; io[0] = io[2]; io[1] = io[3]; io[2] = t0; io[3] = t1; blocks[0] = io[0]; blocks[1] = io[1]; blocks[2] = io[2]; blocks[3] = io[3]; return; } void camellia_decrypt128(const u32 *subkey, u32 *blocks) { u32 il,ir,t0,t1; /* temporary valiables */ u32 io[4]; io[0] = blocks[0]; io[1] = blocks[1]; io[2] = blocks[2]; io[3] = blocks[3]; /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(24); io[1] ^= CamelliaSubkeyR(24); /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(23),CamelliaSubkeyR(23), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(22),CamelliaSubkeyR(22), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(21),CamelliaSubkeyR(21), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(20),CamelliaSubkeyR(20), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(19),CamelliaSubkeyR(19), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(18),CamelliaSubkeyR(18), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(17),CamelliaSubkeyR(17), CamelliaSubkeyL(16),CamelliaSubkeyR(16), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(15),CamelliaSubkeyR(15), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(14),CamelliaSubkeyR(14), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(13),CamelliaSubkeyR(13), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(12),CamelliaSubkeyR(12), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(11),CamelliaSubkeyR(11), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(10),CamelliaSubkeyR(10), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(9),CamelliaSubkeyR(9), CamelliaSubkeyL(8),CamelliaSubkeyR(8), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(7),CamelliaSubkeyR(7), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(6),CamelliaSubkeyR(6), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(5),CamelliaSubkeyR(5), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(4),CamelliaSubkeyR(4), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(3),CamelliaSubkeyR(3), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(2),CamelliaSubkeyR(2), io[0],io[1],il,ir,t0,t1); /* post whitening but kw4 */ io[2] ^= CamelliaSubkeyL(0); io[3] ^= CamelliaSubkeyR(0); t0 = io[0]; t1 = io[1]; io[0] = io[2]; io[1] = io[3]; io[2] = t0; io[3] = t1; blocks[0] = io[0]; blocks[1] = io[1]; blocks[2] = io[2]; blocks[3] = io[3]; return; } /** * stuff for 192 and 256bit encryption/decryption */ void camellia_encrypt256(const u32 *subkey, u32 *blocks) { u32 il,ir,t0,t1; /* temporary valiables */ u32 io[4]; io[0] = blocks[0]; io[1] = blocks[1]; io[2] = blocks[2]; io[3] = blocks[3]; /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(0); io[1] ^= CamelliaSubkeyR(0); /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(2),CamelliaSubkeyR(2), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(3),CamelliaSubkeyR(3), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(4),CamelliaSubkeyR(4), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(5),CamelliaSubkeyR(5), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(6),CamelliaSubkeyR(6), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(7),CamelliaSubkeyR(7), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(8),CamelliaSubkeyR(8), CamelliaSubkeyL(9),CamelliaSubkeyR(9), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(10),CamelliaSubkeyR(10), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(11),CamelliaSubkeyR(11), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(12),CamelliaSubkeyR(12), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(13),CamelliaSubkeyR(13), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(14),CamelliaSubkeyR(14), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(15),CamelliaSubkeyR(15), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(16),CamelliaSubkeyR(16), CamelliaSubkeyL(17),CamelliaSubkeyR(17), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(18),CamelliaSubkeyR(18), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(19),CamelliaSubkeyR(19), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(20),CamelliaSubkeyR(20), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(21),CamelliaSubkeyR(21), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(22),CamelliaSubkeyR(22), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(23),CamelliaSubkeyR(23), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(24),CamelliaSubkeyR(24), CamelliaSubkeyL(25),CamelliaSubkeyR(25), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(26),CamelliaSubkeyR(26), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(27),CamelliaSubkeyR(27), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(28),CamelliaSubkeyR(28), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(29),CamelliaSubkeyR(29), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(30),CamelliaSubkeyR(30), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(31),CamelliaSubkeyR(31), io[0],io[1],il,ir,t0,t1); /* post whitening but kw4 */ io[2] ^= CamelliaSubkeyL(32); io[3] ^= CamelliaSubkeyR(32); t0 = io[0]; t1 = io[1]; io[0] = io[2]; io[1] = io[3]; io[2] = t0; io[3] = t1; blocks[0] = io[0]; blocks[1] = io[1]; blocks[2] = io[2]; blocks[3] = io[3]; return; } void camellia_decrypt256(const u32 *subkey, u32 *blocks) { u32 il,ir,t0,t1; /* temporary valiables */ u32 io[4]; io[0] = blocks[0]; io[1] = blocks[1]; io[2] = blocks[2]; io[3] = blocks[3]; /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(32); io[1] ^= CamelliaSubkeyR(32); /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(31),CamelliaSubkeyR(31), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(30),CamelliaSubkeyR(30), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(29),CamelliaSubkeyR(29), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(28),CamelliaSubkeyR(28), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(27),CamelliaSubkeyR(27), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(26),CamelliaSubkeyR(26), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(25),CamelliaSubkeyR(25), CamelliaSubkeyL(24),CamelliaSubkeyR(24), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(23),CamelliaSubkeyR(23), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(22),CamelliaSubkeyR(22), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(21),CamelliaSubkeyR(21), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(20),CamelliaSubkeyR(20), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(19),CamelliaSubkeyR(19), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(18),CamelliaSubkeyR(18), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(17),CamelliaSubkeyR(17), CamelliaSubkeyL(16),CamelliaSubkeyR(16), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(15),CamelliaSubkeyR(15), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(14),CamelliaSubkeyR(14), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(13),CamelliaSubkeyR(13), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(12),CamelliaSubkeyR(12), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(11),CamelliaSubkeyR(11), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(10),CamelliaSubkeyR(10), io[0],io[1],il,ir,t0,t1); CAMELLIA_FLS(io[0],io[1],io[2],io[3], CamelliaSubkeyL(9),CamelliaSubkeyR(9), CamelliaSubkeyL(8),CamelliaSubkeyR(8), t0,t1,il,ir); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(7),CamelliaSubkeyR(7), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(6),CamelliaSubkeyR(6), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(5),CamelliaSubkeyR(5), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(4),CamelliaSubkeyR(4), io[0],io[1],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(3),CamelliaSubkeyR(3), io[2],io[3],il,ir,t0,t1); CAMELLIA_ROUNDSM(io[2],io[3], CamelliaSubkeyL(2),CamelliaSubkeyR(2), io[0],io[1],il,ir,t0,t1); /* post whitening but kw4 */ io[2] ^= CamelliaSubkeyL(0); io[3] ^= CamelliaSubkeyR(0); t0 = io[0]; t1 = io[1]; io[0] = io[2]; io[1] = io[3]; io[2] = t0; io[3] = t1; blocks[0] = io[0]; blocks[1] = io[1]; blocks[2] = io[2]; blocks[3] = io[3]; return; } #endif /*!USE_ARMV6_ASM*/ /*** * * API for compatibility */ void Camellia_Ekeygen(const int keyBitLength, const unsigned char *rawKey, KEY_TABLE_TYPE keyTable) { switch(keyBitLength) { case 128: camellia_setup128(rawKey, keyTable); break; case 192: camellia_setup192(rawKey, keyTable); break; case 256: camellia_setup256(rawKey, keyTable); break; default: break; } } #ifndef USE_ARMV6_ASM void Camellia_EncryptBlock(const int keyBitLength, const unsigned char *plaintext, const KEY_TABLE_TYPE keyTable, unsigned char *ciphertext) { u32 tmp[4]; tmp[0] = GETU32(plaintext); tmp[1] = GETU32(plaintext + 4); tmp[2] = GETU32(plaintext + 8); tmp[3] = GETU32(plaintext + 12); switch (keyBitLength) { case 128: camellia_encrypt128(keyTable, tmp); break; case 192: /* fall through */ case 256: camellia_encrypt256(keyTable, tmp); break; default: break; } PUTU32(ciphertext, tmp[0]); PUTU32(ciphertext + 4, tmp[1]); PUTU32(ciphertext + 8, tmp[2]); PUTU32(ciphertext + 12, tmp[3]); } void Camellia_DecryptBlock(const int keyBitLength, const unsigned char *ciphertext, const KEY_TABLE_TYPE keyTable, unsigned char *plaintext) { u32 tmp[4]; tmp[0] = GETU32(ciphertext); tmp[1] = GETU32(ciphertext + 4); tmp[2] = GETU32(ciphertext + 8); tmp[3] = GETU32(ciphertext + 12); switch (keyBitLength) { case 128: camellia_decrypt128(keyTable, tmp); break; case 192: /* fall through */ case 256: camellia_decrypt256(keyTable, tmp); break; default: break; } PUTU32(plaintext, tmp[0]); PUTU32(plaintext + 4, tmp[1]); PUTU32(plaintext + 8, tmp[2]); PUTU32(plaintext + 12, tmp[3]); } #endif /*!USE_ARMV6_ASM*/ diff --git a/cipher/cast5.c b/cipher/cast5.c index 0cd59539..ae6b509a 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -1,1013 +1,988 @@ /* cast5.c - CAST5 cipher (RFC2144) * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* Test vectors: * * 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A * plaintext = 01 23 45 67 89 AB CD EF * ciphertext = 23 8B 4F E5 84 7E 44 B2 * * 80-bit key = 01 23 45 67 12 34 56 78 23 45 * = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00 * plaintext = 01 23 45 67 89 AB CD EF * ciphertext = EB 6A 71 1A 2C 02 27 1B * * 40-bit key = 01 23 45 67 12 * = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00 * plaintext = 01 23 45 67 89 AB CD EF * ciphertext = 7A C8 16 D1 6E 9B 30 2E */ #include #include #include #include #include "g10lib.h" #include "types.h" #include "cipher.h" +#include "bithelp.h" #include "bufhelp.h" #include "cipher-selftest.h" /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) # define USE_AMD64_ASM 1 #endif /* USE_ARMV6_ASM indicates whether to use ARMv6 assembly code. */ #undef USE_ARMV6_ASM #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) # ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS # define USE_ARMV6_ASM 1 # endif #endif #define CAST5_BLOCKSIZE 8 typedef struct { u32 Km[16]; byte Kr[16]; #ifdef USE_ARMV6_ASM u32 Kr_arm_enc[16 / sizeof(u32)]; u32 Kr_arm_dec[16 / sizeof(u32)]; #endif } CAST5_context; static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen); static unsigned int encrypt_block (void *c, byte *outbuf, const byte *inbuf); static unsigned int decrypt_block (void *c, byte *outbuf, const byte *inbuf); #define s1 _gcry_cast5_s1to4[0] #define s2 _gcry_cast5_s1to4[1] #define s3 _gcry_cast5_s1to4[2] #define s4 _gcry_cast5_s1to4[3] const u32 _gcry_cast5_s1to4[4][256] = { { 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d, 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935, 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe, 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291, 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511, 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324, 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d, 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d, 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9, 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e, 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf }, { 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb, 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359, 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34, 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860, 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b, 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13, 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6, 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d, 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6, 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa, 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1 }, { 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e, 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b, 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82, 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176, 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341, 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f, 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b, 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536, 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69, 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d, 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783 }, { 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15, 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5, 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d, 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003, 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24, 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df, 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7, 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2, 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef, 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04, 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2 } }; static const u32 s5[256] = { 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff, 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7, 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774, 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910, 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049, 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be, 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4, 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5, 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801, 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20, 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4 }; static const u32 s6[256] = { 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367, 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3, 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9, 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc, 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f, 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f, 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13, 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891, 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084, 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5, 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f }; static const u32 s7[256] = { 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43, 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516, 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756, 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688, 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7, 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a, 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962, 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c, 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be, 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914, 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3 }; static const u32 s8[256] = { 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd, 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862, 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e, 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42, 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225, 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054, 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c, 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101, 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a, 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c, 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e }; #ifdef USE_AMD64_ASM /* Assembly implementations of CAST5. */ extern void _gcry_cast5_amd64_encrypt_block(CAST5_context *c, byte *outbuf, const byte *inbuf); extern void _gcry_cast5_amd64_decrypt_block(CAST5_context *c, byte *outbuf, const byte *inbuf); /* These assembly implementations process four blocks in parallel. */ extern void _gcry_cast5_amd64_ctr_enc(CAST5_context *ctx, byte *out, const byte *in, byte *ctr); extern void _gcry_cast5_amd64_cbc_dec(CAST5_context *ctx, byte *out, const byte *in, byte *iv); extern void _gcry_cast5_amd64_cfb_dec(CAST5_context *ctx, byte *out, const byte *in, byte *iv); static void do_encrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf) { _gcry_cast5_amd64_encrypt_block (context, outbuf, inbuf); } static void do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf) { _gcry_cast5_amd64_decrypt_block (context, outbuf, inbuf); } static unsigned int encrypt_block (void *context , byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_encrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (2*8); } static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; _gcry_cast5_amd64_decrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (2*8); } #elif defined(USE_ARMV6_ASM) /* ARMv6 assembly implementations of CAST5. */ extern void _gcry_cast5_armv6_encrypt_block(CAST5_context *c, byte *outbuf, const byte *inbuf); extern void _gcry_cast5_armv6_decrypt_block(CAST5_context *c, byte *outbuf, const byte *inbuf); /* These assembly implementations process two blocks in parallel. */ extern void _gcry_cast5_armv6_ctr_enc(CAST5_context *ctx, byte *out, const byte *in, byte *ctr); extern void _gcry_cast5_armv6_cbc_dec(CAST5_context *ctx, byte *out, const byte *in, byte *iv); extern void _gcry_cast5_armv6_cfb_dec(CAST5_context *ctx, byte *out, const byte *in, byte *iv); static void do_encrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf) { _gcry_cast5_armv6_encrypt_block (context, outbuf, inbuf); } static void do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf) { _gcry_cast5_armv6_decrypt_block (context, outbuf, inbuf); } static unsigned int encrypt_block (void *context , byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_encrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (10*4); } static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_decrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (10*4); } #else /*USE_ARMV6_ASM*/ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol(int n, u32 x) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n) - :"cc"); - return x; -} -#else -#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - -#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \ +#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol(I,(r))), \ (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) ) -#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \ +#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol(I,(r))), \ (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) ) -#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \ +#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol(I,(r))), \ (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) ) static void do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf ) { u32 l, r, t; u32 I; /* used by the Fx macros */ u32 *Km; byte *Kr; Km = c->Km; Kr = c->Kr; /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) */ - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = buf_get_be32(inbuf + 0); + r = buf_get_be32(inbuf + 4); /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: * Li = Ri-1; * Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2 * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1. * Rounds 2, 5, 8, 11, and 14 use f function Type 2. * Rounds 3, 6, 9, 12, and 15 use f function Type 3. */ t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and * concatenate to form the ciphertext.) */ - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + buf_put_be32(outbuf + 0, r); + buf_put_be32(outbuf + 4, l); } static unsigned int encrypt_block (void *context , byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_encrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (20+4*sizeof(void*)); } static void do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf ) { u32 l, r, t; u32 I; u32 *Km; byte *Kr; Km = c->Km; Kr = c->Kr; - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = buf_get_be32(inbuf + 0); + r = buf_get_be32(inbuf + 4); t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]); t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]); t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]); t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]); t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]); t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]); t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]); t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]); t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]); t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]); t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]); t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]); t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]); t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]); t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]); - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + buf_put_be32(outbuf + 0, r); + buf_put_be32(outbuf + 4, l); } static unsigned int decrypt_block (void *context, byte *outbuf, const byte *inbuf) { CAST5_context *c = (CAST5_context *) context; do_decrypt_block (c, outbuf, inbuf); return /*burn_stack*/ (20+4*sizeof(void*)); } #endif /*!USE_ARMV6_ASM*/ /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size CAST5_BLOCKSIZE. */ void _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[CAST5_BLOCKSIZE]; int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE; int i; #ifdef USE_AMD64_ASM { if (nblocks >= 4) burn_stack_depth += 8 * sizeof(void*); /* Process data in 4 block chunks. */ while (nblocks >= 4) { _gcry_cast5_amd64_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 4; outbuf += 4 * CAST5_BLOCKSIZE; inbuf += 4 * CAST5_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #elif defined(USE_ARMV6_ASM) { /* Process data in 2 block chunks. */ while (nblocks >= 2) { _gcry_cast5_armv6_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 2; outbuf += 2 * CAST5_BLOCKSIZE; inbuf += 2 * CAST5_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ do_encrypt_block(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ buf_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE); outbuf += CAST5_BLOCKSIZE; inbuf += CAST5_BLOCKSIZE; /* Increment the counter. */ for (i = CAST5_BLOCKSIZE; i > 0; i--) { ctr[i-1]++; if (ctr[i-1]) break; } } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[CAST5_BLOCKSIZE]; int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE; #ifdef USE_AMD64_ASM { if (nblocks >= 4) burn_stack_depth += 8 * sizeof(void*); /* Process data in 4 block chunks. */ while (nblocks >= 4) { _gcry_cast5_amd64_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 4; outbuf += 4 * CAST5_BLOCKSIZE; inbuf += 4 * CAST5_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #elif defined(USE_ARMV6_ASM) { /* Process data in 2 block chunks. */ while (nblocks >= 2) { _gcry_cast5_armv6_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 2; outbuf += 2 * CAST5_BLOCKSIZE; inbuf += 2 * CAST5_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* We need to save INBUF away because it may be identical to OUTBUF. */ memcpy(savebuf, inbuf, CAST5_BLOCKSIZE); do_decrypt_block (ctx, outbuf, inbuf); buf_xor(outbuf, outbuf, iv, CAST5_BLOCKSIZE); memcpy(iv, savebuf, CAST5_BLOCKSIZE); inbuf += CAST5_BLOCKSIZE; outbuf += CAST5_BLOCKSIZE; } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE; #ifdef USE_AMD64_ASM { if (nblocks >= 4) burn_stack_depth += 8 * sizeof(void*); /* Process data in 4 block chunks. */ while (nblocks >= 4) { _gcry_cast5_amd64_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 4; outbuf += 4 * CAST5_BLOCKSIZE; inbuf += 4 * CAST5_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #elif defined(USE_ARMV6_ASM) { /* Process data in 2 block chunks. */ while (nblocks >= 2) { _gcry_cast5_armv6_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 2; outbuf += 2 * CAST5_BLOCKSIZE; inbuf += 2 * CAST5_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { do_encrypt_block(ctx, iv, iv); buf_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE); outbuf += CAST5_BLOCKSIZE; inbuf += CAST5_BLOCKSIZE; } _gcry_burn_stack(burn_stack_depth); } /* Run the self-tests for CAST5-CTR, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char * selftest_ctr (void) { const int nblocks = 4+1; const int blocksize = CAST5_BLOCKSIZE; const int context_size = sizeof(CAST5_context); return _gcry_selftest_helper_ctr("CAST5", &cast_setkey, &encrypt_block, &_gcry_cast5_ctr_enc, nblocks, blocksize, context_size); } /* Run the self-tests for CAST5-CBC, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cbc (void) { const int nblocks = 4+2; const int blocksize = CAST5_BLOCKSIZE; const int context_size = sizeof(CAST5_context); return _gcry_selftest_helper_cbc("CAST5", &cast_setkey, &encrypt_block, &_gcry_cast5_cbc_dec, nblocks, blocksize, context_size); } /* Run the self-tests for CAST5-CFB, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cfb (void) { const int nblocks = 4+2; const int blocksize = CAST5_BLOCKSIZE; const int context_size = sizeof(CAST5_context); return _gcry_selftest_helper_cfb("CAST5", &cast_setkey, &encrypt_block, &_gcry_cast5_cfb_dec, nblocks, blocksize, context_size); } static const char* selftest(void) { CAST5_context c; byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; byte buffer[8]; const char *r; cast_setkey( &c, key, 16 ); encrypt_block( &c, buffer, plain ); if( memcmp( buffer, cipher, 8 ) ) return "1"; decrypt_block( &c, buffer, buffer ); if( memcmp( buffer, plain, 8 ) ) return "2"; #if 0 /* full maintenance test */ { int i; byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78, 0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A }; byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6, 0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 }; byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71, 0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E }; for(i=0; i < 1000000; i++ ) { cast_setkey( &c, b0, 16 ); encrypt_block( &c, a0, a0 ); encrypt_block( &c, a0+8, a0+8 ); cast_setkey( &c, a0, 16 ); encrypt_block( &c, b0, b0 ); encrypt_block( &c, b0+8, b0+8 ); } if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) ) return "3"; } #endif if ( (r = selftest_cbc ()) ) return r; if ( (r = selftest_cfb ()) ) return r; if ( (r = selftest_ctr ()) ) return r; return NULL; } static void key_schedule( u32 *x, u32 *z, u32 *k ) { #define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff) #define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff) z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)]; k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)]; k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)]; k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)]; x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)]; k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)]; k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)]; k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)]; z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)]; z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)]; z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)]; z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)]; k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)]; k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)]; k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)]; k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)]; x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)]; x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)]; x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)]; x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)]; k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)]; k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)]; k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)]; k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)]; #undef xi #undef zi } static gcry_err_code_t do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) { static int initialized; static const char* selftest_failed; int i; u32 x[4]; u32 z[4]; u32 k[16]; if( !initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) log_error ("CAST5 selftest failed (%s).\n", selftest_failed ); } if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; if( keylen != 16 ) return GPG_ERR_INV_KEYLEN; - x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3]; - x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7]; - x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11]; - x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]; + x[0] = buf_get_be32(key + 0); + x[1] = buf_get_be32(key + 4); + x[2] = buf_get_be32(key + 8); + x[3] = buf_get_be32(key + 12); key_schedule( x, z, k ); for(i=0; i < 16; i++ ) c->Km[i] = k[i]; key_schedule( x, z, k ); for(i=0; i < 16; i++ ) c->Kr[i] = k[i] & 0x1f; #ifdef USE_ARMV6_ASM for (i = 0; i < 4; i++) { byte Kr_arm[4]; /* Convert rotate left to rotate right and add shift left * by 2. */ Kr_arm[0] = ((32 - c->Kr[4 * i + 0]) - 2) & 0x1f; Kr_arm[1] = ((32 - c->Kr[4 * i + 1]) - 2) & 0x1f; Kr_arm[2] = ((32 - c->Kr[4 * i + 2]) - 2) & 0x1f; Kr_arm[3] = ((32 - c->Kr[4 * i + 3]) - 2) & 0x1f; /* Endian friendly store. */ c->Kr_arm_enc[i] = Kr_arm[0] | (Kr_arm[1] << 8) | (Kr_arm[2] << 16) | (Kr_arm[3] << 24); c->Kr_arm_dec[i] = Kr_arm[3] | (Kr_arm[2] << 8) | (Kr_arm[1] << 16) | (Kr_arm[0] << 24); wipememory(Kr_arm, sizeof(Kr_arm)); } #endif memset(&x,0, sizeof x); memset(&z,0, sizeof z); memset(&k,0, sizeof k); #undef xi #undef zi return GPG_ERR_NO_ERROR; } static gcry_err_code_t cast_setkey (void *context, const byte *key, unsigned keylen ) { CAST5_context *c = (CAST5_context *) context; gcry_err_code_t rc = do_cast_setkey (c, key, keylen); _gcry_burn_stack (96+7*sizeof(void*)); return rc; } gcry_cipher_spec_t _gcry_cipher_spec_cast5 = { "CAST5", NULL, NULL, CAST5_BLOCKSIZE, 128, sizeof (CAST5_context), cast_setkey, encrypt_block, decrypt_block }; diff --git a/cipher/des.c b/cipher/des.c index 7db9e5d8..f1550d1d 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -1,1196 +1,1195 @@ /* des.c - DES and Triple-DES encryption/decryption Algorithm * Copyright (C) 1998, 1999, 2001, 2002, 2003, * 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * For a description of triple encryption, see: * Bruce Schneier: Applied Cryptography. Second Edition. * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. * This implementation is according to the definition of DES in FIPS * PUB 46-2 from December 1993. */ /* * Written by Michael Roth , September 1998 */ /* * U S A G E * =========== * * For DES or Triple-DES encryption/decryption you must initialize a proper * encryption context with a key. * * A DES key is 64bit wide but only 56bits of the key are used. The remaining * bits are parity bits and they will _not_ checked in this implementation, but * simply ignored. * * For Triple-DES you could use either two 64bit keys or three 64bit keys. * The parity bits will _not_ checked, too. * * After initializing a context with a key you could use this context to * encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode. * * (In the examples below the slashes at the beginning and ending of comments * are omited.) * * DES Example * ----------- * unsigned char key[8]; * unsigned char plaintext[8]; * unsigned char ciphertext[8]; * unsigned char recoverd[8]; * des_ctx context; * * * Fill 'key' and 'plaintext' with some data * * .... * * * Set up the DES encryption context * * des_setkey(context, key); * * * Encrypt the plaintext * * des_ecb_encrypt(context, plaintext, ciphertext); * * * To recover the orginal plaintext from ciphertext use: * * des_ecb_decrypt(context, ciphertext, recoverd); * * * Triple-DES Example * ------------------ * unsigned char key1[8]; * unsigned char key2[8]; * unsigned char key3[8]; * unsigned char plaintext[8]; * unsigned char ciphertext[8]; * unsigned char recoverd[8]; * tripledes_ctx context; * * * If you would like to use two 64bit keys, fill 'key1' and'key2' * then setup the encryption context: * * tripledes_set2keys(context, key1, key2); * * * To use three 64bit keys with Triple-DES use: * * tripledes_set3keys(context, key1, key2, key3); * * * Encrypting plaintext with Triple-DES * * tripledes_ecb_encrypt(context, plaintext, ciphertext); * * * Decrypting ciphertext to recover the plaintext with Triple-DES * * tripledes_ecb_decrypt(context, ciphertext, recoverd); * * * Selftest * -------- * char *error_msg; * * * To perform a selftest of this DES/Triple-DES implementation use the * function selftest(). It will return an error string if there are * some problems with this library. * * * if ( (error_msg = selftest()) ) * { * fprintf(stderr, "An error in the DES/Triple-DES implementation occurred: %s\n", error_msg); * abort(); * } */ #include #include #include /* memcpy, memcmp */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" +#include "bufhelp.h" #if defined(__GNUC__) && defined(__GNU_LIBRARY__) #define working_memcmp memcmp #else /* * According to the SunOS man page, memcmp returns indeterminate sign * depending on whether characters are signed or not. */ static int working_memcmp( const char *a, const char *b, size_t n ) { for( ; n; n--, a++, b++ ) if( *a != *b ) return (int)(*(byte*)a) - (int)(*(byte*)b); return 0; } #endif /* * Encryption/Decryption context of DES */ typedef struct _des_ctx { u32 encrypt_subkeys[32]; u32 decrypt_subkeys[32]; } des_ctx[1]; /* * Encryption/Decryption context of Triple-DES */ typedef struct _tripledes_ctx { u32 encrypt_subkeys[96]; u32 decrypt_subkeys[96]; struct { int no_weak_key; } flags; } tripledes_ctx[1]; static void des_key_schedule (const byte *, u32 *); static int des_setkey (struct _des_ctx *, const byte *); static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int); static int tripledes_set2keys (struct _tripledes_ctx *, const byte *, const byte *); static int tripledes_set3keys (struct _tripledes_ctx *, const byte *, const byte *, const byte *); static int tripledes_ecb_crypt (struct _tripledes_ctx *, const byte *, byte *, int); static int is_weak_key ( const byte *key ); static const char *selftest (void); static int initialized; /* * The s-box values are permuted according to the 'primitive function P' * and are rotated one bit to the left. */ static u32 sbox1[64] = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; static u32 sbox2[64] = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; static u32 sbox3[64] = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; static u32 sbox4[64] = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; static u32 sbox5[64] = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; static u32 sbox6[64] = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; static u32 sbox7[64] = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; static u32 sbox8[64] = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; /* * These two tables are part of the 'permuted choice 1' function. * In this implementation several speed improvements are done. */ static u32 leftkey_swap[16] = { 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, 0x01010000, 0x01010001, 0x01010100, 0x01010101 }; static u32 rightkey_swap[16] = { 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, 0x01010101, }; /* * Numbers of left shifts per round for encryption subkeys. * To calculate the decryption subkeys we just reverse the * ordering of the calculated encryption subkeys. So their * is no need for a decryption rotate tab. */ static byte encrypt_rotate_tab[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; /* * Table with weak DES keys sorted in ascending order. * In DES their are 64 known keys which are weak. They are weak * because they produce only one, two or four different * subkeys in the subkey scheduling process. * The keys in this table have all their parity bits cleared. */ static byte weak_keys[64][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*w*/ { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e }, { 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe }, { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, /*sw*/ { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 }, { 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 }, { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, /*sw*/ { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe }, { 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e }, { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, /*sw*/ { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 }, { 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 }, { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e }, { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, /*sw*/ { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe }, { 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 }, { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, /*w*/ { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 }, { 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe }, { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, /*sw*/ { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e }, { 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 }, { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, /*sw*/ { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 }, { 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 }, { 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 }, /*sw*/ { 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe }, { 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e }, /*sw*/ { 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 }, { 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 }, /*w*/ { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe }, { 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 }, { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, /*sw*/ { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 }, { 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 }, { 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 }, /*sw*/ { 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe }, { 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e }, /*sw*/ { 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 }, { 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 }, /*sw*/ { 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e }, { 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe } /*w*/ }; static unsigned char weak_keys_chksum[20] = { 0xD0, 0xCF, 0x07, 0x38, 0x93, 0x70, 0x8A, 0x83, 0x7D, 0xD7, 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 }; /* * Macro to swap bits across two words. */ #define DO_PERMUTATION(a, temp, b, offset, mask) \ temp = ((a>>offset) ^ b) & mask; \ b ^= temp; \ a ^= temp<> 31); \ temp = (left ^ right) & 0xaaaaaaaa; \ right ^= temp; \ left ^= temp; \ left = (left << 1) | (left >> 31); /* * The 'inverse initial permutation'. */ #define FINAL_PERMUTATION(left, temp, right) \ left = (left << 31) | (left >> 1); \ temp = (left ^ right) & 0xaaaaaaaa; \ left ^= temp; \ right ^= temp; \ right = (right << 31) | (right >> 1); \ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \ DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) /* * A full DES round including 'expansion function', 'sbox substitution' * and 'primitive function P' but without swapping the left and right word. * Please note: The data in 'from' and 'to' is already rotated one bit to * the left, done in the initial permutation. */ #define DES_ROUND(from, to, work, subkey) \ work = from ^ *subkey++; \ to ^= sbox8[ work & 0x3f ]; \ to ^= sbox6[ (work>>8) & 0x3f ]; \ to ^= sbox4[ (work>>16) & 0x3f ]; \ to ^= sbox2[ (work>>24) & 0x3f ]; \ work = ((from << 28) | (from >> 4)) ^ *subkey++; \ to ^= sbox7[ work & 0x3f ]; \ to ^= sbox5[ (work>>8) & 0x3f ]; \ to ^= sbox3[ (work>>16) & 0x3f ]; \ to ^= sbox1[ (work>>24) & 0x3f ]; /* * Macros to convert 8 bytes from/to 32bit words. */ #define READ_64BIT_DATA(data, left, right) \ - left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \ - right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; + left = buf_get_be32(data + 0); \ + right = buf_get_be32(data + 4); #define WRITE_64BIT_DATA(data, left, right) \ - data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \ - data[2] = (left >> 8) &0xff; data[3] = left &0xff; \ - data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \ - data[6] = (right >> 8) &0xff; data[7] = right &0xff; + buf_put_be32(data + 0, left); \ + buf_put_be32(data + 4, right); /* * Handy macros for encryption and decryption of data */ #define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0) #define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1) #define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,0) #define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx,from,to,1) /* * des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for * 16 encryption rounds. * To calculate subkeys for decryption the caller * have to reorder the generated subkeys. * * rawkey: 8 Bytes of key data * subkey: Array of at least 32 u32s. Will be filled * with calculated subkeys. * */ static void des_key_schedule (const byte * rawkey, u32 * subkey) { u32 left, right, work; int round; READ_64BIT_DATA (rawkey, left, right) DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f) DO_PERMUTATION (right, work, left, 0, 0x10101010) left = ((leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2) | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf]) | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6) | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4)); left &= 0x0fffffff; right = ((rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2) | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf]) | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6) | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4)); right &= 0x0fffffff; for (round = 0; round < 16; ++round) { left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff; *subkey++ = (((left << 4) & 0x24000000) | ((left << 28) & 0x10000000) | ((left << 14) & 0x08000000) | ((left << 18) & 0x02080000) | ((left << 6) & 0x01000000) | ((left << 9) & 0x00200000) | ((left >> 1) & 0x00100000) | ((left << 10) & 0x00040000) | ((left << 2) & 0x00020000) | ((left >> 10) & 0x00010000) | ((right >> 13) & 0x00002000) | ((right >> 4) & 0x00001000) | ((right << 6) & 0x00000800) | ((right >> 1) & 0x00000400) | ((right >> 14) & 0x00000200) | (right & 0x00000100) | ((right >> 5) & 0x00000020) | ((right >> 10) & 0x00000010) | ((right >> 3) & 0x00000008) | ((right >> 18) & 0x00000004) | ((right >> 26) & 0x00000002) | ((right >> 24) & 0x00000001)); *subkey++ = (((left << 15) & 0x20000000) | ((left << 17) & 0x10000000) | ((left << 10) & 0x08000000) | ((left << 22) & 0x04000000) | ((left >> 2) & 0x02000000) | ((left << 1) & 0x01000000) | ((left << 16) & 0x00200000) | ((left << 11) & 0x00100000) | ((left << 3) & 0x00080000) | ((left >> 6) & 0x00040000) | ((left << 15) & 0x00020000) | ((left >> 4) & 0x00010000) | ((right >> 2) & 0x00002000) | ((right << 8) & 0x00001000) | ((right >> 14) & 0x00000808) | ((right >> 9) & 0x00000400) | ((right) & 0x00000200) | ((right << 7) & 0x00000100) | ((right >> 7) & 0x00000020) | ((right >> 3) & 0x00000011) | ((right << 2) & 0x00000004) | ((right >> 21) & 0x00000002)); } } /* * Fill a DES context with subkeys calculated from a 64bit key. * Does not check parity bits, but simply ignore them. * Does not check for weak keys. */ static int des_setkey (struct _des_ctx *ctx, const byte * key) { static const char *selftest_failed; int i; if (!fips_mode () && !initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("%s\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; des_key_schedule (key, ctx->encrypt_subkeys); _gcry_burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; } return 0; } /* * Electronic Codebook Mode DES encryption/decryption of data according * to 'mode'. */ static int des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode) { u32 left, right, work; u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; READ_64BIT_DATA (from, left, right) INITIAL_PERMUTATION (left, work, right) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) FINAL_PERMUTATION (right, work, left) WRITE_64BIT_DATA (to, right, left) return 0; } /* * Fill a Triple-DES context with subkeys calculated from two 64bit keys. * Does not check the parity bits of the keys, but simply ignore them. * Does not check for weak keys. */ static int tripledes_set2keys (struct _tripledes_ctx *ctx, const byte * key1, const byte * key2) { int i; des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); _gcry_burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i]; ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i]; ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1]; ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i]; ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1]; } return 0; } /* * Fill a Triple-DES context with subkeys calculated from three 64bit keys. * Does not check the parity bits of the keys, but simply ignore them. * Does not check for weak keys. */ static int tripledes_set3keys (struct _tripledes_ctx *ctx, const byte * key1, const byte * key2, const byte * key3) { static const char *selftest_failed; int i; if (!fips_mode () && !initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("%s\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; des_key_schedule (key1, ctx->encrypt_subkeys); des_key_schedule (key2, &(ctx->decrypt_subkeys[32])); des_key_schedule (key3, &(ctx->encrypt_subkeys[64])); _gcry_burn_stack (32); for(i=0; i<32; i+=2) { ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i]; ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i]; ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i]; ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i]; ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i]; ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i]; } return 0; } /* * Electronic Codebook Mode Triple-DES encryption/decryption of data * according to 'mode'. Sometimes this mode is named 'EDE' mode * (Encryption-Decryption-Encryption). */ static int tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, byte * to, int mode) { u32 left, right, work; u32 *keys; keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; READ_64BIT_DATA (from, left, right) INITIAL_PERMUTATION (left, work, right) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys) FINAL_PERMUTATION (right, work, left) WRITE_64BIT_DATA (to, right, left) return 0; } /* * Check whether the 8 byte key is weak. * Does not check the parity bits of the key but simple ignore them. */ static int is_weak_key ( const byte *key ) { byte work[8]; int i, left, right, middle, cmp_result; /* clear parity bits */ for(i=0; i<8; ++i) work[i] = key[i] & 0xfe; /* binary search in the weak key table */ left = 0; right = 63; while(left <= right) { middle = (left + right) / 2; if ( !(cmp_result=working_memcmp(work, weak_keys[middle], 8)) ) return -1; if ( cmp_result > 0 ) left = middle + 1; else right = middle - 1; } return 0; } /* * Performs a selftest of this DES/Triple-DES implementation. * Returns an string with the error text on failure. * Returns NULL if all is ok. */ static const char * selftest (void) { /* * Check if 'u32' is really 32 bits wide. This DES / 3DES implementation * need this. */ if (sizeof (u32) != 4) return "Wrong word size for DES configured."; /* * DES Maintenance Test */ { int i; byte key[8] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}; byte input[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; byte result[8] = {0x24, 0x6e, 0x9d, 0xb9, 0xc5, 0x50, 0x38, 0x1a}; byte temp1[8], temp2[8], temp3[8]; des_ctx des; for (i = 0; i < 64; ++i) { des_setkey (des, key); des_ecb_encrypt (des, input, temp1); des_ecb_encrypt (des, temp1, temp2); des_setkey (des, temp2); des_ecb_decrypt (des, temp1, temp3); memcpy (key, temp3, 8); memcpy (input, temp1, 8); } if (memcmp (temp3, result, 8)) return "DES maintenance test failed."; } /* * Self made Triple-DES test (Does somebody know an official test?) */ { int i; byte input[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; byte key1[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; byte key2[8] = {0x11, 0x22, 0x33, 0x44, 0xff, 0xaa, 0xcc, 0xdd}; byte result[8] = {0x7b, 0x38, 0x3b, 0x23, 0xa2, 0x7d, 0x26, 0xd3}; tripledes_ctx des3; for (i = 0; i < 16; ++i) { tripledes_set2keys (des3, key1, key2); tripledes_ecb_encrypt (des3, input, key1); tripledes_ecb_decrypt (des3, input, key2); tripledes_set3keys (des3, key1, input, key2); tripledes_ecb_encrypt (des3, input, input); } if (memcmp (input, result, 8)) return "Triple-DES test failed."; } /* * More Triple-DES test. These are testvectors as used by SSLeay, * thanks to Jeroen C. van Gelderen. */ { struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, { 0x9D,0x64,0x55,0x5A,0x9A,0x10,0xB8,0x52, }, { 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00 } }, { { 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E, 0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E }, { 0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A }, { 0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A } }, { { 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6, 0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6 }, { 0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2 }, { 0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0x3D,0x12,0x4F,0xE2,0x19,0x8B,0xA3,0x18 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0xFB,0xAB,0xA1,0xFF,0x9D,0x05,0xE9,0xB1 } }, { { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }, { 0x73,0x6F,0x6D,0x65,0x64,0x61,0x74,0x61 }, { 0x18,0xd7,0x48,0xe5,0x63,0x62,0x05,0x72 } }, { { 0x03,0x52,0x02,0x07,0x67,0x20,0x82,0x17, 0x86,0x02,0x87,0x66,0x59,0x08,0x21,0x98, 0x64,0x05,0x6A,0xBD,0xFE,0xA9,0x34,0x57 }, { 0x73,0x71,0x75,0x69,0x67,0x67,0x6C,0x65 }, { 0xc0,0x7d,0x2a,0x0f,0xa5,0x66,0xfa,0x30 } }, { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x80,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0xe6,0xe6,0xdd,0x5b,0x7e,0x72,0x29,0x74 } }, { { 0x10,0x46,0x10,0x34,0x89,0x98,0x80,0x20, 0x91,0x07,0xD0,0x15,0x89,0x19,0x01,0x01, 0x19,0x07,0x92,0x10,0x98,0x1A,0x01,0x01 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0xe1,0xef,0x62,0xc3,0x32,0xfe,0x82,0x5b } } }; byte result[8]; int i; tripledes_ctx des3; for (i=0; iflags.no_weak_key) ; /* Detection has been disabled. */ else if (is_weak_key (key) || is_weak_key (key+8) || is_weak_key (key+16)) { _gcry_burn_stack (64); return GPG_ERR_WEAK_KEY; } _gcry_burn_stack (64); return GPG_ERR_NO_ERROR; } static gcry_err_code_t do_tripledes_set_extra_info (void *context, int what, const void *buffer, size_t buflen) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *)context; gpg_err_code_t ec = 0; (void)buffer; (void)buflen; switch (what) { case CIPHER_INFO_NO_WEAK_KEY: ctx->flags.no_weak_key = 1; break; default: ec = GPG_ERR_INV_OP; break; } return ec; } static unsigned int do_tripledes_encrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_encrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ (32); } static unsigned int do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context; tripledes_ecb_decrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ (32); } static gcry_err_code_t do_des_setkey (void *context, const byte *key, unsigned keylen) { struct _des_ctx *ctx = (struct _des_ctx *) context; if (keylen != 8) return GPG_ERR_INV_KEYLEN; des_setkey (ctx, key); if (is_weak_key (key)) { _gcry_burn_stack (64); return GPG_ERR_WEAK_KEY; } _gcry_burn_stack (64); return GPG_ERR_NO_ERROR; } static unsigned int do_des_encrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _des_ctx *ctx = (struct _des_ctx *) context; des_ecb_encrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ (32); } static unsigned int do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) { struct _des_ctx *ctx = (struct _des_ctx *) context; des_ecb_decrypt ( ctx, inbuf, outbuf ); return /*burn_stack*/ (32); } /* Self-test section. */ /* Selftest for TripleDES. */ static gpg_err_code_t selftest_fips (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; (void)extended; /* No extended tests available. */ what = "low-level"; errtxt = selftest (); if (errtxt) goto failed; /* The low-level self-tests are quite extensive and thus we can do without high level tests. This is also justified because we have no custom block code implementation for 3des but always use the standard high level block code. */ return 0; /* Succeeded. */ failed: if (report) report ("cipher", GCRY_CIPHER_3DES, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_CIPHER_3DES: ec = selftest_fips (extended, report); break; default: ec = GPG_ERR_CIPHER_ALGO; break; } return ec; } gcry_cipher_spec_t _gcry_cipher_spec_des = { "DES", NULL, NULL, 8, 64, sizeof (struct _des_ctx), do_des_setkey, do_des_encrypt, do_des_decrypt }; static gcry_cipher_oid_spec_t oids_tripledes[] = { { "1.2.840.113549.3.7", GCRY_CIPHER_MODE_CBC }, /* Teletrust specific OID for 3DES. */ { "1.3.36.3.1.3.2.1", GCRY_CIPHER_MODE_CBC }, /* pbeWithSHAAnd3_KeyTripleDES_CBC */ { "1.2.840.113549.1.12.1.3", GCRY_CIPHER_MODE_CBC }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_tripledes = { "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx), do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt }; cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = { run_selftests, do_tripledes_set_extra_info }; diff --git a/cipher/md4.c b/cipher/md4.c index 2de530cc..e2d096ce 100644 --- a/cipher/md4.c +++ b/cipher/md4.c @@ -1,290 +1,267 @@ /* md4.c - MD4 Message-Digest Algorithm * Copyright (C) 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * Based on md5.c in libgcrypt, but rewritten to compute md4 checksums * using a public domain md4 implementation with the following comments: * * Modified by Wei Dai from Andrew M. Kuchling's md4.c * The original code and all modifications are in the public domain. * * This is the original introductory comment: * * md4.c : MD4 hash algorithm. * * Part of the Python Cryptography Toolkit, version 1.1 * * Distribute and use freely; there are no restrictions on further * dissemination and usage except those imposed by the laws of your * country of residence. * */ /* MD4 test suite: * MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 * MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 * MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d * MD4 ("message digest") = d9130a8164549fe818874806e1c7014b * MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 * MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = * 043f8582f241db351ce627e153e7f0e4 * MD4 ("123456789012345678901234567890123456789012345678901234567890123456 * 78901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "bithelp.h" +#include "bufhelp.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; u32 A,B,C,D; /* chaining variables */ } MD4_CONTEXT; static unsigned int transform ( void *c, const unsigned char *data ); static void md4_init( void *context ) { MD4_CONTEXT *ctx = context; ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->bctx.nblocks = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 64; ctx->bctx.bwrite = transform; } #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) /**************** * transform 64 bytes */ static unsigned int transform ( void *c, const unsigned char *data ) { MD4_CONTEXT *ctx = c; u32 in[16]; register u32 A = ctx->A; register u32 B = ctx->B; register u32 C = ctx->C; register u32 D = ctx->D; + int i; -#ifdef WORDS_BIGENDIAN - { - int i; - byte *p2; - const byte *p1; - for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) - { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } -#else - memcpy (in, data, 64); -#endif + for ( i = 0; i < 16; i++ ) + in[i] = buf_get_le32(data + i * 4); /* Round 1. */ #define function(a,b,c,d,k,s) a=rol(a+F(b,c,d)+in[k],s); function(A,B,C,D, 0, 3); function(D,A,B,C, 1, 7); function(C,D,A,B, 2,11); function(B,C,D,A, 3,19); function(A,B,C,D, 4, 3); function(D,A,B,C, 5, 7); function(C,D,A,B, 6,11); function(B,C,D,A, 7,19); function(A,B,C,D, 8, 3); function(D,A,B,C, 9, 7); function(C,D,A,B,10,11); function(B,C,D,A,11,19); function(A,B,C,D,12, 3); function(D,A,B,C,13, 7); function(C,D,A,B,14,11); function(B,C,D,A,15,19); #undef function /* Round 2. */ #define function(a,b,c,d,k,s) a=rol(a+G(b,c,d)+in[k]+0x5a827999,s); function(A,B,C,D, 0, 3); function(D,A,B,C, 4, 5); function(C,D,A,B, 8, 9); function(B,C,D,A,12,13); function(A,B,C,D, 1, 3); function(D,A,B,C, 5, 5); function(C,D,A,B, 9, 9); function(B,C,D,A,13,13); function(A,B,C,D, 2, 3); function(D,A,B,C, 6, 5); function(C,D,A,B,10, 9); function(B,C,D,A,14,13); function(A,B,C,D, 3, 3); function(D,A,B,C, 7, 5); function(C,D,A,B,11, 9); function(B,C,D,A,15,13); #undef function /* Round 3. */ #define function(a,b,c,d,k,s) a=rol(a+H(b,c,d)+in[k]+0x6ed9eba1,s); function(A,B,C,D, 0, 3); function(D,A,B,C, 8, 9); function(C,D,A,B, 4,11); function(B,C,D,A,12,15); function(A,B,C,D, 2, 3); function(D,A,B,C,10, 9); function(C,D,A,B, 6,11); function(B,C,D,A,14,15); function(A,B,C,D, 1, 3); function(D,A,B,C, 9, 9); function(C,D,A,B, 5,11); function(B,C,D,A,13,15); function(A,B,C,D, 3, 3); function(D,A,B,C,11, 9); function(C,D,A,B, 7,11); function(B,C,D,A,15,15); /* Put checksum in context given as argument. */ ctx->A += A; ctx->B += B; ctx->C += C; ctx->D += D; return /*burn_stack*/ 80+6*sizeof(void*); } /* The routine final terminates the message-digest computation and * ends with the desired message digest in mdContext->digest[0...15]. * The handle is prepared for a new MD4 cycle. * Returns 16 bytes representing the digest. */ static void md4_final( void *context ) { MD4_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->bctx.count < 56 ) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ while( hd->bctx.count < 56 ) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ while( hd->bctx.count < 64 ) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write(hd, NULL, 0); /* flush */; memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ - *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) -#else /* little endian */ -#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) -#endif +#define X(a) do { *(u32*)p = le_bswap32((*hd).a) ; p += 4; } while(0) X(A); X(B); X(C); X(D); #undef X } static byte * md4_read (void *context) { MD4_CONTEXT *hd = context; return hd->bctx.buf; } static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */ { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 }; static gcry_md_oid_spec_t oid_spec_md4[] = { /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */ { "1.2.840.113549.2.4" }, { NULL }, }; gcry_md_spec_t _gcry_digest_spec_md4 = { "MD4", asn, DIM (asn), oid_spec_md4,16, md4_init, _gcry_md_block_write, md4_final, md4_read, sizeof (MD4_CONTEXT) }; diff --git a/cipher/md5.c b/cipher/md5.c index 88745a81..db0f3150 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -1,317 +1,293 @@ /* md5.c - MD5 Message-Digest Algorithm * Copyright (C) 1995,1996,1998,1999,2001,2002, * 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * According to the definition of MD5 in RFC 1321 from April 1992. * NOTE: This is *not* the same file as the one from glibc. * Written by Ulrich Drepper , 1995. * heavily modified for GnuPG by Werner Koch */ /* Test values: * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61 * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72 * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0 */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "bithelp.h" +#include "bufhelp.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; u32 A,B,C,D; /* chaining variables */ } MD5_CONTEXT; static unsigned int transform ( void *ctx, const unsigned char *data ); static void md5_init( void *context ) { MD5_CONTEXT *ctx = context; ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; ctx->bctx.nblocks = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 64; ctx->bctx.bwrite = transform; } /* These are the four functions used in the four steps of the MD5 algorithm and defined in the RFC 1321. The first function is a little bit optimized (as found in Colin Plumbs public domain implementation). */ /* #define FF(b, c, d) ((b & c) | (~b & d)) */ #define FF(b, c, d) (d ^ (b & (c ^ d))) #define FG(b, c, d) FF (d, b, c) #define FH(b, c, d) (b ^ c ^ d) #define FI(b, c, d) (c ^ (b | ~d)) /**************** * transform n*64 bytes */ static unsigned int transform ( void *c, const unsigned char *data ) { MD5_CONTEXT *ctx = c; u32 correct_words[16]; register u32 A = ctx->A; register u32 B = ctx->B; register u32 C = ctx->C; register u32 D = ctx->D; u32 *cwp = correct_words; + int i; -#ifdef WORDS_BIGENDIAN - { - int i; - byte *p2; - const byte *p1; - for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) - { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } -#else - memcpy( correct_words, data, 64 ); -#endif - + for ( i = 0; i < 16; i++ ) + correct_words[i] = buf_get_le32(data + i * 4); #define OP(a, b, c, d, s, T) \ do \ { \ a += FF (b, c, d) + (*cwp++) + T; \ a = rol(a, s); \ a += b; \ } \ while (0) /* Before we start, one word about the strange constants. They are defined in RFC 1321 as T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 */ /* Round 1. */ OP (A, B, C, D, 7, 0xd76aa478); OP (D, A, B, C, 12, 0xe8c7b756); OP (C, D, A, B, 17, 0x242070db); OP (B, C, D, A, 22, 0xc1bdceee); OP (A, B, C, D, 7, 0xf57c0faf); OP (D, A, B, C, 12, 0x4787c62a); OP (C, D, A, B, 17, 0xa8304613); OP (B, C, D, A, 22, 0xfd469501); OP (A, B, C, D, 7, 0x698098d8); OP (D, A, B, C, 12, 0x8b44f7af); OP (C, D, A, B, 17, 0xffff5bb1); OP (B, C, D, A, 22, 0x895cd7be); OP (A, B, C, D, 7, 0x6b901122); OP (D, A, B, C, 12, 0xfd987193); OP (C, D, A, B, 17, 0xa679438e); OP (B, C, D, A, 22, 0x49b40821); #undef OP #define OP(f, a, b, c, d, k, s, T) \ do \ { \ a += f (b, c, d) + correct_words[k] + T; \ a = rol(a, s); \ a += b; \ } \ while (0) /* Round 2. */ OP (FG, A, B, C, D, 1, 5, 0xf61e2562); OP (FG, D, A, B, C, 6, 9, 0xc040b340); OP (FG, C, D, A, B, 11, 14, 0x265e5a51); OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); OP (FG, A, B, C, D, 5, 5, 0xd62f105d); OP (FG, D, A, B, C, 10, 9, 0x02441453); OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); OP (FG, D, A, B, C, 14, 9, 0xc33707d6); OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); OP (FG, B, C, D, A, 8, 20, 0x455a14ed); OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); OP (FG, C, D, A, B, 7, 14, 0x676f02d9); OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); /* Round 3. */ OP (FH, A, B, C, D, 5, 4, 0xfffa3942); OP (FH, D, A, B, C, 8, 11, 0x8771f681); OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); OP (FH, B, C, D, A, 14, 23, 0xfde5380c); OP (FH, A, B, C, D, 1, 4, 0xa4beea44); OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); OP (FH, B, C, D, A, 6, 23, 0x04881d05); OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); /* Round 4. */ OP (FI, A, B, C, D, 0, 6, 0xf4292244); OP (FI, D, A, B, C, 7, 10, 0x432aff97); OP (FI, C, D, A, B, 14, 15, 0xab9423a7); OP (FI, B, C, D, A, 5, 21, 0xfc93a039); OP (FI, A, B, C, D, 12, 6, 0x655b59c3); OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); OP (FI, C, D, A, B, 10, 15, 0xffeff47d); OP (FI, B, C, D, A, 1, 21, 0x85845dd1); OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); OP (FI, C, D, A, B, 6, 15, 0xa3014314); OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); OP (FI, A, B, C, D, 4, 6, 0xf7537e82); OP (FI, D, A, B, C, 11, 10, 0xbd3af235); OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); OP (FI, B, C, D, A, 9, 21, 0xeb86d391); /* Put checksum in context given as argument. */ ctx->A += A; ctx->B += B; ctx->C += C; ctx->D += D; return /*burn_stack*/ 80+6*sizeof(void*); } /* The routine final terminates the message-digest computation and * ends with the desired message digest in mdContext->digest[0...15]. * The handle is prepared for a new MD5 cycle. * Returns 16 bytes representing the digest. */ static void md5_final( void *context) { MD5_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->bctx.count < 56 ) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ while( hd->bctx.count < 56 ) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ while( hd->bctx.count < 64 ) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write(hd, NULL, 0); /* flush */; memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ - *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0) -#else /* little endian */ -#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0) -#endif +#define X(a) do { *(u32*)p = le_bswap32((*hd).a) ; p += 4; } while(0) X(A); X(B); X(C); X(D); #undef X } static byte * md5_read( void *context ) { MD5_CONTEXT *hd = (MD5_CONTEXT *) context; return hd->bctx.buf; } static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */ { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 }; static gcry_md_oid_spec_t oid_spec_md5[] = { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */ { "1.2.840.113549.1.1.4" }, /* RSADSI digestAlgorithm MD5 */ { "1.2.840.113549.2.5" }, { NULL }, }; gcry_md_spec_t _gcry_digest_spec_md5 = { "MD5", asn, DIM (asn), oid_spec_md5, 16, md5_init, _gcry_md_block_write, md5_final, md5_read, sizeof (MD5_CONTEXT) }; diff --git a/cipher/rmd160.c b/cipher/rmd160.c index 7f143dfa..d156e61d 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -1,541 +1,510 @@ /* rmd160.c - RIPE-MD160 * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include #include "g10lib.h" #include "rmd.h" #include "cipher.h" /* Only used for the rmd160_hash_buffer() prototype. */ #include "bithelp.h" +#include "bufhelp.h" /********************************* * RIPEMD-160 is not patented, see (as of 25.10.97) * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html * Note that the code uses Little Endian byteorder, which is good for * 386 etc, but we must add some conversion when used on a big endian box. * * * Pseudo-code for RIPEMD-160 * * RIPEMD-160 is an iterative hash function that operates on 32-bit words. * The round function takes as input a 5-word chaining variable and a 16-word * message block and maps this to a new chaining variable. All operations are * defined on 32-bit words. Padding is identical to that of MD4. * * * RIPEMD-160: definitions * * * nonlinear functions at bit level: exor, mux, -, mux, - * * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) * * * added constants (hexadecimal) * * K(j) = 0x00000000 (0 <= j <= 15) * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) * K'(j) = 0x00000000 (64 <= j <= 79) * * * selection of message word * * r(j) = j (0 <= j <= 15) * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 * * * amount for rotate left (rol) * * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 * * * initial value (hexadecimal) * * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; * h4 = 0xC3D2E1F0; * * * RIPEMD-160: pseudo-code * * It is assumed that the message after padding consists of t 16-word blocks * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left * shift (rotate) over s positions. * * * for i := 0 to t-1 { * A := h0; B := h1; C := h2; D = h3; E = h4; * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; * for j := 0 to 79 { * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; * A := E; E := D; D := rol_10(C); C := B; B := T; * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] [+] K'(j)) [+] E'; * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; * } * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; * } */ /* Some examples: * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 */ static unsigned int transform ( void *ctx, const unsigned char *data ); void _gcry_rmd160_init (void *context) { RMD160_CONTEXT *hd = context; hd->h0 = 0x67452301; hd->h1 = 0xEFCDAB89; hd->h2 = 0x98BADCFE; hd->h3 = 0x10325476; hd->h4 = 0xC3D2E1F0; hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; } /**************** * Transform the message X which consists of 16 32-bit-words */ static unsigned int transform ( void *ctx, const unsigned char *data ) { RMD160_CONTEXT *hd = ctx; register u32 a,b,c,d,e; u32 aa,bb,cc,dd,ee,t; -#ifdef WORDS_BIGENDIAN u32 x[16]; - { - int i; - byte *p2; - const byte *p1; - for (i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) - { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } -#else - /* This version is better because it is always aligned; - * The performance penalty on a 586-100 is about 6% which - * is acceptable - because the data is more local it might - * also be possible that this is faster on some machines. - * This function (when compiled with -02 on gcc 2.7.2) - * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; - * [measured with a 4MB data and "gpgm --print-md rmd160"] */ - u32 x[16]; - memcpy( x, data, 64 ); -#endif + int i; + for ( i = 0; i < 16; i++ ) + x[i] = buf_get_le32(data + i * 4); #define K0 0x00000000 #define K1 0x5A827999 #define K2 0x6ED9EBA1 #define K3 0x8F1BBCDC #define K4 0xA953FD4E #define KK0 0x50A28BE6 #define KK1 0x5C4DD124 #define KK2 0x6D703EF3 #define KK3 0x7A6D76E9 #define KK4 0x00000000 #define F0(x,y,z) ( (x) ^ (y) ^ (z) ) #define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) #define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) #define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) #define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) #define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ a = rol(t,s) + e; \ c = rol(c,10); \ } while(0) /* left lane */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; R( a, b, c, d, e, F0, K0, 0, 11 ); R( e, a, b, c, d, F0, K0, 1, 14 ); R( d, e, a, b, c, F0, K0, 2, 15 ); R( c, d, e, a, b, F0, K0, 3, 12 ); R( b, c, d, e, a, F0, K0, 4, 5 ); R( a, b, c, d, e, F0, K0, 5, 8 ); R( e, a, b, c, d, F0, K0, 6, 7 ); R( d, e, a, b, c, F0, K0, 7, 9 ); R( c, d, e, a, b, F0, K0, 8, 11 ); R( b, c, d, e, a, F0, K0, 9, 13 ); R( a, b, c, d, e, F0, K0, 10, 14 ); R( e, a, b, c, d, F0, K0, 11, 15 ); R( d, e, a, b, c, F0, K0, 12, 6 ); R( c, d, e, a, b, F0, K0, 13, 7 ); R( b, c, d, e, a, F0, K0, 14, 9 ); R( a, b, c, d, e, F0, K0, 15, 8 ); R( e, a, b, c, d, F1, K1, 7, 7 ); R( d, e, a, b, c, F1, K1, 4, 6 ); R( c, d, e, a, b, F1, K1, 13, 8 ); R( b, c, d, e, a, F1, K1, 1, 13 ); R( a, b, c, d, e, F1, K1, 10, 11 ); R( e, a, b, c, d, F1, K1, 6, 9 ); R( d, e, a, b, c, F1, K1, 15, 7 ); R( c, d, e, a, b, F1, K1, 3, 15 ); R( b, c, d, e, a, F1, K1, 12, 7 ); R( a, b, c, d, e, F1, K1, 0, 12 ); R( e, a, b, c, d, F1, K1, 9, 15 ); R( d, e, a, b, c, F1, K1, 5, 9 ); R( c, d, e, a, b, F1, K1, 2, 11 ); R( b, c, d, e, a, F1, K1, 14, 7 ); R( a, b, c, d, e, F1, K1, 11, 13 ); R( e, a, b, c, d, F1, K1, 8, 12 ); R( d, e, a, b, c, F2, K2, 3, 11 ); R( c, d, e, a, b, F2, K2, 10, 13 ); R( b, c, d, e, a, F2, K2, 14, 6 ); R( a, b, c, d, e, F2, K2, 4, 7 ); R( e, a, b, c, d, F2, K2, 9, 14 ); R( d, e, a, b, c, F2, K2, 15, 9 ); R( c, d, e, a, b, F2, K2, 8, 13 ); R( b, c, d, e, a, F2, K2, 1, 15 ); R( a, b, c, d, e, F2, K2, 2, 14 ); R( e, a, b, c, d, F2, K2, 7, 8 ); R( d, e, a, b, c, F2, K2, 0, 13 ); R( c, d, e, a, b, F2, K2, 6, 6 ); R( b, c, d, e, a, F2, K2, 13, 5 ); R( a, b, c, d, e, F2, K2, 11, 12 ); R( e, a, b, c, d, F2, K2, 5, 7 ); R( d, e, a, b, c, F2, K2, 12, 5 ); R( c, d, e, a, b, F3, K3, 1, 11 ); R( b, c, d, e, a, F3, K3, 9, 12 ); R( a, b, c, d, e, F3, K3, 11, 14 ); R( e, a, b, c, d, F3, K3, 10, 15 ); R( d, e, a, b, c, F3, K3, 0, 14 ); R( c, d, e, a, b, F3, K3, 8, 15 ); R( b, c, d, e, a, F3, K3, 12, 9 ); R( a, b, c, d, e, F3, K3, 4, 8 ); R( e, a, b, c, d, F3, K3, 13, 9 ); R( d, e, a, b, c, F3, K3, 3, 14 ); R( c, d, e, a, b, F3, K3, 7, 5 ); R( b, c, d, e, a, F3, K3, 15, 6 ); R( a, b, c, d, e, F3, K3, 14, 8 ); R( e, a, b, c, d, F3, K3, 5, 6 ); R( d, e, a, b, c, F3, K3, 6, 5 ); R( c, d, e, a, b, F3, K3, 2, 12 ); R( b, c, d, e, a, F4, K4, 4, 9 ); R( a, b, c, d, e, F4, K4, 0, 15 ); R( e, a, b, c, d, F4, K4, 5, 5 ); R( d, e, a, b, c, F4, K4, 9, 11 ); R( c, d, e, a, b, F4, K4, 7, 6 ); R( b, c, d, e, a, F4, K4, 12, 8 ); R( a, b, c, d, e, F4, K4, 2, 13 ); R( e, a, b, c, d, F4, K4, 10, 12 ); R( d, e, a, b, c, F4, K4, 14, 5 ); R( c, d, e, a, b, F4, K4, 1, 12 ); R( b, c, d, e, a, F4, K4, 3, 13 ); R( a, b, c, d, e, F4, K4, 8, 14 ); R( e, a, b, c, d, F4, K4, 11, 11 ); R( d, e, a, b, c, F4, K4, 6, 8 ); R( c, d, e, a, b, F4, K4, 15, 5 ); R( b, c, d, e, a, F4, K4, 13, 6 ); aa = a; bb = b; cc = c; dd = d; ee = e; /* right lane */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; R( a, b, c, d, e, F4, KK0, 5, 8); R( e, a, b, c, d, F4, KK0, 14, 9); R( d, e, a, b, c, F4, KK0, 7, 9); R( c, d, e, a, b, F4, KK0, 0, 11); R( b, c, d, e, a, F4, KK0, 9, 13); R( a, b, c, d, e, F4, KK0, 2, 15); R( e, a, b, c, d, F4, KK0, 11, 15); R( d, e, a, b, c, F4, KK0, 4, 5); R( c, d, e, a, b, F4, KK0, 13, 7); R( b, c, d, e, a, F4, KK0, 6, 7); R( a, b, c, d, e, F4, KK0, 15, 8); R( e, a, b, c, d, F4, KK0, 8, 11); R( d, e, a, b, c, F4, KK0, 1, 14); R( c, d, e, a, b, F4, KK0, 10, 14); R( b, c, d, e, a, F4, KK0, 3, 12); R( a, b, c, d, e, F4, KK0, 12, 6); R( e, a, b, c, d, F3, KK1, 6, 9); R( d, e, a, b, c, F3, KK1, 11, 13); R( c, d, e, a, b, F3, KK1, 3, 15); R( b, c, d, e, a, F3, KK1, 7, 7); R( a, b, c, d, e, F3, KK1, 0, 12); R( e, a, b, c, d, F3, KK1, 13, 8); R( d, e, a, b, c, F3, KK1, 5, 9); R( c, d, e, a, b, F3, KK1, 10, 11); R( b, c, d, e, a, F3, KK1, 14, 7); R( a, b, c, d, e, F3, KK1, 15, 7); R( e, a, b, c, d, F3, KK1, 8, 12); R( d, e, a, b, c, F3, KK1, 12, 7); R( c, d, e, a, b, F3, KK1, 4, 6); R( b, c, d, e, a, F3, KK1, 9, 15); R( a, b, c, d, e, F3, KK1, 1, 13); R( e, a, b, c, d, F3, KK1, 2, 11); R( d, e, a, b, c, F2, KK2, 15, 9); R( c, d, e, a, b, F2, KK2, 5, 7); R( b, c, d, e, a, F2, KK2, 1, 15); R( a, b, c, d, e, F2, KK2, 3, 11); R( e, a, b, c, d, F2, KK2, 7, 8); R( d, e, a, b, c, F2, KK2, 14, 6); R( c, d, e, a, b, F2, KK2, 6, 6); R( b, c, d, e, a, F2, KK2, 9, 14); R( a, b, c, d, e, F2, KK2, 11, 12); R( e, a, b, c, d, F2, KK2, 8, 13); R( d, e, a, b, c, F2, KK2, 12, 5); R( c, d, e, a, b, F2, KK2, 2, 14); R( b, c, d, e, a, F2, KK2, 10, 13); R( a, b, c, d, e, F2, KK2, 0, 13); R( e, a, b, c, d, F2, KK2, 4, 7); R( d, e, a, b, c, F2, KK2, 13, 5); R( c, d, e, a, b, F1, KK3, 8, 15); R( b, c, d, e, a, F1, KK3, 6, 5); R( a, b, c, d, e, F1, KK3, 4, 8); R( e, a, b, c, d, F1, KK3, 1, 11); R( d, e, a, b, c, F1, KK3, 3, 14); R( c, d, e, a, b, F1, KK3, 11, 14); R( b, c, d, e, a, F1, KK3, 15, 6); R( a, b, c, d, e, F1, KK3, 0, 14); R( e, a, b, c, d, F1, KK3, 5, 6); R( d, e, a, b, c, F1, KK3, 12, 9); R( c, d, e, a, b, F1, KK3, 2, 12); R( b, c, d, e, a, F1, KK3, 13, 9); R( a, b, c, d, e, F1, KK3, 9, 12); R( e, a, b, c, d, F1, KK3, 7, 5); R( d, e, a, b, c, F1, KK3, 10, 15); R( c, d, e, a, b, F1, KK3, 14, 8); R( b, c, d, e, a, F0, KK4, 12, 8); R( a, b, c, d, e, F0, KK4, 15, 5); R( e, a, b, c, d, F0, KK4, 10, 12); R( d, e, a, b, c, F0, KK4, 4, 9); R( c, d, e, a, b, F0, KK4, 1, 12); R( b, c, d, e, a, F0, KK4, 5, 5); R( a, b, c, d, e, F0, KK4, 8, 14); R( e, a, b, c, d, F0, KK4, 7, 6); R( d, e, a, b, c, F0, KK4, 6, 8); R( c, d, e, a, b, F0, KK4, 2, 13); R( b, c, d, e, a, F0, KK4, 13, 6); R( a, b, c, d, e, F0, KK4, 14, 5); R( e, a, b, c, d, F0, KK4, 0, 15); R( d, e, a, b, c, F0, KK4, 3, 13); R( c, d, e, a, b, F0, KK4, 9, 11); R( b, c, d, e, a, F0, KK4, 11, 11); t = hd->h1 + d + cc; hd->h1 = hd->h2 + e + dd; hd->h2 = hd->h3 + a + ee; hd->h3 = hd->h4 + b + aa; hd->h4 = hd->h0 + c + bb; hd->h0 = t; return /*burn_stack*/ 108+5*sizeof(void*); } /**************** * Apply the rmd160 transform function on the buffer which must have * a length 64 bytes. Do not use this function together with the * other functions, use rmd160_init to initialize internal variables. * Returns: 16 bytes in buffer with the mixed contentes of buffer. */ void _gcry_rmd160_mixblock ( RMD160_CONTEXT *hd, void *blockof64byte ) { char *p = blockof64byte; transform ( hd, blockof64byte ); #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); #undef X } /* The routine terminates the computation */ static void rmd160_final( void *context ) { RMD160_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->bctx.count < 56 ) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ while( hd->bctx.count < 56 ) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ while( hd->bctx.count < 64 ) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write(hd, NULL, 0); /* flush */; memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ - *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) -#else /* little endian */ -#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -#endif +#define X(a) do { *(u32*)p = le_bswap32(hd->h##a) ; p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); #undef X } static byte * rmd160_read( void *context ) { RMD160_CONTEXT *hd = context; return hd->bctx.buf; } /**************** * Shortcut functions which puts the hash value of the supplied buffer * into outbuf which must have a size of 20 bytes. */ void _gcry_rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length ) { RMD160_CONTEXT hd; _gcry_rmd160_init ( &hd ); _gcry_md_block_write ( &hd, buffer, length ); rmd160_final ( &hd ); memcpy ( outbuf, hd.bctx.buf, 20 ); } static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; static gcry_md_oid_spec_t oid_spec_rmd160[] = { /* rsaSignatureWithripemd160 */ { "1.3.36.3.3.1.2" }, /* TeleTrust hash algorithm. */ { "1.3.36.3.2.1" }, { NULL } }; gcry_md_spec_t _gcry_digest_spec_rmd160 = { "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20, _gcry_rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read, sizeof (RMD160_CONTEXT) }; diff --git a/cipher/salsa20.c b/cipher/salsa20.c index 37f2989e..88f53725 100644 --- a/cipher/salsa20.c +++ b/cipher/salsa20.c @@ -1,419 +1,409 @@ /* salsa20.c - Bernstein's Salsa20 cipher * Copyright (C) 2012 Simon Josefsson, Niels Möller * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * * For a description of the algorithm, see: * http://cr.yp.to/snuffle/spec.pdf * http://cr.yp.to/snuffle/design.pdf */ /* The code is based on the code in Nettle (git commit id 9d2d8ddaee35b91a4e1a32ae77cba04bea3480e7) which in turn is based on salsa20-ref.c version 20051118 D. J. Bernstein Public domain. */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #define SALSA20_MIN_KEY_SIZE 16 /* Bytes. */ #define SALSA20_MAX_KEY_SIZE 32 /* Bytes. */ #define SALSA20_BLOCK_SIZE 64 /* Bytes. */ #define SALSA20_IV_SIZE 8 /* Bytes. */ #define SALSA20_INPUT_LENGTH 16 /* Bytes. */ /* Number of rounds. The standard uses 20 rounds. In any case the number of rounds must be even. */ #define SALSA20_ROUNDS 20 #define SALSA20R12_ROUNDS 12 typedef struct { /* Indices 1-4 and 11-14 holds the key (two identical copies for the shorter key size), indices 0, 5, 10, 15 are constant, indices 6, 7 are the IV, and indices 8, 9 are the block counter: C K K K K C I I B B C K K K K C */ u32 input[SALSA20_INPUT_LENGTH]; u32 pad[SALSA20_INPUT_LENGTH]; unsigned int unused; /* bytes in the pad. */ } SALSA20_context_t; /* The masking of the right shift is needed to allow n == 0 (using just 32 - n and 64 - n results in undefined behaviour). Most uses of these macros use a constant and non-zero rotation count. */ #define ROTL32(n,x) (((x)<<(n)) | ((x)>>((-(n)&31)))) -#ifdef WORDS_BIGENDIAN -# define LE_SWAP32(v) \ - ( (ROTL32( 8, v) & 0x00FF00FFul) \ - |(ROTL32(24, v) & 0xFF00FF00ul)) -#else -# define LE_SWAP32(v) (v) -#endif +#define LE_SWAP32(v) le_bswap32(v) -#define LE_READ_UINT32(p) \ - ( (((u32)(p)[3]) << 24) \ - | (((u32)(p)[2]) << 16) \ - | (((u32)(p)[1]) << 8) \ - | ((u32)(p)[0])) +#define LE_READ_UINT32(p) buf_get_le32(p) static void salsa20_setiv (void *context, const byte *iv, unsigned int ivlen); static const char *selftest (void); #if 0 # define SALSA20_CORE_DEBUG(i) do { \ unsigned debug_j; \ for (debug_j = 0; debug_j < 16; debug_j++) \ { \ if (debug_j == 0) \ fprintf(stderr, "%2d:", (i)); \ else if (debug_j % 4 == 0) \ fprintf(stderr, "\n "); \ fprintf(stderr, " %8x", pad[debug_j]); \ } \ fprintf(stderr, "\n"); \ } while (0) #else # define SALSA20_CORE_DEBUG(i) #endif #define QROUND(x0, x1, x2, x3) \ do { \ x1 ^= ROTL32 ( 7, x0 + x3); \ x2 ^= ROTL32 ( 9, x1 + x0); \ x3 ^= ROTL32 (13, x2 + x1); \ x0 ^= ROTL32 (18, x3 + x2); \ } while(0) static void salsa20_core (u32 *dst, const u32 *src, unsigned rounds) { u32 pad[SALSA20_INPUT_LENGTH]; unsigned int i; memcpy (pad, src, sizeof(pad)); for (i = 0; i < rounds; i += 2) { SALSA20_CORE_DEBUG (i); QROUND (pad[0], pad[4], pad[8], pad[12]); QROUND (pad[5], pad[9], pad[13], pad[1] ); QROUND (pad[10], pad[14], pad[2], pad[6] ); QROUND (pad[15], pad[3], pad[7], pad[11]); SALSA20_CORE_DEBUG (i+1); QROUND (pad[0], pad[1], pad[2], pad[3] ); QROUND (pad[5], pad[6], pad[7], pad[4] ); QROUND (pad[10], pad[11], pad[8], pad[9] ); QROUND (pad[15], pad[12], pad[13], pad[14]); } SALSA20_CORE_DEBUG (i); for (i = 0; i < SALSA20_INPUT_LENGTH; i++) { u32 t = pad[i] + src[i]; dst[i] = LE_SWAP32 (t); } } #undef QROUND #undef SALSA20_CORE_DEBUG static gcry_err_code_t salsa20_do_setkey (SALSA20_context_t *ctx, const byte *key, unsigned int keylen) { static int initialized; static const char *selftest_failed; if (!initialized ) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("SALSA20 selftest failed (%s)\n", selftest_failed ); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen != SALSA20_MIN_KEY_SIZE && keylen != SALSA20_MAX_KEY_SIZE) return GPG_ERR_INV_KEYLEN; /* These constants are the little endian encoding of the string "expand 32-byte k". For the 128 bit variant, the "32" in that string will be fixed up to "16". */ ctx->input[0] = 0x61707865; /* "apxe" */ ctx->input[5] = 0x3320646e; /* "3 dn" */ ctx->input[10] = 0x79622d32; /* "yb-2" */ ctx->input[15] = 0x6b206574; /* "k et" */ ctx->input[1] = LE_READ_UINT32(key + 0); ctx->input[2] = LE_READ_UINT32(key + 4); ctx->input[3] = LE_READ_UINT32(key + 8); ctx->input[4] = LE_READ_UINT32(key + 12); if (keylen == SALSA20_MAX_KEY_SIZE) /* 256 bits */ { ctx->input[11] = LE_READ_UINT32(key + 16); ctx->input[12] = LE_READ_UINT32(key + 20); ctx->input[13] = LE_READ_UINT32(key + 24); ctx->input[14] = LE_READ_UINT32(key + 28); } else /* 128 bits */ { ctx->input[11] = ctx->input[1]; ctx->input[12] = ctx->input[2]; ctx->input[13] = ctx->input[3]; ctx->input[14] = ctx->input[4]; ctx->input[5] -= 0x02000000; /* Change to "1 dn". */ ctx->input[10] += 0x00000004; /* Change to "yb-6". */ } /* We default to a zero nonce. */ salsa20_setiv (ctx, NULL, 0); return 0; } static gcry_err_code_t salsa20_setkey (void *context, const byte *key, unsigned int keylen) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; gcry_err_code_t rc = salsa20_do_setkey (ctx, key, keylen); _gcry_burn_stack (300/* FIXME*/); return rc; } static void salsa20_setiv (void *context, const byte *iv, unsigned int ivlen) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; if (!iv) { ctx->input[6] = 0; ctx->input[7] = 0; } else if (ivlen == SALSA20_IV_SIZE) { ctx->input[6] = LE_READ_UINT32(iv + 0); ctx->input[7] = LE_READ_UINT32(iv + 4); } else { log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", ivlen); ctx->input[6] = 0; ctx->input[7] = 0; } /* Reset the block counter. */ ctx->input[8] = 0; ctx->input[9] = 0; /* Reset the unused pad bytes counter. */ ctx->unused = 0; } /* Note: This function requires LENGTH > 0. */ static void salsa20_do_encrypt_stream (SALSA20_context_t *ctx, byte *outbuf, const byte *inbuf, unsigned int length, unsigned rounds) { if (ctx->unused) { unsigned char *p = (void*)ctx->pad; unsigned int n; gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE); n = ctx->unused; if (n > length) n = length; buf_xor (outbuf, inbuf, p + SALSA20_BLOCK_SIZE - ctx->unused, n); length -= n; outbuf += n; inbuf += n; ctx->unused -= n; if (!length) return; gcry_assert (!ctx->unused); } for (;;) { /* Create the next pad and bump the block counter. Note that it is the user's duty to change to another nonce not later than after 2^70 processed bytes. */ salsa20_core (ctx->pad, ctx->input, rounds); if (!++ctx->input[8]) ctx->input[9]++; if (length <= SALSA20_BLOCK_SIZE) { buf_xor (outbuf, inbuf, ctx->pad, length); ctx->unused = SALSA20_BLOCK_SIZE - length; return; } buf_xor (outbuf, inbuf, ctx->pad, SALSA20_BLOCK_SIZE); length -= SALSA20_BLOCK_SIZE; outbuf += SALSA20_BLOCK_SIZE; inbuf += SALSA20_BLOCK_SIZE; } } static void salsa20_encrypt_stream (void *context, byte *outbuf, const byte *inbuf, unsigned int length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; if (length) { salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20_ROUNDS); _gcry_burn_stack (/* salsa20_do_encrypt_stream: */ 2*sizeof (void*) + 3*sizeof (void*) + sizeof (unsigned int) /* salsa20_core: */ + 2*sizeof (void*) + 2*sizeof (void*) + 64 + sizeof (unsigned int) + sizeof (u32) ); } } static void salsa20r12_encrypt_stream (void *context, byte *outbuf, const byte *inbuf, unsigned int length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; if (length) { salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20R12_ROUNDS); _gcry_burn_stack (/* salsa20_do_encrypt_stream: */ 2*sizeof (void*) + 3*sizeof (void*) + sizeof (unsigned int) /* salsa20_core: */ + 2*sizeof (void*) + 2*sizeof (void*) + 64 + sizeof (unsigned int) + sizeof (u32) ); } } static const char* selftest (void) { SALSA20_context_t ctx; byte scratch[8+1]; static byte key_1[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const byte nonce_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const byte plaintext_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const byte ciphertext_1[] = { 0xE3, 0xBE, 0x8F, 0xDD, 0x8B, 0xEC, 0xA2, 0xE3}; salsa20_setkey (&ctx, key_1, sizeof key_1); salsa20_setiv (&ctx, nonce_1, sizeof nonce_1); scratch[8] = 0; salsa20_encrypt_stream (&ctx, scratch, plaintext_1, sizeof plaintext_1); if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1)) return "Salsa20 encryption test 1 failed."; if (scratch[8]) return "Salsa20 wrote too much."; salsa20_setkey( &ctx, key_1, sizeof(key_1)); salsa20_setiv (&ctx, nonce_1, sizeof nonce_1); salsa20_encrypt_stream (&ctx, scratch, scratch, sizeof plaintext_1); if (memcmp (scratch, plaintext_1, sizeof plaintext_1)) return "Salsa20 decryption test 1 failed."; return NULL; } gcry_cipher_spec_t _gcry_cipher_spec_salsa20 = { "SALSA20", /* name */ NULL, /* aliases */ NULL, /* oids */ 1, /* blocksize in bytes. */ SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */ sizeof (SALSA20_context_t), salsa20_setkey, NULL, NULL, salsa20_encrypt_stream, salsa20_encrypt_stream }; gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12 = { "SALSA20R12", /* name */ NULL, /* aliases */ NULL, /* oids */ 1, /* blocksize in bytes. */ SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */ sizeof (SALSA20_context_t), salsa20_setkey, NULL, NULL, salsa20r12_encrypt_stream, salsa20r12_encrypt_stream }; cipher_extra_spec_t _gcry_cipher_extraspec_salsa20 = { NULL, NULL, salsa20_setiv }; diff --git a/cipher/scrypt.c b/cipher/scrypt.c index 9e29288a..6f6a7f11 100644 --- a/cipher/scrypt.c +++ b/cipher/scrypt.c @@ -1,348 +1,324 @@ /* scrypt.c - Scrypt password-based key derivation function. * Copyright (C) 2012 Simon Josefsson * Copyright (C) 2013 Christian Grothoff * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* Adapted from the nettle, low-level cryptographics library for * libgcrypt by Christian Grothoff; original license: * * Copyright (C) 2012 Simon Josefsson * * The nettle library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The nettle library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the nettle library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02111-1301, USA. */ #include #include #include #include #include "g10lib.h" #include "kdf-internal.h" #include "bufhelp.h" /* We really need a 64 bit type for this code. */ #ifdef HAVE_U64_TYPEDEF #define SALSA20_INPUT_LENGTH 16 #define ROTL32(n,x) (((x)<<(n)) | ((x)>>(32-(n)))) /* Reads a 64-bit integer, in network, big-endian, byte order */ -#define READ_UINT64(p) \ -( (((u64) (p)[0]) << 56) \ - | (((u64) (p)[1]) << 48) \ - | (((u64) (p)[2]) << 40) \ - | (((u64) (p)[3]) << 32) \ - | (((u64) (p)[4]) << 24) \ - | (((u64) (p)[5]) << 16) \ - | (((u64) (p)[6]) << 8) \ - | ((u64) (p)[7])) - +#define READ_UINT64(p) buf_get_be64(p) /* And the other, little-endian, byteorder */ -#define LE_READ_UINT64(p) \ -( (((u64) (p)[7]) << 56) \ - | (((u64) (p)[6]) << 48) \ - | (((u64) (p)[5]) << 40) \ - | (((u64) (p)[4]) << 32) \ - | (((u64) (p)[3]) << 24) \ - | (((u64) (p)[2]) << 16) \ - | (((u64) (p)[1]) << 8) \ - | ((u64) (p)[0])) - - - -#ifdef WORDS_BIGENDIAN -#define LE_SWAP32(v) \ - ((ROTL32(8, v) & 0x00FF00FFUL) | \ - (ROTL32(24, v) & 0xFF00FF00UL)) -#else -#define LE_SWAP32(v) (v) -#endif +#define LE_READ_UINT64(p) buf_get_le64(p) + +#define LE_SWAP32(v) le_bswap32(v) + #define QROUND(x0, x1, x2, x3) do { \ x1 ^= ROTL32(7, x0 + x3); \ x2 ^= ROTL32(9, x1 + x0); \ x3 ^= ROTL32(13, x2 + x1); \ x0 ^= ROTL32(18, x3 + x2); \ } while(0) static void _salsa20_core(u32 *dst, const u32 *src, unsigned rounds) { u32 x[SALSA20_INPUT_LENGTH]; unsigned i; assert ( (rounds & 1) == 0); for (i = 0; i < SALSA20_INPUT_LENGTH; i++) x[i] = LE_SWAP32(src[i]); for (i = 0; i < rounds;i += 2) { QROUND(x[0], x[4], x[8], x[12]); QROUND(x[5], x[9], x[13], x[1]); QROUND(x[10], x[14], x[2], x[6]); QROUND(x[15], x[3], x[7], x[11]); QROUND(x[0], x[1], x[2], x[3]); QROUND(x[5], x[6], x[7], x[4]); QROUND(x[10], x[11], x[8], x[9]); QROUND(x[15], x[12], x[13], x[14]); } for (i = 0; i < SALSA20_INPUT_LENGTH; i++) { u32 t = x[i] + LE_SWAP32(src[i]); dst[i] = LE_SWAP32(t); } } static void _scryptBlockMix (u32 r, unsigned char *B, unsigned char *tmp2) { u64 i; unsigned char *X = tmp2; unsigned char *Y = tmp2 + 64; #if 0 if (r == 1) { for (i = 0; i < 2 * r; i++) { size_t j; printf ("B[%d] = ", (int)i); for (j = 0; j < 64; j++) { if (j && !(j % 16)) printf ("\n "); printf (" %02x", B[i * 64 + j]); } putchar ('\n'); } } #endif /* X = B[2 * r - 1] */ memcpy (X, &B[(2 * r - 1) * 64], 64); /* for i = 0 to 2 * r - 1 do */ for (i = 0; i <= 2 * r - 1; i++) { /* T = X xor B[i] */ buf_xor(X, X, &B[i * 64], 64); /* X = Salsa (T) */ _salsa20_core ((u32*)X, (u32*)X, 8); /* Y[i] = X */ memcpy (&Y[i * 64], X, 64); } for (i = 0; i < r; i++) { memcpy (&B[i * 64], &Y[2 * i * 64], 64); memcpy (&B[(r + i) * 64], &Y[(2 * i + 1) * 64], 64); } #if 0 if (r==1) { for (i = 0; i < 2 * r; i++) { size_t j; printf ("B'[%d] =", (int)i); for (j = 0; j < 64; j++) { if (j && !(j % 16)) printf ("\n "); printf (" %02x", B[i * 64 + j]); } putchar ('\n'); } } #endif } static void _scryptROMix (u32 r, unsigned char *B, u64 N, unsigned char *tmp1, unsigned char *tmp2) { unsigned char *X = B, *T = B; u64 i; #if 0 if (r == 1) { printf ("B = "); for (i = 0; i < 128 * r; i++) { if (i && !(i % 16)) printf ("\n "); printf (" %02x", B[i]); } putchar ('\n'); } #endif /* for i = 0 to N - 1 do */ for (i = 0; i <= N - 1; i++) { /* V[i] = X */ memcpy (&tmp1[i * 128 * r], X, 128 * r); /* X = ScryptBlockMix (X) */ _scryptBlockMix (r, X, tmp2); } /* for i = 0 to N - 1 do */ for (i = 0; i <= N - 1; i++) { u64 j; /* j = Integerify (X) mod N */ j = LE_READ_UINT64 (&X[128 * r - 64]) % N; /* T = X xor V[j] */ buf_xor (T, T, &tmp1[j * 128 * r], 128 * r); /* X = scryptBlockMix (T) */ _scryptBlockMix (r, T, tmp2); } #if 0 if (r == 1) { printf ("B' ="); for (i = 0; i < 128 * r; i++) { if (i && !(i % 16)) printf ("\n "); printf (" %02x", B[i]); } putchar ('\n'); } #endif } /** */ gcry_err_code_t _gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen, int algo, int subalgo, const unsigned char *salt, size_t saltlen, unsigned long iterations, size_t dkLen, unsigned char *DK) { u64 N = subalgo; /* CPU/memory cost paramter. */ u32 r; /* Block size. */ u32 p = iterations; /* Parallelization parameter. */ gpg_err_code_t ec; u32 i; unsigned char *B = NULL; unsigned char *tmp1 = NULL; unsigned char *tmp2 = NULL; size_t r128; size_t nbytes; if (subalgo < 1 || !iterations) return GPG_ERR_INV_VALUE; if (algo == GCRY_KDF_SCRYPT) r = 8; else if (algo == 41) /* Hack to allow the use of all test vectors. */ r = 1; else return GPG_ERR_UNKNOWN_ALGORITHM; r128 = r * 128; if (r128 / 128 != r) return GPG_ERR_ENOMEM; nbytes = p * r128; if (r128 && nbytes / r128 != p) return GPG_ERR_ENOMEM; nbytes = N * r128; if (r128 && nbytes / r128 != N) return GPG_ERR_ENOMEM; nbytes = 64 + r128; if (nbytes < r128) return GPG_ERR_ENOMEM; B = gcry_malloc (p * r128); if (!B) { ec = gpg_err_code_from_syserror (); goto leave; } tmp1 = gcry_malloc (N * r128); if (!tmp1) { ec = gpg_err_code_from_syserror (); goto leave; } tmp2 = gcry_malloc (64 + r128); if (!tmp2) { ec = gpg_err_code_from_syserror (); goto leave; } ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, salt, saltlen, 1 /* iterations */, p * r128, B); for (i = 0; !ec && i < p; i++) _scryptROMix (r, &B[i * r128], N, tmp1, tmp2); for (i = 0; !ec && i < p; i++) ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, B, p * r128, 1 /* iterations */, dkLen, DK); leave: gcry_free (tmp2); gcry_free (tmp1); gcry_free (B); return ec; } #endif /* HAVE_U64_TYPEDEF */ diff --git a/cipher/seed.c b/cipher/seed.c index 1600c55e..474ccbaf 100644 --- a/cipher/seed.c +++ b/cipher/seed.c @@ -1,478 +1,475 @@ /* SEED for libgcrypt * Copyright (C) 2006 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * -- * This implementation was provided for libgcrypt in public domain * by Hye-Shik Chang , July 2006. */ #include #include #include #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" +#include "bufhelp.h" #define NUMKC 16 -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ - ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { (ct)[0] = (byte)((st) >> 24); \ - (ct)[1] = (byte)((st) >> 16); \ - (ct)[2] = (byte)((st) >> 8); \ - (ct)[3] = (byte)(st); } +#define GETU32(pt) buf_get_be32(pt) +#define PUTU32(ct, st) buf_put_be32(ct, st) union wordbuf { u32 w; byte b[4]; }; #ifdef WORDS_BIGENDIAN #define b0 b[3] #define b1 b[2] #define b2 b[1] #define b3 b[0] #else #define b0 b[0] #define b1 b[1] #define b2 b[2] #define b3 b[3] #endif static const char *selftest(void); typedef struct { u32 keyschedule[32]; } SEED_context; static const u32 SS0[256] = { 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038, 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330, 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298, }; static const u32 SS1[256] = { 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3, }; static const u32 SS2[256] = { 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808, 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303, 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a, }; static const u32 SS3[256] = { 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437, }; static const u32 KC[NUMKC] = { 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b, }; /* Perform the key setup. */ static gcry_err_code_t do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen) { static int initialized = 0; static const char *selftest_failed=0; u32 x1, x2, x3, x4; union wordbuf t0, t1; u32 *keyout = ctx->keyschedule; int i; if (!initialized) { initialized = 1; selftest_failed = selftest (); if( selftest_failed ) log_error ("%s\n", selftest_failed ); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen != 16) return GPG_ERR_INV_KEYLEN; x1 = GETU32 (key); x2 = GETU32 (key+4); x3 = GETU32 (key+8); x4 = GETU32 (key+12); for (i = 0; i < NUMKC; i++) { t0.w = x1 + x3 - KC[i]; t1.w = x2 + KC[i] - x4; *(keyout++) = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; *(keyout++) = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; if (i % 2 == 0) { t0.w = x1; x1 = (x1>>8) ^ (x2<<24); x2 = (x2>>8) ^ (t0.w<<24); } else { t0.w = x3; x3 = (x3<<8) ^ (x4>>24); x4 = (x4<<8) ^ (t0.w>>24); } } return 0; } static gcry_err_code_t seed_setkey (void *context, const byte *key, const unsigned keylen) { SEED_context *ctx = context; int rc = do_setkey (ctx, key, keylen); _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2); return rc; } #define OP(X1, X2, X3, X4, rbase) \ t0.w = X3 ^ ctx->keyschedule[rbase]; \ t1.w = X4 ^ ctx->keyschedule[rbase+1]; \ t1.w ^= t0.w; \ t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ t0.w += t1.w; \ t0.w = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; \ t1.w += t0.w; \ t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ t0.w += t1.w; \ X1 ^= t0.w; \ X2 ^= t1.w; /* Encrypt one block. inbuf and outbuf may be the same. */ static void do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf) { u32 x1, x2, x3, x4; union wordbuf t0, t1; x1 = GETU32 (inbuf); x2 = GETU32 (inbuf+4); x3 = GETU32 (inbuf+8); x4 = GETU32 (inbuf+12); OP (x1, x2, x3, x4, 0); OP (x3, x4, x1, x2, 2); OP (x1, x2, x3, x4, 4); OP (x3, x4, x1, x2, 6); OP (x1, x2, x3, x4, 8); OP (x3, x4, x1, x2, 10); OP (x1, x2, x3, x4, 12); OP (x3, x4, x1, x2, 14); OP (x1, x2, x3, x4, 16); OP (x3, x4, x1, x2, 18); OP (x1, x2, x3, x4, 20); OP (x3, x4, x1, x2, 22); OP (x1, x2, x3, x4, 24); OP (x3, x4, x1, x2, 26); OP (x1, x2, x3, x4, 28); OP (x3, x4, x1, x2, 30); PUTU32 (outbuf, x3); PUTU32 (outbuf+4, x4); PUTU32 (outbuf+8, x1); PUTU32 (outbuf+12, x2); } static unsigned int seed_encrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_encrypt (ctx, outbuf, inbuf); return /*burn_stack*/ (4*6); } /* Decrypt one block. inbuf and outbuf may be the same. */ static void do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf) { u32 x1, x2, x3, x4; union wordbuf t0, t1; x1 = GETU32 (inbuf); x2 = GETU32 (inbuf+4); x3 = GETU32 (inbuf+8); x4 = GETU32 (inbuf+12); OP (x1, x2, x3, x4, 30); OP (x3, x4, x1, x2, 28); OP (x1, x2, x3, x4, 26); OP (x3, x4, x1, x2, 24); OP (x1, x2, x3, x4, 22); OP (x3, x4, x1, x2, 20); OP (x1, x2, x3, x4, 18); OP (x3, x4, x1, x2, 16); OP (x1, x2, x3, x4, 14); OP (x3, x4, x1, x2, 12); OP (x1, x2, x3, x4, 10); OP (x3, x4, x1, x2, 8); OP (x1, x2, x3, x4, 6); OP (x3, x4, x1, x2, 4); OP (x1, x2, x3, x4, 2); OP (x3, x4, x1, x2, 0); PUTU32 (outbuf, x3); PUTU32 (outbuf+4, x4); PUTU32 (outbuf+8, x1); PUTU32 (outbuf+12, x2); } static unsigned int seed_decrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_decrypt (ctx, outbuf, inbuf); return /*burn_stack*/ (4*6); } /* Test a single encryption and decryption with each key size. */ static const char* selftest (void) { SEED_context ctx; byte scratch[16]; /* The test vector is taken from the appendix section B.3 of RFC4269. */ static const byte plaintext[16] = { 0x83, 0xA2, 0xF8, 0xA2, 0x88, 0x64, 0x1F, 0xB9, 0xA4, 0xE9, 0xA5, 0xCC, 0x2F, 0x13, 0x1C, 0x7D }; static const byte key[16] = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xE6, 0x1B, 0xE8, 0x5D, 0x74, 0xBF, 0xB3, 0xFD, 0x95, 0x61, 0x85 }; static const byte ciphertext[16] = { 0xEE, 0x54, 0xD1, 0x3E, 0xBC, 0xAE, 0x70, 0x6D, 0x22, 0x6B, 0xC3, 0x14, 0x2C, 0xD4, 0x0D, 0x4A, }; seed_setkey (&ctx, key, sizeof(key)); seed_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "SEED test encryption failed."; seed_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "SEED test decryption failed."; return NULL; } static gcry_cipher_oid_spec_t seed_oids[] = { { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB }, { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC }, { "1.2.410.200004.1.5", GCRY_CIPHER_MODE_CFB }, { "1.2.410.200004.1.6", GCRY_CIPHER_MODE_OFB }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_seed = { "SEED", NULL, seed_oids, 16, 128, sizeof (SEED_context), seed_setkey, seed_encrypt, seed_decrypt, }; diff --git a/cipher/serpent.c b/cipher/serpent.c index 72895ede..4720b9c6 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -1,1233 +1,1212 @@ /* serpent.c - Implementation of the Serpent encryption algorithm. * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" #include "cipher-selftest.h" /* USE_SSE2 indicates whether to compile with AMD64 SSE2 code. */ #undef USE_SSE2 #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) # define USE_SSE2 1 #endif /* USE_AVX2 indicates whether to compile with AMD64 AVX2 code. */ #undef USE_AVX2 #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) # if defined(ENABLE_AVX2_SUPPORT) # define USE_AVX2 1 # endif #endif /* Number of rounds per Serpent encrypt/decrypt operation. */ #define ROUNDS 32 /* Magic number, used during generating of the subkeys. */ #define PHI 0x9E3779B9 /* Serpent works on 128 bit blocks. */ typedef u32 serpent_block_t[4]; /* Serpent key, provided by the user. If the original key is shorter than 256 bits, it is padded. */ typedef u32 serpent_key_t[8]; /* The key schedule consists of 33 128 bit subkeys. */ typedef u32 serpent_subkeys_t[ROUNDS + 1][4]; /* A Serpent context. */ typedef struct serpent_context { serpent_subkeys_t keys; /* Generated subkeys. */ #ifdef USE_AVX2 int use_avx2; #endif } serpent_context_t; #ifdef USE_SSE2 /* Assembler implementations of Serpent using SSE2. Process 8 block in parallel. */ extern void _gcry_serpent_sse2_ctr_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr); extern void _gcry_serpent_sse2_cbc_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); extern void _gcry_serpent_sse2_cfb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); #endif #ifdef USE_AVX2 /* Assembler implementations of Serpent using SSE2. Process 16 block in parallel. */ extern void _gcry_serpent_avx2_ctr_enc(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *ctr); extern void _gcry_serpent_avx2_cbc_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); extern void _gcry_serpent_avx2_cfb_dec(serpent_context_t *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); #endif /* A prototype. */ static const char *serpent_test (void); -#define byte_swap_32(x) \ - (0 \ - | (((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ - | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) - /* * These are the S-Boxes of Serpent from following research paper. * * D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference, * (New York, New York, USA), p. 317–329, National Institute of Standards and * Technology, 2000. * * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf * */ #define SBOX0(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r3 ^= r0; r4 = r1; \ r1 &= r3; r4 ^= r2; \ r1 ^= r0; r0 |= r3; \ r0 ^= r4; r4 ^= r3; \ r3 ^= r2; r2 |= r1; \ r2 ^= r4; r4 = ~r4; \ r4 |= r1; r1 ^= r3; \ r1 ^= r4; r3 |= r0; \ r1 ^= r3; r4 ^= r3; \ \ w = r1; x = r4; y = r2; z = r0; \ } #define SBOX0_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r2 = ~r2; r4 = r1; \ r1 |= r0; r4 = ~r4; \ r1 ^= r2; r2 |= r4; \ r1 ^= r3; r0 ^= r4; \ r2 ^= r0; r0 &= r3; \ r4 ^= r0; r0 |= r1; \ r0 ^= r2; r3 ^= r4; \ r2 ^= r1; r3 ^= r0; \ r3 ^= r1; \ r2 &= r3; \ r4 ^= r2; \ \ w = r0; x = r4; y = r1; z = r3; \ } #define SBOX1(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r0 = ~r0; r2 = ~r2; \ r4 = r0; r0 &= r1; \ r2 ^= r0; r0 |= r3; \ r3 ^= r2; r1 ^= r0; \ r0 ^= r4; r4 |= r1; \ r1 ^= r3; r2 |= r0; \ r2 &= r4; r0 ^= r1; \ r1 &= r2; \ r1 ^= r0; r0 &= r2; \ r0 ^= r4; \ \ w = r2; x = r0; y = r3; z = r1; \ } #define SBOX1_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r1; r1 ^= r3; \ r3 &= r1; r4 ^= r2; \ r3 ^= r0; r0 |= r1; \ r2 ^= r3; r0 ^= r4; \ r0 |= r2; r1 ^= r3; \ r0 ^= r1; r1 |= r3; \ r1 ^= r0; r4 = ~r4; \ r4 ^= r1; r1 |= r0; \ r1 ^= r0; \ r1 |= r4; \ r3 ^= r1; \ \ w = r4; x = r0; y = r3; z = r2; \ } #define SBOX2(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r0; r0 &= r2; \ r0 ^= r3; r2 ^= r1; \ r2 ^= r0; r3 |= r4; \ r3 ^= r1; r4 ^= r2; \ r1 = r3; r3 |= r4; \ r3 ^= r0; r0 &= r1; \ r4 ^= r0; r1 ^= r3; \ r1 ^= r4; r4 = ~r4; \ \ w = r2; x = r3; y = r1; z = r4; \ } #define SBOX2_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r2 ^= r3; r3 ^= r0; \ r4 = r3; r3 &= r2; \ r3 ^= r1; r1 |= r2; \ r1 ^= r4; r4 &= r3; \ r2 ^= r3; r4 &= r0; \ r4 ^= r2; r2 &= r1; \ r2 |= r0; r3 = ~r3; \ r2 ^= r3; r0 ^= r3; \ r0 &= r1; r3 ^= r4; \ r3 ^= r0; \ \ w = r1; x = r4; y = r2; z = r3; \ } #define SBOX3(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r0; r0 |= r3; \ r3 ^= r1; r1 &= r4; \ r4 ^= r2; r2 ^= r3; \ r3 &= r0; r4 |= r1; \ r3 ^= r4; r0 ^= r1; \ r4 &= r0; r1 ^= r3; \ r4 ^= r2; r1 |= r0; \ r1 ^= r2; r0 ^= r3; \ r2 = r1; r1 |= r3; \ r1 ^= r0; \ \ w = r1; x = r2; y = r3; z = r4; \ } #define SBOX3_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r2; r2 ^= r1; \ r0 ^= r2; r4 &= r2; \ r4 ^= r0; r0 &= r1; \ r1 ^= r3; r3 |= r4; \ r2 ^= r3; r0 ^= r3; \ r1 ^= r4; r3 &= r2; \ r3 ^= r1; r1 ^= r0; \ r1 |= r2; r0 ^= r3; \ r1 ^= r4; \ r0 ^= r1; \ \ w = r2; x = r1; y = r3; z = r0; \ } #define SBOX4(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r1 ^= r3; r3 = ~r3; \ r2 ^= r3; r3 ^= r0; \ r4 = r1; r1 &= r3; \ r1 ^= r2; r4 ^= r3; \ r0 ^= r4; r2 &= r4; \ r2 ^= r0; r0 &= r1; \ r3 ^= r0; r4 |= r1; \ r4 ^= r0; r0 |= r3; \ r0 ^= r2; r2 &= r3; \ r0 = ~r0; r4 ^= r2; \ \ w = r1; x = r4; y = r0; z = r3; \ } #define SBOX4_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r2; r2 &= r3; \ r2 ^= r1; r1 |= r3; \ r1 &= r0; r4 ^= r2; \ r4 ^= r1; r1 &= r2; \ r0 = ~r0; r3 ^= r4; \ r1 ^= r3; r3 &= r0; \ r3 ^= r2; r0 ^= r1; \ r2 &= r0; r3 ^= r0; \ r2 ^= r4; \ r2 |= r3; r3 ^= r0; \ r2 ^= r1; \ \ w = r0; x = r3; y = r2; z = r4; \ } #define SBOX5(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r0 ^= r1; r1 ^= r3; \ r3 = ~r3; r4 = r1; \ r1 &= r0; r2 ^= r3; \ r1 ^= r2; r2 |= r4; \ r4 ^= r3; r3 &= r1; \ r3 ^= r0; r4 ^= r1; \ r4 ^= r2; r2 ^= r0; \ r0 &= r3; r2 = ~r2; \ r0 ^= r4; r4 |= r3; \ r2 ^= r4; \ \ w = r1; x = r3; y = r0; z = r2; \ } #define SBOX5_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r1 = ~r1; r4 = r3; \ r2 ^= r1; r3 |= r0; \ r3 ^= r2; r2 |= r1; \ r2 &= r0; r4 ^= r3; \ r2 ^= r4; r4 |= r0; \ r4 ^= r1; r1 &= r2; \ r1 ^= r3; r4 ^= r2; \ r3 &= r4; r4 ^= r1; \ r3 ^= r4; r4 = ~r4; \ r3 ^= r0; \ \ w = r1; x = r4; y = r3; z = r2; \ } #define SBOX6(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r2 = ~r2; r4 = r3; \ r3 &= r0; r0 ^= r4; \ r3 ^= r2; r2 |= r4; \ r1 ^= r3; r2 ^= r0; \ r0 |= r1; r2 ^= r1; \ r4 ^= r0; r0 |= r3; \ r0 ^= r2; r4 ^= r3; \ r4 ^= r0; r3 = ~r3; \ r2 &= r4; \ r2 ^= r3; \ \ w = r0; x = r1; y = r4; z = r2; \ } #define SBOX6_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r0 ^= r2; r4 = r2; \ r2 &= r0; r4 ^= r3; \ r2 = ~r2; r3 ^= r1; \ r2 ^= r3; r4 |= r0; \ r0 ^= r2; r3 ^= r4; \ r4 ^= r1; r1 &= r3; \ r1 ^= r0; r0 ^= r3; \ r0 |= r2; r3 ^= r1; \ r4 ^= r0; \ \ w = r1; x = r2; y = r4; z = r3; \ } #define SBOX7(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r1; r1 |= r2; \ r1 ^= r3; r4 ^= r2; \ r2 ^= r1; r3 |= r4; \ r3 &= r0; r4 ^= r2; \ r3 ^= r1; r1 |= r4; \ r1 ^= r0; r0 |= r4; \ r0 ^= r2; r1 ^= r4; \ r2 ^= r1; r1 &= r0; \ r1 ^= r4; r2 = ~r2; \ r2 |= r0; \ r4 ^= r2; \ \ w = r4; x = r3; y = r1; z = r0; \ } #define SBOX7_INVERSE(r0, r1, r2, r3, w, x, y, z) \ { \ u32 r4; \ \ r4 = r2; r2 ^= r0; \ r0 &= r3; r4 |= r3; \ r2 = ~r2; r3 ^= r1; \ r1 |= r0; r0 ^= r2; \ r2 &= r4; r3 &= r4; \ r1 ^= r2; r2 ^= r0; \ r0 |= r2; r4 ^= r1; \ r0 ^= r3; r3 ^= r4; \ r4 |= r0; r3 ^= r2; \ r4 ^= r2; \ \ w = r3; x = r0; y = r1; z = r4; \ } /* XOR BLOCK1 into BLOCK0. */ #define BLOCK_XOR(block0, block1) \ { \ block0[0] ^= block1[0]; \ block0[1] ^= block1[1]; \ block0[2] ^= block1[2]; \ block0[3] ^= block1[3]; \ } /* Copy BLOCK_SRC to BLOCK_DST. */ #define BLOCK_COPY(block_dst, block_src) \ { \ block_dst[0] = block_src[0]; \ block_dst[1] = block_src[1]; \ block_dst[2] = block_src[2]; \ block_dst[3] = block_src[3]; \ } /* Apply SBOX number WHICH to to the block found in ARRAY0 at index INDEX, writing the output to the block found in ARRAY1 at index INDEX. */ #define SBOX(which, array0, array1, index) \ SBOX##which (array0[index + 0], array0[index + 1], \ array0[index + 2], array0[index + 3], \ array1[index + 0], array1[index + 1], \ array1[index + 2], array1[index + 3]); /* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at index INDEX, writing the output to the block found in ARRAY1 at index INDEX. */ #define SBOX_INVERSE(which, array0, array1, index) \ SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \ array0[index + 2], array0[index + 3], \ array1[index + 0], array1[index + 1], \ array1[index + 2], array1[index + 3]); /* Apply the linear transformation to BLOCK. */ #define LINEAR_TRANSFORMATION(block) \ { \ block[0] = rol (block[0], 13); \ block[2] = rol (block[2], 3); \ block[1] = block[1] ^ block[0] ^ block[2]; \ block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ block[1] = rol (block[1], 1); \ block[3] = rol (block[3], 7); \ block[0] = block[0] ^ block[1] ^ block[3]; \ block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ block[0] = rol (block[0], 5); \ block[2] = rol (block[2], 22); \ } /* Apply the inverse linear transformation to BLOCK. */ #define LINEAR_TRANSFORMATION_INVERSE(block) \ { \ block[2] = ror (block[2], 22); \ block[0] = ror (block[0] , 5); \ block[2] = block[2] ^ block[3] ^ (block[1] << 7); \ block[0] = block[0] ^ block[1] ^ block[3]; \ block[3] = ror (block[3], 7); \ block[1] = ror (block[1], 1); \ block[3] = block[3] ^ block[2] ^ (block[0] << 3); \ block[1] = block[1] ^ block[0] ^ block[2]; \ block[2] = ror (block[2], 3); \ block[0] = ror (block[0], 13); \ } /* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. This macro increments `round'. */ #define ROUND(which, subkeys, block, block_tmp) \ { \ BLOCK_XOR (block, subkeys[round]); \ round++; \ SBOX (which, block, block_tmp, 0); \ LINEAR_TRANSFORMATION (block_tmp); \ BLOCK_COPY (block, block_tmp); \ } /* Apply the last Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. The result will be stored in BLOCK_TMP. This macro increments `round'. */ #define ROUND_LAST(which, subkeys, block, block_tmp) \ { \ BLOCK_XOR (block, subkeys[round]); \ round++; \ SBOX (which, block, block_tmp, 0); \ BLOCK_XOR (block_tmp, subkeys[round]); \ round++; \ } /* Apply an inverse Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. This macro increments `round'. */ #define ROUND_INVERSE(which, subkey, block, block_tmp) \ { \ LINEAR_TRANSFORMATION_INVERSE (block); \ SBOX_INVERSE (which, block, block_tmp, 0); \ BLOCK_XOR (block_tmp, subkey[round]); \ round--; \ BLOCK_COPY (block, block_tmp); \ } /* Apply the first Serpent round to BLOCK, using the SBOX number WHICH and the subkeys contained in SUBKEYS. Use BLOCK_TMP as temporary storage. The result will be stored in BLOCK_TMP. This macro increments `round'. */ #define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \ { \ BLOCK_XOR (block, subkeys[round]); \ round--; \ SBOX_INVERSE (which, block, block_tmp, 0); \ BLOCK_XOR (block_tmp, subkeys[round]); \ round--; \ } /* Convert the user provided key KEY of KEY_LENGTH bytes into the internally used format. */ static void serpent_key_prepare (const byte *key, unsigned int key_length, serpent_key_t key_prepared) { int i; /* Copy key. */ - memcpy (key_prepared, key, key_length); key_length /= 4; -#ifdef WORDS_BIGENDIAN for (i = 0; i < key_length; i++) - key_prepared[i] = byte_swap_32 (key_prepared[i]); -#else - i = key_length; -#endif + key_prepared[i] = buf_get_le32 (key + i * 4); + if (i < 8) { /* Key must be padded according to the Serpent specification. */ key_prepared[i] = 0x00000001; for (i++; i < 8; i++) key_prepared[i] = 0; } } /* Derive the 33 subkeys from KEY and store them in SUBKEYS. */ static void serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) { u32 w_real[140]; /* The `prekey'. */ u32 k[132]; u32 *w = &w_real[8]; int i, j; /* Initialize with key values. */ for (i = 0; i < 8; i++) w[i - 8] = key[i]; /* Expand to intermediate key using the affine recurrence. */ for (i = 0; i < 132; i++) w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); /* Calculate subkeys via S-Boxes, in bitslice mode. */ SBOX (3, w, k, 0); SBOX (2, w, k, 4); SBOX (1, w, k, 8); SBOX (0, w, k, 12); SBOX (7, w, k, 16); SBOX (6, w, k, 20); SBOX (5, w, k, 24); SBOX (4, w, k, 28); SBOX (3, w, k, 32); SBOX (2, w, k, 36); SBOX (1, w, k, 40); SBOX (0, w, k, 44); SBOX (7, w, k, 48); SBOX (6, w, k, 52); SBOX (5, w, k, 56); SBOX (4, w, k, 60); SBOX (3, w, k, 64); SBOX (2, w, k, 68); SBOX (1, w, k, 72); SBOX (0, w, k, 76); SBOX (7, w, k, 80); SBOX (6, w, k, 84); SBOX (5, w, k, 88); SBOX (4, w, k, 92); SBOX (3, w, k, 96); SBOX (2, w, k, 100); SBOX (1, w, k, 104); SBOX (0, w, k, 108); SBOX (7, w, k, 112); SBOX (6, w, k, 116); SBOX (5, w, k, 120); SBOX (4, w, k, 124); SBOX (3, w, k, 128); /* Renumber subkeys. */ for (i = 0; i < ROUNDS + 1; i++) for (j = 0; j < 4; j++) subkeys[i][j] = k[4 * i + j]; } /* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ static void serpent_setkey_internal (serpent_context_t *context, const byte *key, unsigned int key_length) { serpent_key_t key_prepared; serpent_key_prepare (key, key_length, key_prepared); serpent_subkeys_generate (key_prepared, context->keys); #ifdef USE_AVX2 context->use_avx2 = 0; if ((_gcry_get_hw_features () & HWF_INTEL_AVX2)) { context->use_avx2 = 1; } #endif _gcry_burn_stack (272 * sizeof (u32)); } /* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ static gcry_err_code_t serpent_setkey (void *ctx, const byte *key, unsigned int key_length) { serpent_context_t *context = ctx; static const char *serpent_test_ret; static int serpent_init_done; gcry_err_code_t ret = GPG_ERR_NO_ERROR; if (! serpent_init_done) { /* Execute a self-test the first time, Serpent is used. */ serpent_init_done = 1; serpent_test_ret = serpent_test (); if (serpent_test_ret) log_error ("Serpent test failure: %s\n", serpent_test_ret); } if (serpent_test_ret) ret = GPG_ERR_SELFTEST_FAILED; else { serpent_setkey_internal (context, key, key_length); _gcry_burn_stack (sizeof (serpent_key_t)); } return ret; } static void serpent_encrypt_internal (serpent_context_t *context, const byte *input, byte *output) { serpent_block_t b, b_next; int round = 0; - memcpy (b, input, sizeof (b)); -#ifdef WORDS_BIGENDIAN - b[0] = byte_swap_32 (b[0]); - b[1] = byte_swap_32 (b[1]); - b[2] = byte_swap_32 (b[2]); - b[3] = byte_swap_32 (b[3]); -#endif + b[0] = buf_get_le32 (input + 0); + b[1] = buf_get_le32 (input + 4); + b[2] = buf_get_le32 (input + 8); + b[3] = buf_get_le32 (input + 12); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND (7, context->keys, b, b_next); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND (7, context->keys, b, b_next); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND (7, context->keys, b, b_next); ROUND (0, context->keys, b, b_next); ROUND (1, context->keys, b, b_next); ROUND (2, context->keys, b, b_next); ROUND (3, context->keys, b, b_next); ROUND (4, context->keys, b, b_next); ROUND (5, context->keys, b, b_next); ROUND (6, context->keys, b, b_next); ROUND_LAST (7, context->keys, b, b_next); -#ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (b_next[0]); - b_next[1] = byte_swap_32 (b_next[1]); - b_next[2] = byte_swap_32 (b_next[2]); - b_next[3] = byte_swap_32 (b_next[3]); -#endif - memcpy (output, b_next, sizeof (b_next)); + buf_put_le32 (output + 0, b_next[0]); + buf_put_le32 (output + 4, b_next[1]); + buf_put_le32 (output + 8, b_next[2]); + buf_put_le32 (output + 12, b_next[3]); } static void serpent_decrypt_internal (serpent_context_t *context, const byte *input, byte *output) { serpent_block_t b, b_next; int round = ROUNDS; - memcpy (b_next, input, sizeof (b)); -#ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (b_next[0]); - b_next[1] = byte_swap_32 (b_next[1]); - b_next[2] = byte_swap_32 (b_next[2]); - b_next[3] = byte_swap_32 (b_next[3]); -#endif + b_next[0] = buf_get_le32 (input + 0); + b_next[1] = buf_get_le32 (input + 4); + b_next[2] = buf_get_le32 (input + 8); + b_next[3] = buf_get_le32 (input + 12); ROUND_FIRST_INVERSE (7, context->keys, b_next, b); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); ROUND_INVERSE (7, context->keys, b, b_next); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); ROUND_INVERSE (7, context->keys, b, b_next); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); ROUND_INVERSE (7, context->keys, b, b_next); ROUND_INVERSE (6, context->keys, b, b_next); ROUND_INVERSE (5, context->keys, b, b_next); ROUND_INVERSE (4, context->keys, b, b_next); ROUND_INVERSE (3, context->keys, b, b_next); ROUND_INVERSE (2, context->keys, b, b_next); ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); -#ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (b_next[0]); - b_next[1] = byte_swap_32 (b_next[1]); - b_next[2] = byte_swap_32 (b_next[2]); - b_next[3] = byte_swap_32 (b_next[3]); -#endif - memcpy (output, b_next, sizeof (b_next)); + buf_put_le32 (output + 0, b_next[0]); + buf_put_le32 (output + 4, b_next[1]); + buf_put_le32 (output + 8, b_next[2]); + buf_put_le32 (output + 12, b_next[3]); } static unsigned int serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_encrypt_internal (context, buffer_in, buffer_out); return /*burn_stack*/ (2 * sizeof (serpent_block_t)); } static unsigned int serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; serpent_decrypt_internal (context, buffer_in, buffer_out); return /*burn_stack*/ (2 * sizeof (serpent_block_t)); } /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size sizeof(serpent_block_t). */ void _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[sizeof(serpent_block_t)]; int burn_stack_depth = 2 * sizeof (serpent_block_t); int i; #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_serpent_avx2_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic/sse2 code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_sse2_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ serpent_encrypt_internal(ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ buf_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); /* Increment the counter. */ for (i = sizeof(serpent_block_t); i > 0; i--) { ctr[i-1]++; if (ctr[i-1]) break; } } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_serpent_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[sizeof(serpent_block_t)]; int burn_stack_depth = 2 * sizeof (serpent_block_t); #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_serpent_avx2_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic/sse2 code to handle smaller chunks... */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_sse2_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* We need to save INBUF away because it may be identical to OUTBUF. */ memcpy(savebuf, inbuf, sizeof(serpent_block_t)); serpent_decrypt_internal (ctx, inbuf, outbuf); buf_xor(outbuf, outbuf, iv, sizeof(serpent_block_t)); memcpy(iv, savebuf, sizeof(serpent_block_t)); inbuf += sizeof(serpent_block_t); outbuf += sizeof(serpent_block_t); } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_serpent_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 2 * sizeof (serpent_block_t); #ifdef USE_AVX2 if (ctx->use_avx2) { int did_use_avx2 = 0; /* Process data in 16 block chunks. */ while (nblocks >= 16) { _gcry_serpent_avx2_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 16; outbuf += 16 * sizeof(serpent_block_t); inbuf += 16 * sizeof(serpent_block_t); did_use_avx2 = 1; } if (did_use_avx2) { /* serpent-avx2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic/sse2 code to handle smaller chunks... */ } #endif #ifdef USE_SSE2 { int did_use_sse2 = 0; /* Process data in 8 block chunks. */ while (nblocks >= 8) { _gcry_serpent_sse2_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 8; outbuf += 8 * sizeof(serpent_block_t); inbuf += 8 * sizeof(serpent_block_t); did_use_sse2 = 1; } if (did_use_sse2) { /* serpent-sse2 assembly code does not use stack */ if (nblocks == 0) burn_stack_depth = 0; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { serpent_encrypt_internal(ctx, iv, iv); buf_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); } _gcry_burn_stack(burn_stack_depth); } /* Run the self-tests for SERPENT-CTR-128, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char* selftest_ctr_128 (void) { const int nblocks = 16+1; const int blocksize = sizeof(serpent_block_t); const int context_size = sizeof(serpent_context_t); return _gcry_selftest_helper_ctr("SERPENT", &serpent_setkey, &serpent_encrypt, &_gcry_serpent_ctr_enc, nblocks, blocksize, context_size); } /* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cbc_128 (void) { const int nblocks = 16+2; const int blocksize = sizeof(serpent_block_t); const int context_size = sizeof(serpent_context_t); return _gcry_selftest_helper_cbc("SERPENT", &serpent_setkey, &serpent_encrypt, &_gcry_serpent_cbc_dec, nblocks, blocksize, context_size); } /* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption. Returns NULL on success. */ static const char* selftest_cfb_128 (void) { const int nblocks = 16+2; const int blocksize = sizeof(serpent_block_t); const int context_size = sizeof(serpent_context_t); return _gcry_selftest_helper_cfb("SERPENT", &serpent_setkey, &serpent_encrypt, &_gcry_serpent_cfb_dec, nblocks, blocksize, context_size); } /* Serpent test. */ static const char * serpent_test (void) { serpent_context_t context; unsigned char scratch[16]; unsigned int i; const char *r; static struct test { int key_length; unsigned char key[32]; unsigned char text_plain[16]; unsigned char text_cipher[16]; } test_data[] = { { 16, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E", "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D" }, { 24, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00", "\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E", "\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9" }, { 32, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E", "\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B" }, { 32, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00", "\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C" }, { 0 }, }; for (i = 0; test_data[i].key_length; i++) { serpent_setkey_internal (&context, test_data[i].key, test_data[i].key_length); serpent_encrypt_internal (&context, test_data[i].text_plain, scratch); if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) switch (test_data[i].key_length) { case 16: return "Serpent-128 test encryption failed."; case 24: return "Serpent-192 test encryption failed."; case 32: return "Serpent-256 test encryption failed."; } serpent_decrypt_internal (&context, test_data[i].text_cipher, scratch); if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) switch (test_data[i].key_length) { case 16: return "Serpent-128 test decryption failed."; case 24: return "Serpent-192 test decryption failed."; case 32: return "Serpent-256 test decryption failed."; } } if ( (r = selftest_ctr_128 ()) ) return r; if ( (r = selftest_cbc_128 ()) ) return r; if ( (r = selftest_cfb_128 ()) ) return r; return NULL; } /* "SERPENT" is an alias for "SERPENT128". */ static const char *cipher_spec_serpent128_aliases[] = { "SERPENT", NULL }; gcry_cipher_spec_t _gcry_cipher_spec_serpent128 = { "SERPENT128", cipher_spec_serpent128_aliases, NULL, 16, 128, sizeof (serpent_context_t), serpent_setkey, serpent_encrypt, serpent_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_serpent192 = { "SERPENT192", NULL, NULL, 16, 192, sizeof (serpent_context_t), serpent_setkey, serpent_encrypt, serpent_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_serpent256 = { "SERPENT256", NULL, NULL, 16, 256, sizeof (serpent_context_t), serpent_setkey, serpent_encrypt, serpent_decrypt }; diff --git a/cipher/sha1.c b/cipher/sha1.c index 382bce83..aef9f059 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -1,445 +1,421 @@ /* sha1.c - SHA1 hash function * Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* Test vectors: * * "abc" * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D * * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 */ #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* A macro to test whether P is properly aligned for an u32 type. Note that config.h provides a suitable replacement for uintptr_t if it does not exist in stdint.h. */ /* #if __GNUC__ >= 2 */ /* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % __alignof__ (u32))) */ /* #else */ /* # define U32_ALIGNED_P(p) (!(((uintptr_t)p) % sizeof (u32))) */ /* #endif */ typedef struct { gcry_md_block_ctx_t bctx; u32 h0,h1,h2,h3,h4; } SHA1_CONTEXT; static unsigned int transform (void *c, const unsigned char *data); static void sha1_init (void *context) { SHA1_CONTEXT *hd = context; hd->h0 = 0x67452301; hd->h1 = 0xefcdab89; hd->h2 = 0x98badcfe; hd->h3 = 0x10325476; hd->h4 = 0xc3d2e1f0; hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; } /* Round function macros. */ #define K1 0x5A827999L #define K2 0x6ED9EBA1L #define K3 0x8F1BBCDCL #define K4 0xCA62C1D6L #define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) #define F2(x,y,z) ( x ^ y ^ z ) #define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) #define F4(x,y,z) ( x ^ y ^ z ) #define M(i) ( tm = x[ i &0x0f] \ ^ x[(i-14)&0x0f] \ ^ x[(i-8) &0x0f] \ ^ x[(i-3) &0x0f], \ (x[i&0x0f] = rol(tm, 1))) #define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + f( b, c, d ) \ + k \ + m; \ b = rol( b, 30 ); \ } while(0) /* * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA. */ static unsigned int transform (void *ctx, const unsigned char *data) { SHA1_CONTEXT *hd = ctx; + const u32 *idata = (const void *)data; register u32 a, b, c, d, e; /* Local copies of the chaining variables. */ register u32 tm; /* Helper. */ u32 x[16]; /* The array we work on. */ -#ifdef WORDS_BIGENDIAN - memcpy (x, data, 64); - data += 64; -#else - { - int i; - unsigned char *p; - - for(i=0, p=(unsigned char*)x; i < 16; i++, p += 4 ) - { - p[3] = *data++; - p[2] = *data++; - p[1] = *data++; - p[0] = *data++; - } - } -#endif +#define I(i) (x[i] = buf_get_be32(idata + i)) + /* Get the values of the chaining variables. */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; /* Transform. */ - R( a, b, c, d, e, F1, K1, x[ 0] ); - R( e, a, b, c, d, F1, K1, x[ 1] ); - R( d, e, a, b, c, F1, K1, x[ 2] ); - R( c, d, e, a, b, F1, K1, x[ 3] ); - R( b, c, d, e, a, F1, K1, x[ 4] ); - R( a, b, c, d, e, F1, K1, x[ 5] ); - R( e, a, b, c, d, F1, K1, x[ 6] ); - R( d, e, a, b, c, F1, K1, x[ 7] ); - R( c, d, e, a, b, F1, K1, x[ 8] ); - R( b, c, d, e, a, F1, K1, x[ 9] ); - R( a, b, c, d, e, F1, K1, x[10] ); - R( e, a, b, c, d, F1, K1, x[11] ); - R( d, e, a, b, c, F1, K1, x[12] ); - R( c, d, e, a, b, F1, K1, x[13] ); - R( b, c, d, e, a, F1, K1, x[14] ); - R( a, b, c, d, e, F1, K1, x[15] ); + R( a, b, c, d, e, F1, K1, I( 0) ); + R( e, a, b, c, d, F1, K1, I( 1) ); + R( d, e, a, b, c, F1, K1, I( 2) ); + R( c, d, e, a, b, F1, K1, I( 3) ); + R( b, c, d, e, a, F1, K1, I( 4) ); + R( a, b, c, d, e, F1, K1, I( 5) ); + R( e, a, b, c, d, F1, K1, I( 6) ); + R( d, e, a, b, c, F1, K1, I( 7) ); + R( c, d, e, a, b, F1, K1, I( 8) ); + R( b, c, d, e, a, F1, K1, I( 9) ); + R( a, b, c, d, e, F1, K1, I(10) ); + R( e, a, b, c, d, F1, K1, I(11) ); + R( d, e, a, b, c, F1, K1, I(12) ); + R( c, d, e, a, b, F1, K1, I(13) ); + R( b, c, d, e, a, F1, K1, I(14) ); + R( a, b, c, d, e, F1, K1, I(15) ); R( e, a, b, c, d, F1, K1, M(16) ); R( d, e, a, b, c, F1, K1, M(17) ); R( c, d, e, a, b, F1, K1, M(18) ); R( b, c, d, e, a, F1, K1, M(19) ); R( a, b, c, d, e, F2, K2, M(20) ); R( e, a, b, c, d, F2, K2, M(21) ); R( d, e, a, b, c, F2, K2, M(22) ); R( c, d, e, a, b, F2, K2, M(23) ); R( b, c, d, e, a, F2, K2, M(24) ); R( a, b, c, d, e, F2, K2, M(25) ); R( e, a, b, c, d, F2, K2, M(26) ); R( d, e, a, b, c, F2, K2, M(27) ); R( c, d, e, a, b, F2, K2, M(28) ); R( b, c, d, e, a, F2, K2, M(29) ); R( a, b, c, d, e, F2, K2, M(30) ); R( e, a, b, c, d, F2, K2, M(31) ); R( d, e, a, b, c, F2, K2, M(32) ); R( c, d, e, a, b, F2, K2, M(33) ); R( b, c, d, e, a, F2, K2, M(34) ); R( a, b, c, d, e, F2, K2, M(35) ); R( e, a, b, c, d, F2, K2, M(36) ); R( d, e, a, b, c, F2, K2, M(37) ); R( c, d, e, a, b, F2, K2, M(38) ); R( b, c, d, e, a, F2, K2, M(39) ); R( a, b, c, d, e, F3, K3, M(40) ); R( e, a, b, c, d, F3, K3, M(41) ); R( d, e, a, b, c, F3, K3, M(42) ); R( c, d, e, a, b, F3, K3, M(43) ); R( b, c, d, e, a, F3, K3, M(44) ); R( a, b, c, d, e, F3, K3, M(45) ); R( e, a, b, c, d, F3, K3, M(46) ); R( d, e, a, b, c, F3, K3, M(47) ); R( c, d, e, a, b, F3, K3, M(48) ); R( b, c, d, e, a, F3, K3, M(49) ); R( a, b, c, d, e, F3, K3, M(50) ); R( e, a, b, c, d, F3, K3, M(51) ); R( d, e, a, b, c, F3, K3, M(52) ); R( c, d, e, a, b, F3, K3, M(53) ); R( b, c, d, e, a, F3, K3, M(54) ); R( a, b, c, d, e, F3, K3, M(55) ); R( e, a, b, c, d, F3, K3, M(56) ); R( d, e, a, b, c, F3, K3, M(57) ); R( c, d, e, a, b, F3, K3, M(58) ); R( b, c, d, e, a, F3, K3, M(59) ); R( a, b, c, d, e, F4, K4, M(60) ); R( e, a, b, c, d, F4, K4, M(61) ); R( d, e, a, b, c, F4, K4, M(62) ); R( c, d, e, a, b, F4, K4, M(63) ); R( b, c, d, e, a, F4, K4, M(64) ); R( a, b, c, d, e, F4, K4, M(65) ); R( e, a, b, c, d, F4, K4, M(66) ); R( d, e, a, b, c, F4, K4, M(67) ); R( c, d, e, a, b, F4, K4, M(68) ); R( b, c, d, e, a, F4, K4, M(69) ); R( a, b, c, d, e, F4, K4, M(70) ); R( e, a, b, c, d, F4, K4, M(71) ); R( d, e, a, b, c, F4, K4, M(72) ); R( c, d, e, a, b, F4, K4, M(73) ); R( b, c, d, e, a, F4, K4, M(74) ); R( a, b, c, d, e, F4, K4, M(75) ); R( e, a, b, c, d, F4, K4, M(76) ); R( d, e, a, b, c, F4, K4, M(77) ); R( c, d, e, a, b, F4, K4, M(78) ); R( b, c, d, e, a, F4, K4, M(79) ); /* Update the chaining variables. */ hd->h0 += a; hd->h1 += b; hd->h2 += c; hd->h3 += d; hd->h4 += e; return /* burn_stack */ 88+4*sizeof(void*); } /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the * handle will the destroy the returned buffer. * Returns: 20 bytes representing the digest. */ static void sha1_final(void *context) { SHA1_CONTEXT *hd = context; u32 t, msb, lsb; unsigned char *p; unsigned int burn; _gcry_md_block_write (hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->bctx.count < 56 ) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ while( hd->bctx.count < 56 ) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ while( hd->bctx.count < 64 ) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write(hd, NULL, 0); /* flush */; memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = msb >> 24; - hd->bctx.buf[57] = msb >> 16; - hd->bctx.buf[58] = msb >> 8; - hd->bctx.buf[59] = msb ; - hd->bctx.buf[60] = lsb >> 24; - hd->bctx.buf[61] = lsb >> 16; - hd->bctx.buf[62] = lsb >> 8; - hd->bctx.buf[63] = lsb ; + buf_put_be32(hd->bctx.buf + 56, msb); + buf_put_be32(hd->bctx.buf + 60, lsb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) -#endif +#define X(a) do { *(u32*)p = be_bswap32(hd->h##a) ; p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); #undef X } static unsigned char * sha1_read( void *context ) { SHA1_CONTEXT *hd = context; return hd->bctx.buf; } /**************** * Shortcut functions which puts the hash value of the supplied buffer * into outbuf which must have a size of 20 bytes. */ void _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) { SHA1_CONTEXT hd; sha1_init (&hd); _gcry_md_block_write (&hd, buffer, length); sha1_final (&hd); memcpy (outbuf, hd.bctx.buf, 20); } /* Variant of the above shortcut function using a multiple buffers. */ void _gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA1_CONTEXT hd; sha1_init (&hd); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); sha1_final (&hd); memcpy (outbuf, hd.bctx.buf, 20); } /* Self-test section. */ static gpg_err_code_t selftests_sha1 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA1, 0, "abc", 3, "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D", 20); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA1, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE" "\x4A\xA1\xF9\x51\x29\xE5\xE5\x46\x70\xF1", 20); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA1, 1, NULL, 0, "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F", 20); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA1, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA1: ec = selftests_sha1 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; static gcry_md_oid_spec_t oid_spec_sha1[] = { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */ { "1.2.840.113549.1.1.5" }, /* iso.member-body.us.x9-57.x9cm.3 (dsaWithSha1)*/ { "1.2.840.10040.4.3" }, /* from NIST's OIW (sha1) */ { "1.3.14.3.2.26" }, /* from NIST OIW (sha-1WithRSAEncryption) */ { "1.3.14.3.2.29" }, /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */ { "1.2.840.10045.4.1" }, { NULL }, }; gcry_md_spec_t _gcry_digest_spec_sha1 = { "SHA1", asn, DIM (asn), oid_spec_sha1, 20, sha1_init, _gcry_md_block_write, sha1_final, sha1_read, sizeof (SHA1_CONTEXT) }; md_extra_spec_t _gcry_digest_extraspec_sha1 = { run_selftests }; diff --git a/cipher/sha256.c b/cipher/sha256.c index cf23f2f4..ad08cc78 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -1,523 +1,496 @@ /* sha256.c - SHA256 hash function * Copyright (C) 2003, 2006, 2008, 2009 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* Test vectors: "abc" SHA224: 23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7 SHA256: ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" SHA224: 75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525 SHA256: 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 "a" one million times SHA224: 20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67 SHA256: cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0 */ #include #include #include #include #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; u32 h0,h1,h2,h3,h4,h5,h6,h7; } SHA256_CONTEXT; static unsigned int transform (void *c, const unsigned char *data); static void sha256_init (void *context) { SHA256_CONTEXT *hd = context; hd->h0 = 0x6a09e667; hd->h1 = 0xbb67ae85; hd->h2 = 0x3c6ef372; hd->h3 = 0xa54ff53a; hd->h4 = 0x510e527f; hd->h5 = 0x9b05688c; hd->h6 = 0x1f83d9ab; hd->h7 = 0x5be0cd19; hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; } static void sha224_init (void *context) { SHA256_CONTEXT *hd = context; hd->h0 = 0xc1059ed8; hd->h1 = 0x367cd507; hd->h2 = 0x3070dd17; hd->h3 = 0xf70e5939; hd->h4 = 0xffc00b31; hd->h5 = 0x68581511; hd->h6 = 0x64f98fa7; hd->h7 = 0xbefa4fa4; hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; } /* Transform the message X which consists of 16 32-bit-words. See FIPS 180-2 for details. */ #define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3)) /* (4.6) */ #define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10)) /* (4.7) */ #define R(a,b,c,d,e,f,g,h,k,w) do \ { \ t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w); \ t2 = Sum0((a)) + Maj((a),(b),(c)); \ h = g; \ g = f; \ f = e; \ e = d + t1; \ d = c; \ c = b; \ b = a; \ a = t1 + t2; \ } while (0) /* (4.2) same as SHA-1's F1. */ static inline u32 Cho (u32 x, u32 y, u32 z) { return (z ^ (x & (y ^ z))); } /* (4.3) same as SHA-1's F3 */ static inline u32 Maj (u32 x, u32 y, u32 z) { return ((x & y) | (z & (x|y))); } /* (4.4) */ static inline u32 Sum0 (u32 x) { return (ror (x, 2) ^ ror (x, 13) ^ ror (x, 22)); } /* (4.5) */ static inline u32 Sum1 (u32 x) { return (ror (x, 6) ^ ror (x, 11) ^ ror (x, 25)); } static unsigned int transform (void *ctx, const unsigned char *data) { SHA256_CONTEXT *hd = ctx; static const u32 K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; u32 a,b,c,d,e,f,g,h,t1,t2; - u32 x[16]; u32 w[64]; int i; a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; f = hd->h5; g = hd->h6; h = hd->h7; -#ifdef WORDS_BIGENDIAN - memcpy (x, data, 64); -#else - { - byte *p2; - - for (i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) - { - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif - for (i=0; i < 16; i++) - w[i] = x[i]; + w[i] = buf_get_be32(data + i * 4); for (; i < 64; i++) w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16]; for (i=0; i < 64;) { #if 0 R(a,b,c,d,e,f,g,h,K[i],w[i]); i++; #else t1 = h + Sum1 (e) + Cho (e, f, g) + K[i] + w[i]; t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Cho (d, e, f) + K[i+1] + w[i+1]; t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Cho (c, d, e) + K[i+2] + w[i+2]; t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Cho (b, c, d) + K[i+3] + w[i+3]; t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Cho (a, b, c) + K[i+4] + w[i+4]; t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Cho (h, a, b) + K[i+5] + w[i+5]; t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Cho (g, h, a) + K[i+6] + w[i+6]; t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Cho (f, g, h) + K[i+7] + w[i+7]; t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; i += 8; #endif } hd->h0 += a; hd->h1 += b; hd->h2 += c; hd->h3 += d; hd->h4 += e; hd->h5 += f; hd->h6 += g; hd->h7 += h; return /*burn_stack*/ 74*4+32; } #undef S0 #undef S1 #undef R /* The routine finally terminates the computation and returns the digest. The handle is prepared for a new cycle, but adding bytes to the handle will the destroy the returned buffer. Returns: 32 bytes with the message the digest. */ static void sha256_final(void *context) { SHA256_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write (hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if (hd->bctx.count < 56) { /* enough room */ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ while (hd->bctx.count < 56) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else { /* need one extra block */ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ while (hd->bctx.count < 64) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write (hd, NULL, 0); /* flush */; memset (hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = msb >> 24; - hd->bctx.buf[57] = msb >> 16; - hd->bctx.buf[58] = msb >> 8; - hd->bctx.buf[59] = msb; - hd->bctx.buf[60] = lsb >> 24; - hd->bctx.buf[61] = lsb >> 16; - hd->bctx.buf[62] = lsb >> 8; - hd->bctx.buf[63] = lsb; + buf_put_be32(hd->bctx.buf + 56, msb); + buf_put_be32(hd->bctx.buf + 60, lsb); burn = transform (hd, hd->bctx.buf); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ - *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) -#endif +#define X(a) do { *(u32*)p = be_bswap32(hd->h##a); p += 4; } while(0) X(0); X(1); X(2); X(3); X(4); X(5); X(6); X(7); #undef X } static byte * sha256_read (void *context) { SHA256_CONTEXT *hd = context; return hd->bctx.buf; } /* Self-test section. */ static gpg_err_code_t selftests_sha224 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA224, 0, "abc", 3, "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3" "\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA224, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50" "\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25", 28); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA224, 1, NULL, 0, "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67", 28); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA224, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha256 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA256, 0, "abc", 3, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA256, 0, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39" "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", 32); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA256, 1, NULL, 0, "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0", 32); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA256, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA224: ec = selftests_sha224 (extended, report); break; case GCRY_MD_SHA256: ec = selftests_sha256 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */ { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C }; static gcry_md_oid_spec_t oid_spec_sha224[] = { /* From RFC3874, Section 4 */ { "2.16.840.1.101.3.4.2.4" }, { NULL }, }; static byte asn256[19] = /* Object ID is 2.16.840.1.101.3.4.2.1 */ { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; static gcry_md_oid_spec_t oid_spec_sha256[] = { /* According to the OpenPGP draft rfc2440-bis06 */ { "2.16.840.1.101.3.4.2.1" }, /* PKCS#1 sha256WithRSAEncryption */ { "1.2.840.113549.1.1.11" }, { NULL }, }; gcry_md_spec_t _gcry_digest_spec_sha224 = { "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28, sha224_init, _gcry_md_block_write, sha256_final, sha256_read, sizeof (SHA256_CONTEXT) }; md_extra_spec_t _gcry_digest_extraspec_sha224 = { run_selftests }; gcry_md_spec_t _gcry_digest_spec_sha256 = { "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32, sha256_init, _gcry_md_block_write, sha256_final, sha256_read, sizeof (SHA256_CONTEXT) }; md_extra_spec_t _gcry_digest_extraspec_sha256 = { run_selftests }; diff --git a/cipher/sha512.c b/cipher/sha512.c index 26cbe14d..505a1e46 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -1,808 +1,769 @@ /* sha512.c - SHA384 and SHA512 hash functions * Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* Test vectors from FIPS-180-2: * * "abc" * 384: * CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163 * 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7 * 512: * DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A * 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F * * "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" * 384: * 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2 * 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039 * 512: * 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018 * 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909 * * "a" x 1000000 * 384: * 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852 * 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985 * 512: * E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB * DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B */ #include #include #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" /* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */ #undef USE_ARM_NEON_ASM #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) # if defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \ defined(HAVE_GCC_INLINE_ASM_NEON) # define USE_ARM_NEON_ASM 1 # endif #endif typedef struct { u64 h0, h1, h2, h3, h4, h5, h6, h7; } SHA512_STATE; typedef struct { gcry_md_block_ctx_t bctx; SHA512_STATE state; #ifdef USE_ARM_NEON_ASM int use_neon; #endif } SHA512_CONTEXT; static unsigned int transform (void *context, const unsigned char *data); static void sha512_init (void *context) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; hd->h0 = U64_C(0x6a09e667f3bcc908); hd->h1 = U64_C(0xbb67ae8584caa73b); hd->h2 = U64_C(0x3c6ef372fe94f82b); hd->h3 = U64_C(0xa54ff53a5f1d36f1); hd->h4 = U64_C(0x510e527fade682d1); hd->h5 = U64_C(0x9b05688c2b3e6c1f); hd->h6 = U64_C(0x1f83d9abfb41bd6b); hd->h7 = U64_C(0x5be0cd19137e2179); ctx->bctx.nblocks = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 128; ctx->bctx.bwrite = transform; #ifdef USE_ARM_NEON_ASM ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; #endif } static void sha384_init (void *context) { SHA512_CONTEXT *ctx = context; SHA512_STATE *hd = &ctx->state; hd->h0 = U64_C(0xcbbb9d5dc1059ed8); hd->h1 = U64_C(0x629a292a367cd507); hd->h2 = U64_C(0x9159015a3070dd17); hd->h3 = U64_C(0x152fecd8f70e5939); hd->h4 = U64_C(0x67332667ffc00b31); hd->h5 = U64_C(0x8eb44a8768581511); hd->h6 = U64_C(0xdb0c2e0d64f98fa7); hd->h7 = U64_C(0x47b5481dbefa4fa4); ctx->bctx.nblocks = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 128; ctx->bctx.bwrite = transform; #ifdef USE_ARM_NEON_ASM ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; #endif } static inline u64 ROTR (u64 x, u64 n) { return ((x >> n) | (x << (64 - n))); } static inline u64 Ch (u64 x, u64 y, u64 z) { return ((x & y) ^ ( ~x & z)); } static inline u64 Maj (u64 x, u64 y, u64 z) { return ((x & y) ^ (x & z) ^ (y & z)); } static inline u64 Sum0 (u64 x) { return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39)); } static inline u64 Sum1 (u64 x) { return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41)); } static const u64 k[] = { U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd), U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc), U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019), U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118), U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe), U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2), U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1), U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694), U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3), U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65), U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483), U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5), U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210), U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4), U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725), U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70), U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926), U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df), U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8), U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b), U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001), U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30), U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910), U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8), U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53), U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8), U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb), U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3), U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60), U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec), U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9), U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b), U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207), U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178), U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6), U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b), U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493), U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c), U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a), U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817) }; /**************** * Transform the message W which consists of 16 64-bit-words */ static unsigned int __transform (SHA512_STATE *hd, const unsigned char *data) { u64 a, b, c, d, e, f, g, h; u64 w[16]; int t; /* get values from the chaining vars */ a = hd->h0; b = hd->h1; c = hd->h2; d = hd->h3; e = hd->h4; f = hd->h5; g = hd->h6; h = hd->h7; -#ifdef WORDS_BIGENDIAN - memcpy (w, data, 128); -#else - { - int i; - byte *p2; - - for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += 8) - { - p2[7] = *data++; - p2[6] = *data++; - p2[5] = *data++; - p2[4] = *data++; - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif + for ( t = 0; t < 16; t++ ) + w[t] = buf_get_be64(data + t * 8); #define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) #define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) for (t = 0; t < 80 - 16; ) { u64 t1, t2; /* Performance on a AMD Athlon(tm) Dual Core Processor 4050e with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes initialized to 0,1,2,3...255,0,... and 1000 iterations: Not unrolled with macros: 440ms Unrolled with macros: 350ms Unrolled with inline: 330ms */ #if 0 /* Not unrolled. */ t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t%16]; w[t%16] += S1 (w[(t - 2)%16]) + w[(t - 7)%16] + S0 (w[(t - 15)%16]); t2 = Sum0 (a) + Maj (a, b, c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; t++; #else /* Unrolled to interweave the chain variables. */ t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0]; w[0] += S1 (w[14]) + w[9] + S0 (w[1]); t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1]; w[1] += S1 (w[15]) + w[10] + S0 (w[2]); t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2]; w[2] += S1 (w[0]) + w[11] + S0 (w[3]); t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3]; w[3] += S1 (w[1]) + w[12] + S0 (w[4]); t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4]; w[4] += S1 (w[2]) + w[13] + S0 (w[5]); t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5]; w[5] += S1 (w[3]) + w[14] + S0 (w[6]); t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6]; w[6] += S1 (w[4]) + w[15] + S0 (w[7]); t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7]; w[7] += S1 (w[5]) + w[0] + S0 (w[8]); t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8]; w[8] += S1 (w[6]) + w[1] + S0 (w[9]); t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9]; w[9] += S1 (w[7]) + w[2] + S0 (w[10]); t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10]; w[10] += S1 (w[8]) + w[3] + S0 (w[11]); t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11]; w[11] += S1 (w[9]) + w[4] + S0 (w[12]); t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12]; w[12] += S1 (w[10]) + w[5] + S0 (w[13]); t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13]; w[13] += S1 (w[11]) + w[6] + S0 (w[14]); t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14]; w[14] += S1 (w[12]) + w[7] + S0 (w[15]); t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15]; w[15] += S1 (w[13]) + w[8] + S0 (w[0]); t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t += 16; #endif } for (; t < 80; ) { u64 t1, t2; #if 0 /* Not unrolled. */ t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t%16]; t2 = Sum0 (a) + Maj (a, b, c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; t++; #else /* Unrolled to interweave the chain variables. */ t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0]; t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1]; t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2]; t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3]; t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4]; t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5]; t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6]; t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7]; t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8]; t2 = Sum0 (a) + Maj (a, b, c); d += t1; h = t1 + t2; t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9]; t2 = Sum0 (h) + Maj (h, a, b); c += t1; g = t1 + t2; t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10]; t2 = Sum0 (g) + Maj (g, h, a); b += t1; f = t1 + t2; t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11]; t2 = Sum0 (f) + Maj (f, g, h); a += t1; e = t1 + t2; t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12]; t2 = Sum0 (e) + Maj (e, f, g); h += t1; d = t1 + t2; t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13]; t2 = Sum0 (d) + Maj (d, e, f); g += t1; c = t1 + t2; t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14]; t2 = Sum0 (c) + Maj (c, d, e); f += t1; b = t1 + t2; t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15]; t2 = Sum0 (b) + Maj (b, c, d); e += t1; a = t1 + t2; t += 16; #endif } /* Update chaining vars. */ hd->h0 += a; hd->h1 += b; hd->h2 += c; hd->h3 += d; hd->h4 += e; hd->h5 += f; hd->h6 += g; hd->h7 += h; return /* burn_stack */ (8 + 16) * sizeof(u64) + sizeof(u32) + 3 * sizeof(void*); } #ifdef USE_ARM_NEON_ASM void _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd, const unsigned char *data, const u64 k[]); #endif static unsigned int transform (void *context, const unsigned char *data) { SHA512_CONTEXT *ctx = context; #ifdef USE_ARM_NEON_ASM if (hd->use_neon) { _gcry_sha512_transform_armv7_neon(&ctx->state, data, k); /* _gcry_sha512_transform_armv7_neon does not store sensitive data * to stack. */ return /* no burn_stack */ 0; } #endif return __transform (&ctx->state, data) + 3 * sizeof(void*); } /* The routine final terminates the computation and * returns the digest. * The handle is prepared for a new cycle, but adding bytes to the * handle will the destroy the returned buffer. * Returns: 64 bytes representing the digest. When used for sha384, * we take the leftmost 48 of those bytes. */ static void sha512_final (void *context) { SHA512_CONTEXT *hd = context; unsigned int stack_burn_depth; u64 t, msb, lsb; byte *p; _gcry_md_block_write (context, NULL, 0); /* flush */ ; t = hd->bctx.nblocks; /* multiply by 128 to make a byte count */ lsb = t << 7; msb = t >> 57; /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 61; if (hd->bctx.count < 112) { /* enough room */ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */ while (hd->bctx.count < 112) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else { /* need one extra block */ hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */ while (hd->bctx.count < 128) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write (context, NULL, 0); /* flush */ ; memset (hd->bctx.buf, 0, 112); /* fill next block with zeroes */ } /* append the 128 bit count */ - hd->bctx.buf[112] = msb >> 56; - hd->bctx.buf[113] = msb >> 48; - hd->bctx.buf[114] = msb >> 40; - hd->bctx.buf[115] = msb >> 32; - hd->bctx.buf[116] = msb >> 24; - hd->bctx.buf[117] = msb >> 16; - hd->bctx.buf[118] = msb >> 8; - hd->bctx.buf[119] = msb; - - hd->bctx.buf[120] = lsb >> 56; - hd->bctx.buf[121] = lsb >> 48; - hd->bctx.buf[122] = lsb >> 40; - hd->bctx.buf[123] = lsb >> 32; - hd->bctx.buf[124] = lsb >> 24; - hd->bctx.buf[125] = lsb >> 16; - hd->bctx.buf[126] = lsb >> 8; - hd->bctx.buf[127] = lsb; + buf_put_be64(hd->bctx.buf + 112, msb); + buf_put_be64(hd->bctx.buf + 120, lsb); stack_burn_depth = transform (hd, hd->bctx.buf); _gcry_burn_stack (stack_burn_depth); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u64*)p = hd->state.h##a ; p += 8; } while (0) -#else /* little endian */ -#define X(a) do { *p++ = hd->state.h##a >> 56; *p++ = hd->state.h##a >> 48; \ - *p++ = hd->state.h##a >> 40; *p++ = hd->state.h##a >> 32; \ - *p++ = hd->state.h##a >> 24; *p++ = hd->state.h##a >> 16; \ - *p++ = hd->state.h##a >> 8; *p++ = hd->state.h##a; } while(0) -#endif +#define X(a) do { *(u64*)p = be_bswap64(hd->state.h##a) ; p += 8; } while (0) X (0); X (1); X (2); X (3); X (4); X (5); /* Note that these last two chunks are included even for SHA384. We just ignore them. */ X (6); X (7); #undef X } static byte * sha512_read (void *context) { SHA512_CONTEXT *hd = (SHA512_CONTEXT *) context; return hd->bctx.buf; } /* Self-test section. */ static gpg_err_code_t selftests_sha384 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA384, 0, "abc", 3, "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed" "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA384, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, "\x09\x33\x0C\x33\xF7\x11\x47\xE8\x3D\x19\x2F\xC7\x82\xCD\x1B\x47" "\x53\x11\x1B\x17\x3B\x3B\x05\xD2\x2F\xA0\x80\x86\xE3\xB0\xF7\x12" "\xFC\xC7\xC7\x1A\x55\x7E\x2D\xB9\x66\xC3\xE9\xFA\x91\x74\x60\x39", 48); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA384, 1, NULL, 0, "\x9D\x0E\x18\x09\x71\x64\x74\xCB\x08\x6E\x83\x4E\x31\x0A\x4A\x1C" "\xED\x14\x9E\x9C\x00\xF2\x48\x52\x79\x72\xCE\xC5\x70\x4C\x2A\x5B" "\x07\xB8\xB3\xDC\x38\xEC\xC4\xEB\xAE\x97\xDD\xD8\x7F\x3D\x89\x85", 48); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA384, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha512 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; what = "short string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512, 0, "abc", 3, "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD" "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F", 64); if (errtxt) goto failed; if (extended) { what = "long string"; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512, 0, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, "\x8E\x95\x9B\x75\xDA\xE3\x13\xDA\x8C\xF4\xF7\x28\x14\xFC\x14\x3F" "\x8F\x77\x79\xC6\xEB\x9F\x7F\xA1\x72\x99\xAE\xAD\xB6\x88\x90\x18" "\x50\x1D\x28\x9E\x49\x00\xF7\xE4\x33\x1B\x99\xDE\xC4\xB5\x43\x3A" "\xC7\xD3\x29\xEE\xB6\xDD\x26\x54\x5E\x96\xE5\x5B\x87\x4B\xE9\x09", 64); if (errtxt) goto failed; what = "one million \"a\""; errtxt = _gcry_hash_selftest_check_one (GCRY_MD_SHA512, 1, NULL, 0, "\xE7\x18\x48\x3D\x0C\xE7\x69\x64\x4E\x2E\x42\xC7\xBC\x15\xB4\x63" "\x8E\x1F\x98\xB1\x3B\x20\x44\x28\x56\x32\xA8\x03\xAF\xA9\x73\xEB" "\xDE\x0F\xF2\x44\x87\x7E\xA6\x0A\x4C\xB0\x43\x2C\xE5\x77\xC3\x1B" "\xEB\x00\x9C\x5C\x2C\x49\xAA\x2E\x4E\xAD\xB2\x17\xAD\x8C\xC0\x9B", 64); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("digest", GCRY_MD_SHA512, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Run a full self-test for ALGO and return 0 on success. */ static gpg_err_code_t run_selftests (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MD_SHA384: ec = selftests_sha384 (extended, report); break; case GCRY_MD_SHA512: ec = selftests_sha512 (extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } static byte sha512_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.3 */ { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; static gcry_md_oid_spec_t oid_spec_sha512[] = { { "2.16.840.1.101.3.4.2.3" }, /* PKCS#1 sha512WithRSAEncryption */ { "1.2.840.113549.1.1.13" }, { NULL } }; gcry_md_spec_t _gcry_digest_spec_sha512 = { "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64, sha512_init, _gcry_md_block_write, sha512_final, sha512_read, sizeof (SHA512_CONTEXT), }; md_extra_spec_t _gcry_digest_extraspec_sha512 = { run_selftests }; static byte sha384_asn[] = /* Object ID is 2.16.840.1.101.3.4.2.2 */ { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 }; static gcry_md_oid_spec_t oid_spec_sha384[] = { { "2.16.840.1.101.3.4.2.2" }, /* PKCS#1 sha384WithRSAEncryption */ { "1.2.840.113549.1.1.12" }, { NULL }, }; gcry_md_spec_t _gcry_digest_spec_sha384 = { "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48, sha384_init, _gcry_md_block_write, sha512_final, sha512_read, sizeof (SHA512_CONTEXT), }; md_extra_spec_t _gcry_digest_extraspec_sha384 = { run_selftests }; diff --git a/cipher/stribog.c b/cipher/stribog.c index 1f798823..61aa222d 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -1,1427 +1,1400 @@ /* stribog.c - GOST R 34.11-2012 (Stribog) hash function * Copyright (C) 2013 Dmitry Eremin-Solenikov * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* Undefine symbol to trade memory for speed */ #define STRIBOG_TABLES 1 #include #include #include #include #include "g10lib.h" #include "bithelp.h" +#include "bufhelp.h" #include "cipher.h" #include "hash-common.h" typedef struct { gcry_md_block_ctx_t bctx; union { u64 h[8]; unsigned char result[64]; }; u64 N[8]; u64 Sigma[8]; } STRIBOG_CONTEXT; static const byte Pi[256] = { 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77, 233, 119, 240, 219, 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, 249, 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66, 139, 1, 142, 79, 5, 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, 212, 211, 31, 235, 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204, 181, 112, 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135, 21, 161, 150, 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158, 178, 177, 50, 117, 25, 61, 255, 53, 138, 126, 109, 84, 198, 128, 195, 189, 13, 87, 223, 245, 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, 3, 224, 15, 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74, 167, 151, 96, 115, 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, 173, 69, 70, 146, 39, 94, 85, 47, 140, 163, 165, 125, 105, 213, 149, 59, 7, 88, 179, 64, 134, 172, 29, 247, 48, 55, 107, 228, 136, 217, 231, 137, 225, 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97, 32, 113, 103, 164, 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82, 89, 166, 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182 }; #ifndef STRIBOG_TABLES static const u64 A[64] = { U64_C(0x641c314b2b8ee083), U64_C(0xc83862965601dd1b), U64_C(0x8d70c431ac02a736), U64_C(0x07e095624504536c), U64_C(0x0edd37c48a08a6d8), U64_C(0x1ca76e95091051ad), U64_C(0x3853dc371220a247), U64_C(0x70a6a56e2440598e), U64_C(0xa48b474f9ef5dc18), U64_C(0x550b8e9e21f7a530), U64_C(0xaa16012142f35760), U64_C(0x492c024284fbaec0), U64_C(0x9258048415eb419d), U64_C(0x39b008152acb8227), U64_C(0x727d102a548b194e), U64_C(0xe4fa2054a80b329c), U64_C(0xf97d86d98a327728), U64_C(0xeffa11af0964ee50), U64_C(0xc3e9224312c8c1a0), U64_C(0x9bcf4486248d9f5d), U64_C(0x2b838811480723ba), U64_C(0x561b0d22900e4669), U64_C(0xac361a443d1c8cd2), U64_C(0x456c34887a3805b9), U64_C(0x5b068c651810a89e), U64_C(0xb60c05ca30204d21), U64_C(0x71180a8960409a42), U64_C(0xe230140fc0802984), U64_C(0xd960281e9d1d5215), U64_C(0xafc0503c273aa42a), U64_C(0x439da0784e745554), U64_C(0x86275df09ce8aaa8), U64_C(0x0321658cba93c138), U64_C(0x0642ca05693b9f70), U64_C(0x0c84890ad27623e0), U64_C(0x18150f14b9ec46dd), U64_C(0x302a1e286fc58ca7), U64_C(0x60543c50de970553), U64_C(0xc0a878a0a1330aa6), U64_C(0x9d4df05d5f661451), U64_C(0xaccc9ca9328a8950), U64_C(0x4585254f64090fa0), U64_C(0x8a174a9ec8121e5d), U64_C(0x092e94218d243cba), U64_C(0x125c354207487869), U64_C(0x24b86a840e90f0d2), U64_C(0x486dd4151c3dfdb9), U64_C(0x90dab52a387ae76f), U64_C(0x46b60f011a83988e), U64_C(0x8c711e02341b2d01), U64_C(0x05e23c0468365a02), U64_C(0x0ad97808d06cb404), U64_C(0x14aff010bdd87508), U64_C(0x2843fd2067adea10), U64_C(0x5086e740ce47c920), U64_C(0xa011d380818e8f40), U64_C(0x83478b07b2468764), U64_C(0x1b8e0b0e798c13c8), U64_C(0x3601161cf205268d), U64_C(0x6c022c38f90a4c07), U64_C(0xd8045870ef14980e), U64_C(0xad08b0e0c3282d1c), U64_C(0x47107ddd9b505a38), U64_C(0x8e20faa72ba0b470), }; static u64 strido (u64 l) { u64 t = 0; #if 0 int j; for (j = 0; j < 64; j++, l >>= 1) { if (l & 1) t ^= A[j]; } #else #define X(k) if (l & (1LL << k)) t ^= A[k]; X(000); X(001); X(002); X(003); X(004); X(005); X(006); X(007); X(010); X(011); X(012); X(013); X(014); X(015); X(016); X(017); X(020); X(021); X(022); X(023); X(024); X(025); X(026); X(027); X(030); X(031); X(032); X(033); X(034); X(035); X(036); X(037); X(040); X(041); X(042); X(043); X(044); X(045); X(046); X(047); X(050); X(051); X(052); X(053); X(054); X(055); X(056); X(057); X(060); X(061); X(062); X(063); X(064); X(065); X(066); X(067); X(070); X(071); X(072); X(073); X(074); X(075); X(076); X(077); #undef X #endif return t; } #else /* Pre-computed results of multiplication of bytes on A */ static const u64 stribog_table[8][256] = { /* 0 */ { U64_C(0x0000000000000000), U64_C(0x641c314b2b8ee083), U64_C(0xc83862965601dd1b), U64_C(0xac2453dd7d8f3d98), U64_C(0x8d70c431ac02a736), U64_C(0xe96cf57a878c47b5), U64_C(0x4548a6a7fa037a2d), U64_C(0x215497ecd18d9aae), U64_C(0x07e095624504536c), U64_C(0x63fca4296e8ab3ef), U64_C(0xcfd8f7f413058e77), U64_C(0xabc4c6bf388b6ef4), U64_C(0x8a905153e906f45a), U64_C(0xee8c6018c28814d9), U64_C(0x42a833c5bf072941), U64_C(0x26b4028e9489c9c2), U64_C(0x0edd37c48a08a6d8), U64_C(0x6ac1068fa186465b), U64_C(0xc6e55552dc097bc3), U64_C(0xa2f96419f7879b40), U64_C(0x83adf3f5260a01ee), U64_C(0xe7b1c2be0d84e16d), U64_C(0x4b959163700bdcf5), U64_C(0x2f89a0285b853c76), U64_C(0x093da2a6cf0cf5b4), U64_C(0x6d2193ede4821537), U64_C(0xc105c030990d28af), U64_C(0xa519f17bb283c82c), U64_C(0x844d6697630e5282), U64_C(0xe05157dc4880b201), U64_C(0x4c750401350f8f99), U64_C(0x2869354a1e816f1a), U64_C(0x1ca76e95091051ad), U64_C(0x78bb5fde229eb12e), U64_C(0xd49f0c035f118cb6), U64_C(0xb0833d48749f6c35), U64_C(0x91d7aaa4a512f69b), U64_C(0xf5cb9bef8e9c1618), U64_C(0x59efc832f3132b80), U64_C(0x3df3f979d89dcb03), U64_C(0x1b47fbf74c1402c1), U64_C(0x7f5bcabc679ae242), U64_C(0xd37f99611a15dfda), U64_C(0xb763a82a319b3f59), U64_C(0x96373fc6e016a5f7), U64_C(0xf22b0e8dcb984574), U64_C(0x5e0f5d50b61778ec), U64_C(0x3a136c1b9d99986f), U64_C(0x127a59518318f775), U64_C(0x7666681aa89617f6), U64_C(0xda423bc7d5192a6e), U64_C(0xbe5e0a8cfe97caed), U64_C(0x9f0a9d602f1a5043), U64_C(0xfb16ac2b0494b0c0), U64_C(0x5732fff6791b8d58), U64_C(0x332ecebd52956ddb), U64_C(0x159acc33c61ca419), U64_C(0x7186fd78ed92449a), U64_C(0xdda2aea5901d7902), U64_C(0xb9be9feebb939981), U64_C(0x98ea08026a1e032f), U64_C(0xfcf639494190e3ac), U64_C(0x50d26a943c1fde34), U64_C(0x34ce5bdf17913eb7), U64_C(0x3853dc371220a247), U64_C(0x5c4fed7c39ae42c4), U64_C(0xf06bbea144217f5c), U64_C(0x94778fea6faf9fdf), U64_C(0xb5231806be220571), U64_C(0xd13f294d95ace5f2), U64_C(0x7d1b7a90e823d86a), U64_C(0x19074bdbc3ad38e9), U64_C(0x3fb349555724f12b), U64_C(0x5baf781e7caa11a8), U64_C(0xf78b2bc301252c30), U64_C(0x93971a882aabccb3), U64_C(0xb2c38d64fb26561d), U64_C(0xd6dfbc2fd0a8b69e), U64_C(0x7afbeff2ad278b06), U64_C(0x1ee7deb986a96b85), U64_C(0x368eebf39828049f), U64_C(0x5292dab8b3a6e41c), U64_C(0xfeb68965ce29d984), U64_C(0x9aaab82ee5a73907), U64_C(0xbbfe2fc2342aa3a9), U64_C(0xdfe21e891fa4432a), U64_C(0x73c64d54622b7eb2), U64_C(0x17da7c1f49a59e31), U64_C(0x316e7e91dd2c57f3), U64_C(0x55724fdaf6a2b770), U64_C(0xf9561c078b2d8ae8), U64_C(0x9d4a2d4ca0a36a6b), U64_C(0xbc1ebaa0712ef0c5), U64_C(0xd8028beb5aa01046), U64_C(0x7426d836272f2dde), U64_C(0x103ae97d0ca1cd5d), U64_C(0x24f4b2a21b30f3ea), U64_C(0x40e883e930be1369), U64_C(0xecccd0344d312ef1), U64_C(0x88d0e17f66bfce72), U64_C(0xa9847693b73254dc), U64_C(0xcd9847d89cbcb45f), U64_C(0x61bc1405e13389c7), U64_C(0x05a0254ecabd6944), U64_C(0x231427c05e34a086), U64_C(0x4708168b75ba4005), U64_C(0xeb2c455608357d9d), U64_C(0x8f30741d23bb9d1e), U64_C(0xae64e3f1f23607b0), U64_C(0xca78d2bad9b8e733), U64_C(0x665c8167a437daab), U64_C(0x0240b02c8fb93a28), U64_C(0x2a29856691385532), U64_C(0x4e35b42dbab6b5b1), U64_C(0xe211e7f0c7398829), U64_C(0x860dd6bbecb768aa), U64_C(0xa75941573d3af204), U64_C(0xc345701c16b41287), U64_C(0x6f6123c16b3b2f1f), U64_C(0x0b7d128a40b5cf9c), U64_C(0x2dc91004d43c065e), U64_C(0x49d5214fffb2e6dd), U64_C(0xe5f17292823ddb45), U64_C(0x81ed43d9a9b33bc6), U64_C(0xa0b9d435783ea168), U64_C(0xc4a5e57e53b041eb), U64_C(0x6881b6a32e3f7c73), U64_C(0x0c9d87e805b19cf0), U64_C(0x70a6a56e2440598e), U64_C(0x14ba94250fceb90d), U64_C(0xb89ec7f872418495), U64_C(0xdc82f6b359cf6416), U64_C(0xfdd6615f8842feb8), U64_C(0x99ca5014a3cc1e3b), U64_C(0x35ee03c9de4323a3), U64_C(0x51f23282f5cdc320), U64_C(0x7746300c61440ae2), U64_C(0x135a01474acaea61), U64_C(0xbf7e529a3745d7f9), U64_C(0xdb6263d11ccb377a), U64_C(0xfa36f43dcd46add4), U64_C(0x9e2ac576e6c84d57), U64_C(0x320e96ab9b4770cf), U64_C(0x5612a7e0b0c9904c), U64_C(0x7e7b92aaae48ff56), U64_C(0x1a67a3e185c61fd5), U64_C(0xb643f03cf849224d), U64_C(0xd25fc177d3c7c2ce), U64_C(0xf30b569b024a5860), U64_C(0x971767d029c4b8e3), U64_C(0x3b33340d544b857b), U64_C(0x5f2f05467fc565f8), U64_C(0x799b07c8eb4cac3a), U64_C(0x1d873683c0c24cb9), U64_C(0xb1a3655ebd4d7121), U64_C(0xd5bf541596c391a2), U64_C(0xf4ebc3f9474e0b0c), U64_C(0x90f7f2b26cc0eb8f), U64_C(0x3cd3a16f114fd617), U64_C(0x58cf90243ac13694), U64_C(0x6c01cbfb2d500823), U64_C(0x081dfab006dee8a0), U64_C(0xa439a96d7b51d538), U64_C(0xc025982650df35bb), U64_C(0xe1710fca8152af15), U64_C(0x856d3e81aadc4f96), U64_C(0x29496d5cd753720e), U64_C(0x4d555c17fcdd928d), U64_C(0x6be15e9968545b4f), U64_C(0x0ffd6fd243dabbcc), U64_C(0xa3d93c0f3e558654), U64_C(0xc7c50d4415db66d7), U64_C(0xe6919aa8c456fc79), U64_C(0x828dabe3efd81cfa), U64_C(0x2ea9f83e92572162), U64_C(0x4ab5c975b9d9c1e1), U64_C(0x62dcfc3fa758aefb), U64_C(0x06c0cd748cd64e78), U64_C(0xaae49ea9f15973e0), U64_C(0xcef8afe2dad79363), U64_C(0xefac380e0b5a09cd), U64_C(0x8bb0094520d4e94e), U64_C(0x27945a985d5bd4d6), U64_C(0x43886bd376d53455), U64_C(0x653c695de25cfd97), U64_C(0x01205816c9d21d14), U64_C(0xad040bcbb45d208c), U64_C(0xc9183a809fd3c00f), U64_C(0xe84cad6c4e5e5aa1), U64_C(0x8c509c2765d0ba22), U64_C(0x2074cffa185f87ba), U64_C(0x4468feb133d16739), U64_C(0x48f579593660fbc9), U64_C(0x2ce948121dee1b4a), U64_C(0x80cd1bcf606126d2), U64_C(0xe4d12a844befc651), U64_C(0xc585bd689a625cff), U64_C(0xa1998c23b1ecbc7c), U64_C(0x0dbddffecc6381e4), U64_C(0x69a1eeb5e7ed6167), U64_C(0x4f15ec3b7364a8a5), U64_C(0x2b09dd7058ea4826), U64_C(0x872d8ead256575be), U64_C(0xe331bfe60eeb953d), U64_C(0xc265280adf660f93), U64_C(0xa6791941f4e8ef10), U64_C(0x0a5d4a9c8967d288), U64_C(0x6e417bd7a2e9320b), U64_C(0x46284e9dbc685d11), U64_C(0x22347fd697e6bd92), U64_C(0x8e102c0bea69800a), U64_C(0xea0c1d40c1e76089), U64_C(0xcb588aac106afa27), U64_C(0xaf44bbe73be41aa4), U64_C(0x0360e83a466b273c), U64_C(0x677cd9716de5c7bf), U64_C(0x41c8dbfff96c0e7d), U64_C(0x25d4eab4d2e2eefe), U64_C(0x89f0b969af6dd366), U64_C(0xedec882284e333e5), U64_C(0xccb81fce556ea94b), U64_C(0xa8a42e857ee049c8), U64_C(0x04807d58036f7450), U64_C(0x609c4c1328e194d3), U64_C(0x545217cc3f70aa64), U64_C(0x304e268714fe4ae7), U64_C(0x9c6a755a6971777f), U64_C(0xf876441142ff97fc), U64_C(0xd922d3fd93720d52), U64_C(0xbd3ee2b6b8fcedd1), U64_C(0x111ab16bc573d049), U64_C(0x75068020eefd30ca), U64_C(0x53b282ae7a74f908), U64_C(0x37aeb3e551fa198b), U64_C(0x9b8ae0382c752413), U64_C(0xff96d17307fbc490), U64_C(0xdec2469fd6765e3e), U64_C(0xbade77d4fdf8bebd), U64_C(0x16fa240980778325), U64_C(0x72e61542abf963a6), U64_C(0x5a8f2008b5780cbc), U64_C(0x3e9311439ef6ec3f), U64_C(0x92b7429ee379d1a7), U64_C(0xf6ab73d5c8f73124), U64_C(0xd7ffe439197aab8a), U64_C(0xb3e3d57232f44b09), U64_C(0x1fc786af4f7b7691), U64_C(0x7bdbb7e464f59612), U64_C(0x5d6fb56af07c5fd0), U64_C(0x39738421dbf2bf53), U64_C(0x9557d7fca67d82cb), U64_C(0xf14be6b78df36248), U64_C(0xd01f715b5c7ef8e6), U64_C(0xb403401077f01865), U64_C(0x182713cd0a7f25fd), U64_C(0x7c3b228621f1c57e) }, /* 1 */ { U64_C(0x0000000000000000), U64_C(0xa48b474f9ef5dc18), U64_C(0x550b8e9e21f7a530), U64_C(0xf180c9d1bf027928), U64_C(0xaa16012142f35760), U64_C(0x0e9d466edc068b78), U64_C(0xff1d8fbf6304f250), U64_C(0x5b96c8f0fdf12e48), U64_C(0x492c024284fbaec0), U64_C(0xeda7450d1a0e72d8), U64_C(0x1c278cdca50c0bf0), U64_C(0xb8accb933bf9d7e8), U64_C(0xe33a0363c608f9a0), U64_C(0x47b1442c58fd25b8), U64_C(0xb6318dfde7ff5c90), U64_C(0x12bacab2790a8088), U64_C(0x9258048415eb419d), U64_C(0x36d343cb8b1e9d85), U64_C(0xc7538a1a341ce4ad), U64_C(0x63d8cd55aae938b5), U64_C(0x384e05a5571816fd), U64_C(0x9cc542eac9edcae5), U64_C(0x6d458b3b76efb3cd), U64_C(0xc9cecc74e81a6fd5), U64_C(0xdb7406c69110ef5d), U64_C(0x7fff41890fe53345), U64_C(0x8e7f8858b0e74a6d), U64_C(0x2af4cf172e129675), U64_C(0x716207e7d3e3b83d), U64_C(0xd5e940a84d166425), U64_C(0x24698979f2141d0d), U64_C(0x80e2ce366ce1c115), U64_C(0x39b008152acb8227), U64_C(0x9d3b4f5ab43e5e3f), U64_C(0x6cbb868b0b3c2717), U64_C(0xc830c1c495c9fb0f), U64_C(0x93a609346838d547), U64_C(0x372d4e7bf6cd095f), U64_C(0xc6ad87aa49cf7077), U64_C(0x6226c0e5d73aac6f), U64_C(0x709c0a57ae302ce7), U64_C(0xd4174d1830c5f0ff), U64_C(0x259784c98fc789d7), U64_C(0x811cc386113255cf), U64_C(0xda8a0b76ecc37b87), U64_C(0x7e014c397236a79f), U64_C(0x8f8185e8cd34deb7), U64_C(0x2b0ac2a753c102af), U64_C(0xabe80c913f20c3ba), U64_C(0x0f634bdea1d51fa2), U64_C(0xfee3820f1ed7668a), U64_C(0x5a68c5408022ba92), U64_C(0x01fe0db07dd394da), U64_C(0xa5754affe32648c2), U64_C(0x54f5832e5c2431ea), U64_C(0xf07ec461c2d1edf2), U64_C(0xe2c40ed3bbdb6d7a), U64_C(0x464f499c252eb162), U64_C(0xb7cf804d9a2cc84a), U64_C(0x1344c70204d91452), U64_C(0x48d20ff2f9283a1a), U64_C(0xec5948bd67dde602), U64_C(0x1dd9816cd8df9f2a), U64_C(0xb952c623462a4332), U64_C(0x727d102a548b194e), U64_C(0xd6f65765ca7ec556), U64_C(0x27769eb4757cbc7e), U64_C(0x83fdd9fbeb896066), U64_C(0xd86b110b16784e2e), U64_C(0x7ce05644888d9236), U64_C(0x8d609f95378feb1e), U64_C(0x29ebd8daa97a3706), U64_C(0x3b511268d070b78e), U64_C(0x9fda55274e856b96), U64_C(0x6e5a9cf6f18712be), U64_C(0xcad1dbb96f72cea6), U64_C(0x914713499283e0ee), U64_C(0x35cc54060c763cf6), U64_C(0xc44c9dd7b37445de), U64_C(0x60c7da982d8199c6), U64_C(0xe02514ae416058d3), U64_C(0x44ae53e1df9584cb), U64_C(0xb52e9a306097fde3), U64_C(0x11a5dd7ffe6221fb), U64_C(0x4a33158f03930fb3), U64_C(0xeeb852c09d66d3ab), U64_C(0x1f389b112264aa83), U64_C(0xbbb3dc5ebc91769b), U64_C(0xa90916ecc59bf613), U64_C(0x0d8251a35b6e2a0b), U64_C(0xfc029872e46c5323), U64_C(0x5889df3d7a998f3b), U64_C(0x031f17cd8768a173), U64_C(0xa7945082199d7d6b), U64_C(0x56149953a69f0443), U64_C(0xf29fde1c386ad85b), U64_C(0x4bcd183f7e409b69), U64_C(0xef465f70e0b54771), U64_C(0x1ec696a15fb73e59), U64_C(0xba4dd1eec142e241), U64_C(0xe1db191e3cb3cc09), U64_C(0x45505e51a2461011), U64_C(0xb4d097801d446939), U64_C(0x105bd0cf83b1b521), U64_C(0x02e11a7dfabb35a9), U64_C(0xa66a5d32644ee9b1), U64_C(0x57ea94e3db4c9099), U64_C(0xf361d3ac45b94c81), U64_C(0xa8f71b5cb84862c9), U64_C(0x0c7c5c1326bdbed1), U64_C(0xfdfc95c299bfc7f9), U64_C(0x5977d28d074a1be1), U64_C(0xd9951cbb6babdaf4), U64_C(0x7d1e5bf4f55e06ec), U64_C(0x8c9e92254a5c7fc4), U64_C(0x2815d56ad4a9a3dc), U64_C(0x73831d9a29588d94), U64_C(0xd7085ad5b7ad518c), U64_C(0x2688930408af28a4), U64_C(0x8203d44b965af4bc), U64_C(0x90b91ef9ef507434), U64_C(0x343259b671a5a82c), U64_C(0xc5b29067cea7d104), U64_C(0x6139d72850520d1c), U64_C(0x3aaf1fd8ada32354), U64_C(0x9e2458973356ff4c), U64_C(0x6fa491468c548664), U64_C(0xcb2fd60912a15a7c), U64_C(0xe4fa2054a80b329c), U64_C(0x4071671b36feee84), U64_C(0xb1f1aeca89fc97ac), U64_C(0x157ae98517094bb4), U64_C(0x4eec2175eaf865fc), U64_C(0xea67663a740db9e4), U64_C(0x1be7afebcb0fc0cc), U64_C(0xbf6ce8a455fa1cd4), U64_C(0xadd622162cf09c5c), U64_C(0x095d6559b2054044), U64_C(0xf8ddac880d07396c), U64_C(0x5c56ebc793f2e574), U64_C(0x07c023376e03cb3c), U64_C(0xa34b6478f0f61724), U64_C(0x52cbada94ff46e0c), U64_C(0xf640eae6d101b214), U64_C(0x76a224d0bde07301), U64_C(0xd229639f2315af19), U64_C(0x23a9aa4e9c17d631), U64_C(0x8722ed0102e20a29), U64_C(0xdcb425f1ff132461), U64_C(0x783f62be61e6f879), U64_C(0x89bfab6fdee48151), U64_C(0x2d34ec2040115d49), U64_C(0x3f8e2692391bddc1), U64_C(0x9b0561dda7ee01d9), U64_C(0x6a85a80c18ec78f1), U64_C(0xce0eef438619a4e9), U64_C(0x959827b37be88aa1), U64_C(0x311360fce51d56b9), U64_C(0xc093a92d5a1f2f91), U64_C(0x6418ee62c4eaf389), U64_C(0xdd4a284182c0b0bb), U64_C(0x79c16f0e1c356ca3), U64_C(0x8841a6dfa337158b), U64_C(0x2ccae1903dc2c993), U64_C(0x775c2960c033e7db), U64_C(0xd3d76e2f5ec63bc3), U64_C(0x2257a7fee1c442eb), U64_C(0x86dce0b17f319ef3), U64_C(0x94662a03063b1e7b), U64_C(0x30ed6d4c98cec263), U64_C(0xc16da49d27ccbb4b), U64_C(0x65e6e3d2b9396753), U64_C(0x3e702b2244c8491b), U64_C(0x9afb6c6dda3d9503), U64_C(0x6b7ba5bc653fec2b), U64_C(0xcff0e2f3fbca3033), U64_C(0x4f122cc5972bf126), U64_C(0xeb996b8a09de2d3e), U64_C(0x1a19a25bb6dc5416), U64_C(0xbe92e5142829880e), U64_C(0xe5042de4d5d8a646), U64_C(0x418f6aab4b2d7a5e), U64_C(0xb00fa37af42f0376), U64_C(0x1484e4356adadf6e), U64_C(0x063e2e8713d05fe6), U64_C(0xa2b569c88d2583fe), U64_C(0x5335a0193227fad6), U64_C(0xf7bee756acd226ce), U64_C(0xac282fa651230886), U64_C(0x08a368e9cfd6d49e), U64_C(0xf923a13870d4adb6), U64_C(0x5da8e677ee2171ae), U64_C(0x9687307efc802bd2), U64_C(0x320c77316275f7ca), U64_C(0xc38cbee0dd778ee2), U64_C(0x6707f9af438252fa), U64_C(0x3c91315fbe737cb2), U64_C(0x981a76102086a0aa), U64_C(0x699abfc19f84d982), U64_C(0xcd11f88e0171059a), U64_C(0xdfab323c787b8512), U64_C(0x7b207573e68e590a), U64_C(0x8aa0bca2598c2022), U64_C(0x2e2bfbedc779fc3a), U64_C(0x75bd331d3a88d272), U64_C(0xd1367452a47d0e6a), U64_C(0x20b6bd831b7f7742), U64_C(0x843dfacc858aab5a), U64_C(0x04df34fae96b6a4f), U64_C(0xa05473b5779eb657), U64_C(0x51d4ba64c89ccf7f), U64_C(0xf55ffd2b56691367), U64_C(0xaec935dbab983d2f), U64_C(0x0a427294356de137), U64_C(0xfbc2bb458a6f981f), U64_C(0x5f49fc0a149a4407), U64_C(0x4df336b86d90c48f), U64_C(0xe97871f7f3651897), U64_C(0x18f8b8264c6761bf), U64_C(0xbc73ff69d292bda7), U64_C(0xe7e537992f6393ef), U64_C(0x436e70d6b1964ff7), U64_C(0xb2eeb9070e9436df), U64_C(0x1665fe489061eac7), U64_C(0xaf37386bd64ba9f5), U64_C(0x0bbc7f2448be75ed), U64_C(0xfa3cb6f5f7bc0cc5), U64_C(0x5eb7f1ba6949d0dd), U64_C(0x0521394a94b8fe95), U64_C(0xa1aa7e050a4d228d), U64_C(0x502ab7d4b54f5ba5), U64_C(0xf4a1f09b2bba87bd), U64_C(0xe61b3a2952b00735), U64_C(0x42907d66cc45db2d), U64_C(0xb310b4b77347a205), U64_C(0x179bf3f8edb27e1d), U64_C(0x4c0d3b0810435055), U64_C(0xe8867c478eb68c4d), U64_C(0x1906b59631b4f565), U64_C(0xbd8df2d9af41297d), U64_C(0x3d6f3cefc3a0e868), U64_C(0x99e47ba05d553470), U64_C(0x6864b271e2574d58), U64_C(0xcceff53e7ca29140), U64_C(0x97793dce8153bf08), U64_C(0x33f27a811fa66310), U64_C(0xc272b350a0a41a38), U64_C(0x66f9f41f3e51c620), U64_C(0x74433ead475b46a8), U64_C(0xd0c879e2d9ae9ab0), U64_C(0x2148b03366ace398), U64_C(0x85c3f77cf8593f80), U64_C(0xde553f8c05a811c8), U64_C(0x7ade78c39b5dcdd0), U64_C(0x8b5eb112245fb4f8), U64_C(0x2fd5f65dbaaa68e0) }, /* 2 */ { U64_C(0x0000000000000000), U64_C(0xf97d86d98a327728), U64_C(0xeffa11af0964ee50), U64_C(0x1687977683569978), U64_C(0xc3e9224312c8c1a0), U64_C(0x3a94a49a98fab688), U64_C(0x2c1333ec1bac2ff0), U64_C(0xd56eb535919e58d8), U64_C(0x9bcf4486248d9f5d), U64_C(0x62b2c25faebfe875), U64_C(0x743555292de9710d), U64_C(0x8d48d3f0a7db0625), U64_C(0x582666c536455efd), U64_C(0xa15be01cbc7729d5), U64_C(0xb7dc776a3f21b0ad), U64_C(0x4ea1f1b3b513c785), U64_C(0x2b838811480723ba), U64_C(0xd2fe0ec8c2355492), U64_C(0xc47999be4163cdea), U64_C(0x3d041f67cb51bac2), U64_C(0xe86aaa525acfe21a), U64_C(0x11172c8bd0fd9532), U64_C(0x0790bbfd53ab0c4a), U64_C(0xfeed3d24d9997b62), U64_C(0xb04ccc976c8abce7), U64_C(0x49314a4ee6b8cbcf), U64_C(0x5fb6dd3865ee52b7), U64_C(0xa6cb5be1efdc259f), U64_C(0x73a5eed47e427d47), U64_C(0x8ad8680df4700a6f), U64_C(0x9c5fff7b77269317), U64_C(0x652279a2fd14e43f), U64_C(0x561b0d22900e4669), U64_C(0xaf668bfb1a3c3141), U64_C(0xb9e11c8d996aa839), U64_C(0x409c9a541358df11), U64_C(0x95f22f6182c687c9), U64_C(0x6c8fa9b808f4f0e1), U64_C(0x7a083ece8ba26999), U64_C(0x8375b81701901eb1), U64_C(0xcdd449a4b483d934), U64_C(0x34a9cf7d3eb1ae1c), U64_C(0x222e580bbde73764), U64_C(0xdb53ded237d5404c), U64_C(0x0e3d6be7a64b1894), U64_C(0xf740ed3e2c796fbc), U64_C(0xe1c77a48af2ff6c4), U64_C(0x18bafc91251d81ec), U64_C(0x7d988533d80965d3), U64_C(0x84e503ea523b12fb), U64_C(0x9262949cd16d8b83), U64_C(0x6b1f12455b5ffcab), U64_C(0xbe71a770cac1a473), U64_C(0x470c21a940f3d35b), U64_C(0x518bb6dfc3a54a23), U64_C(0xa8f6300649973d0b), U64_C(0xe657c1b5fc84fa8e), U64_C(0x1f2a476c76b68da6), U64_C(0x09add01af5e014de), U64_C(0xf0d056c37fd263f6), U64_C(0x25bee3f6ee4c3b2e), U64_C(0xdcc3652f647e4c06), U64_C(0xca44f259e728d57e), U64_C(0x333974806d1aa256), U64_C(0xac361a443d1c8cd2), U64_C(0x554b9c9db72efbfa), U64_C(0x43cc0beb34786282), U64_C(0xbab18d32be4a15aa), U64_C(0x6fdf38072fd44d72), U64_C(0x96a2bedea5e63a5a), U64_C(0x802529a826b0a322), U64_C(0x7958af71ac82d40a), U64_C(0x37f95ec21991138f), U64_C(0xce84d81b93a364a7), U64_C(0xd8034f6d10f5fddf), U64_C(0x217ec9b49ac78af7), U64_C(0xf4107c810b59d22f), U64_C(0x0d6dfa58816ba507), U64_C(0x1bea6d2e023d3c7f), U64_C(0xe297ebf7880f4b57), U64_C(0x87b59255751baf68), U64_C(0x7ec8148cff29d840), U64_C(0x684f83fa7c7f4138), U64_C(0x91320523f64d3610), U64_C(0x445cb01667d36ec8), U64_C(0xbd2136cfede119e0), U64_C(0xaba6a1b96eb78098), U64_C(0x52db2760e485f7b0), U64_C(0x1c7ad6d351963035), U64_C(0xe507500adba4471d), U64_C(0xf380c77c58f2de65), U64_C(0x0afd41a5d2c0a94d), U64_C(0xdf93f490435ef195), U64_C(0x26ee7249c96c86bd), U64_C(0x3069e53f4a3a1fc5), U64_C(0xc91463e6c00868ed), U64_C(0xfa2d1766ad12cabb), U64_C(0x035091bf2720bd93), U64_C(0x15d706c9a47624eb), U64_C(0xecaa80102e4453c3), U64_C(0x39c43525bfda0b1b), U64_C(0xc0b9b3fc35e87c33), U64_C(0xd63e248ab6bee54b), U64_C(0x2f43a2533c8c9263), U64_C(0x61e253e0899f55e6), U64_C(0x989fd53903ad22ce), U64_C(0x8e18424f80fbbbb6), U64_C(0x7765c4960ac9cc9e), U64_C(0xa20b71a39b579446), U64_C(0x5b76f77a1165e36e), U64_C(0x4df1600c92337a16), U64_C(0xb48ce6d518010d3e), U64_C(0xd1ae9f77e515e901), U64_C(0x28d319ae6f279e29), U64_C(0x3e548ed8ec710751), U64_C(0xc729080166437079), U64_C(0x1247bd34f7dd28a1), U64_C(0xeb3a3bed7def5f89), U64_C(0xfdbdac9bfeb9c6f1), U64_C(0x04c02a42748bb1d9), U64_C(0x4a61dbf1c198765c), U64_C(0xb31c5d284baa0174), U64_C(0xa59bca5ec8fc980c), U64_C(0x5ce64c8742ceef24), U64_C(0x8988f9b2d350b7fc), U64_C(0x70f57f6b5962c0d4), U64_C(0x6672e81dda3459ac), U64_C(0x9f0f6ec450062e84), U64_C(0x456c34887a3805b9), U64_C(0xbc11b251f00a7291), U64_C(0xaa962527735cebe9), U64_C(0x53eba3fef96e9cc1), U64_C(0x868516cb68f0c419), U64_C(0x7ff89012e2c2b331), U64_C(0x697f076461942a49), U64_C(0x900281bdeba65d61), U64_C(0xdea3700e5eb59ae4), U64_C(0x27def6d7d487edcc), U64_C(0x315961a157d174b4), U64_C(0xc824e778dde3039c), U64_C(0x1d4a524d4c7d5b44), U64_C(0xe437d494c64f2c6c), U64_C(0xf2b043e24519b514), U64_C(0x0bcdc53bcf2bc23c), U64_C(0x6eefbc99323f2603), U64_C(0x97923a40b80d512b), U64_C(0x8115ad363b5bc853), U64_C(0x78682befb169bf7b), U64_C(0xad069eda20f7e7a3), U64_C(0x547b1803aac5908b), U64_C(0x42fc8f75299309f3), U64_C(0xbb8109aca3a17edb), U64_C(0xf520f81f16b2b95e), U64_C(0x0c5d7ec69c80ce76), U64_C(0x1adae9b01fd6570e), U64_C(0xe3a76f6995e42026), U64_C(0x36c9da5c047a78fe), U64_C(0xcfb45c858e480fd6), U64_C(0xd933cbf30d1e96ae), U64_C(0x204e4d2a872ce186), U64_C(0x137739aaea3643d0), U64_C(0xea0abf73600434f8), U64_C(0xfc8d2805e352ad80), U64_C(0x05f0aedc6960daa8), U64_C(0xd09e1be9f8fe8270), U64_C(0x29e39d3072ccf558), U64_C(0x3f640a46f19a6c20), U64_C(0xc6198c9f7ba81b08), U64_C(0x88b87d2ccebbdc8d), U64_C(0x71c5fbf54489aba5), U64_C(0x67426c83c7df32dd), U64_C(0x9e3fea5a4ded45f5), U64_C(0x4b515f6fdc731d2d), U64_C(0xb22cd9b656416a05), U64_C(0xa4ab4ec0d517f37d), U64_C(0x5dd6c8195f258455), U64_C(0x38f4b1bba231606a), U64_C(0xc189376228031742), U64_C(0xd70ea014ab558e3a), U64_C(0x2e7326cd2167f912), U64_C(0xfb1d93f8b0f9a1ca), U64_C(0x026015213acbd6e2), U64_C(0x14e78257b99d4f9a), U64_C(0xed9a048e33af38b2), U64_C(0xa33bf53d86bcff37), U64_C(0x5a4673e40c8e881f), U64_C(0x4cc1e4928fd81167), U64_C(0xb5bc624b05ea664f), U64_C(0x60d2d77e94743e97), U64_C(0x99af51a71e4649bf), U64_C(0x8f28c6d19d10d0c7), U64_C(0x765540081722a7ef), U64_C(0xe95a2ecc4724896b), U64_C(0x1027a815cd16fe43), U64_C(0x06a03f634e40673b), U64_C(0xffddb9bac4721013), U64_C(0x2ab30c8f55ec48cb), U64_C(0xd3ce8a56dfde3fe3), U64_C(0xc5491d205c88a69b), U64_C(0x3c349bf9d6bad1b3), U64_C(0x72956a4a63a91636), U64_C(0x8be8ec93e99b611e), U64_C(0x9d6f7be56acdf866), U64_C(0x6412fd3ce0ff8f4e), U64_C(0xb17c48097161d796), U64_C(0x4801ced0fb53a0be), U64_C(0x5e8659a6780539c6), U64_C(0xa7fbdf7ff2374eee), U64_C(0xc2d9a6dd0f23aad1), U64_C(0x3ba420048511ddf9), U64_C(0x2d23b77206474481), U64_C(0xd45e31ab8c7533a9), U64_C(0x0130849e1deb6b71), U64_C(0xf84d024797d91c59), U64_C(0xeeca9531148f8521), U64_C(0x17b713e89ebdf209), U64_C(0x5916e25b2bae358c), U64_C(0xa06b6482a19c42a4), U64_C(0xb6ecf3f422cadbdc), U64_C(0x4f91752da8f8acf4), U64_C(0x9affc0183966f42c), U64_C(0x638246c1b3548304), U64_C(0x7505d1b730021a7c), U64_C(0x8c78576eba306d54), U64_C(0xbf4123eed72acf02), U64_C(0x463ca5375d18b82a), U64_C(0x50bb3241de4e2152), U64_C(0xa9c6b498547c567a), U64_C(0x7ca801adc5e20ea2), U64_C(0x85d587744fd0798a), U64_C(0x93521002cc86e0f2), U64_C(0x6a2f96db46b497da), U64_C(0x248e6768f3a7505f), U64_C(0xddf3e1b179952777), U64_C(0xcb7476c7fac3be0f), U64_C(0x3209f01e70f1c927), U64_C(0xe767452be16f91ff), U64_C(0x1e1ac3f26b5de6d7), U64_C(0x089d5484e80b7faf), U64_C(0xf1e0d25d62390887), U64_C(0x94c2abff9f2decb8), U64_C(0x6dbf2d26151f9b90), U64_C(0x7b38ba50964902e8), U64_C(0x82453c891c7b75c0), U64_C(0x572b89bc8de52d18), U64_C(0xae560f6507d75a30), U64_C(0xb8d198138481c348), U64_C(0x41ac1eca0eb3b460), U64_C(0x0f0def79bba073e5), U64_C(0xf67069a0319204cd), U64_C(0xe0f7fed6b2c49db5), U64_C(0x198a780f38f6ea9d), U64_C(0xcce4cd3aa968b245), U64_C(0x35994be3235ac56d), U64_C(0x231edc95a00c5c15), U64_C(0xda635a4c2a3e2b3d) }, /* 3 */ { U64_C(0x0000000000000000), U64_C(0x5b068c651810a89e), U64_C(0xb60c05ca30204d21), U64_C(0xed0a89af2830e5bf), U64_C(0x71180a8960409a42), U64_C(0x2a1e86ec785032dc), U64_C(0xc7140f435060d763), U64_C(0x9c12832648707ffd), U64_C(0xe230140fc0802984), U64_C(0xb936986ad890811a), U64_C(0x543c11c5f0a064a5), U64_C(0x0f3a9da0e8b0cc3b), U64_C(0x93281e86a0c0b3c6), U64_C(0xc82e92e3b8d01b58), U64_C(0x25241b4c90e0fee7), U64_C(0x7e22972988f05679), U64_C(0xd960281e9d1d5215), U64_C(0x8266a47b850dfa8b), U64_C(0x6f6c2dd4ad3d1f34), U64_C(0x346aa1b1b52db7aa), U64_C(0xa8782297fd5dc857), U64_C(0xf37eaef2e54d60c9), U64_C(0x1e74275dcd7d8576), U64_C(0x4572ab38d56d2de8), U64_C(0x3b503c115d9d7b91), U64_C(0x6056b074458dd30f), U64_C(0x8d5c39db6dbd36b0), U64_C(0xd65ab5be75ad9e2e), U64_C(0x4a4836983ddde1d3), U64_C(0x114ebafd25cd494d), U64_C(0xfc4433520dfdacf2), U64_C(0xa742bf3715ed046c), U64_C(0xafc0503c273aa42a), U64_C(0xf4c6dc593f2a0cb4), U64_C(0x19cc55f6171ae90b), U64_C(0x42cad9930f0a4195), U64_C(0xded85ab5477a3e68), U64_C(0x85ded6d05f6a96f6), U64_C(0x68d45f7f775a7349), U64_C(0x33d2d31a6f4adbd7), U64_C(0x4df04433e7ba8dae), U64_C(0x16f6c856ffaa2530), U64_C(0xfbfc41f9d79ac08f), U64_C(0xa0facd9ccf8a6811), U64_C(0x3ce84eba87fa17ec), U64_C(0x67eec2df9feabf72), U64_C(0x8ae44b70b7da5acd), U64_C(0xd1e2c715afcaf253), U64_C(0x76a07822ba27f63f), U64_C(0x2da6f447a2375ea1), U64_C(0xc0ac7de88a07bb1e), U64_C(0x9baaf18d92171380), U64_C(0x07b872abda676c7d), U64_C(0x5cbefecec277c4e3), U64_C(0xb1b47761ea47215c), U64_C(0xeab2fb04f25789c2), U64_C(0x94906c2d7aa7dfbb), U64_C(0xcf96e04862b77725), U64_C(0x229c69e74a87929a), U64_C(0x799ae58252973a04), U64_C(0xe58866a41ae745f9), U64_C(0xbe8eeac102f7ed67), U64_C(0x5384636e2ac708d8), U64_C(0x0882ef0b32d7a046), U64_C(0x439da0784e745554), U64_C(0x189b2c1d5664fdca), U64_C(0xf591a5b27e541875), U64_C(0xae9729d76644b0eb), U64_C(0x3285aaf12e34cf16), U64_C(0x6983269436246788), U64_C(0x8489af3b1e148237), U64_C(0xdf8f235e06042aa9), U64_C(0xa1adb4778ef47cd0), U64_C(0xfaab381296e4d44e), U64_C(0x17a1b1bdbed431f1), U64_C(0x4ca73dd8a6c4996f), U64_C(0xd0b5befeeeb4e692), U64_C(0x8bb3329bf6a44e0c), U64_C(0x66b9bb34de94abb3), U64_C(0x3dbf3751c684032d), U64_C(0x9afd8866d3690741), U64_C(0xc1fb0403cb79afdf), U64_C(0x2cf18dace3494a60), U64_C(0x77f701c9fb59e2fe), U64_C(0xebe582efb3299d03), U64_C(0xb0e30e8aab39359d), U64_C(0x5de987258309d022), U64_C(0x06ef0b409b1978bc), U64_C(0x78cd9c6913e92ec5), U64_C(0x23cb100c0bf9865b), U64_C(0xcec199a323c963e4), U64_C(0x95c715c63bd9cb7a), U64_C(0x09d596e073a9b487), U64_C(0x52d31a856bb91c19), U64_C(0xbfd9932a4389f9a6), U64_C(0xe4df1f4f5b995138), U64_C(0xec5df044694ef17e), U64_C(0xb75b7c21715e59e0), U64_C(0x5a51f58e596ebc5f), U64_C(0x015779eb417e14c1), U64_C(0x9d45facd090e6b3c), U64_C(0xc64376a8111ec3a2), U64_C(0x2b49ff07392e261d), U64_C(0x704f7362213e8e83), U64_C(0x0e6de44ba9ced8fa), U64_C(0x556b682eb1de7064), U64_C(0xb861e18199ee95db), U64_C(0xe3676de481fe3d45), U64_C(0x7f75eec2c98e42b8), U64_C(0x247362a7d19eea26), U64_C(0xc979eb08f9ae0f99), U64_C(0x927f676de1bea707), U64_C(0x353dd85af453a36b), U64_C(0x6e3b543fec430bf5), U64_C(0x8331dd90c473ee4a), U64_C(0xd83751f5dc6346d4), U64_C(0x4425d2d394133929), U64_C(0x1f235eb68c0391b7), U64_C(0xf229d719a4337408), U64_C(0xa92f5b7cbc23dc96), U64_C(0xd70dcc5534d38aef), U64_C(0x8c0b40302cc32271), U64_C(0x6101c99f04f3c7ce), U64_C(0x3a0745fa1ce36f50), U64_C(0xa615c6dc549310ad), U64_C(0xfd134ab94c83b833), U64_C(0x1019c31664b35d8c), U64_C(0x4b1f4f737ca3f512), U64_C(0x86275df09ce8aaa8), U64_C(0xdd21d19584f80236), U64_C(0x302b583aacc8e789), U64_C(0x6b2dd45fb4d84f17), U64_C(0xf73f5779fca830ea), U64_C(0xac39db1ce4b89874), U64_C(0x413352b3cc887dcb), U64_C(0x1a35ded6d498d555), U64_C(0x641749ff5c68832c), U64_C(0x3f11c59a44782bb2), U64_C(0xd21b4c356c48ce0d), U64_C(0x891dc05074586693), U64_C(0x150f43763c28196e), U64_C(0x4e09cf132438b1f0), U64_C(0xa30346bc0c08544f), U64_C(0xf805cad91418fcd1), U64_C(0x5f4775ee01f5f8bd), U64_C(0x0441f98b19e55023), U64_C(0xe94b702431d5b59c), U64_C(0xb24dfc4129c51d02), U64_C(0x2e5f7f6761b562ff), U64_C(0x7559f30279a5ca61), U64_C(0x98537aad51952fde), U64_C(0xc355f6c849858740), U64_C(0xbd7761e1c175d139), U64_C(0xe671ed84d96579a7), U64_C(0x0b7b642bf1559c18), U64_C(0x507de84ee9453486), U64_C(0xcc6f6b68a1354b7b), U64_C(0x9769e70db925e3e5), U64_C(0x7a636ea29115065a), U64_C(0x2165e2c78905aec4), U64_C(0x29e70dccbbd20e82), U64_C(0x72e181a9a3c2a61c), U64_C(0x9feb08068bf243a3), U64_C(0xc4ed846393e2eb3d), U64_C(0x58ff0745db9294c0), U64_C(0x03f98b20c3823c5e), U64_C(0xeef3028febb2d9e1), U64_C(0xb5f58eeaf3a2717f), U64_C(0xcbd719c37b522706), U64_C(0x90d195a663428f98), U64_C(0x7ddb1c094b726a27), U64_C(0x26dd906c5362c2b9), U64_C(0xbacf134a1b12bd44), U64_C(0xe1c99f2f030215da), U64_C(0x0cc316802b32f065), U64_C(0x57c59ae5332258fb), U64_C(0xf08725d226cf5c97), U64_C(0xab81a9b73edff409), U64_C(0x468b201816ef11b6), U64_C(0x1d8dac7d0effb928), U64_C(0x819f2f5b468fc6d5), U64_C(0xda99a33e5e9f6e4b), U64_C(0x37932a9176af8bf4), U64_C(0x6c95a6f46ebf236a), U64_C(0x12b731dde64f7513), U64_C(0x49b1bdb8fe5fdd8d), U64_C(0xa4bb3417d66f3832), U64_C(0xffbdb872ce7f90ac), U64_C(0x63af3b54860fef51), U64_C(0x38a9b7319e1f47cf), U64_C(0xd5a33e9eb62fa270), U64_C(0x8ea5b2fbae3f0aee), U64_C(0xc5bafd88d29cfffc), U64_C(0x9ebc71edca8c5762), U64_C(0x73b6f842e2bcb2dd), U64_C(0x28b07427faac1a43), U64_C(0xb4a2f701b2dc65be), U64_C(0xefa47b64aacccd20), U64_C(0x02aef2cb82fc289f), U64_C(0x59a87eae9aec8001), U64_C(0x278ae987121cd678), U64_C(0x7c8c65e20a0c7ee6), U64_C(0x9186ec4d223c9b59), U64_C(0xca8060283a2c33c7), U64_C(0x5692e30e725c4c3a), U64_C(0x0d946f6b6a4ce4a4), U64_C(0xe09ee6c4427c011b), U64_C(0xbb986aa15a6ca985), U64_C(0x1cdad5964f81ade9), U64_C(0x47dc59f357910577), U64_C(0xaad6d05c7fa1e0c8), U64_C(0xf1d05c3967b14856), U64_C(0x6dc2df1f2fc137ab), U64_C(0x36c4537a37d19f35), U64_C(0xdbcedad51fe17a8a), U64_C(0x80c856b007f1d214), U64_C(0xfeeac1998f01846d), U64_C(0xa5ec4dfc97112cf3), U64_C(0x48e6c453bf21c94c), U64_C(0x13e04836a73161d2), U64_C(0x8ff2cb10ef411e2f), U64_C(0xd4f44775f751b6b1), U64_C(0x39fecedadf61530e), U64_C(0x62f842bfc771fb90), U64_C(0x6a7aadb4f5a65bd6), U64_C(0x317c21d1edb6f348), U64_C(0xdc76a87ec58616f7), U64_C(0x8770241bdd96be69), U64_C(0x1b62a73d95e6c194), U64_C(0x40642b588df6690a), U64_C(0xad6ea2f7a5c68cb5), U64_C(0xf6682e92bdd6242b), U64_C(0x884ab9bb35267252), U64_C(0xd34c35de2d36dacc), U64_C(0x3e46bc7105063f73), U64_C(0x654030141d1697ed), U64_C(0xf952b3325566e810), U64_C(0xa2543f574d76408e), U64_C(0x4f5eb6f86546a531), U64_C(0x14583a9d7d560daf), U64_C(0xb31a85aa68bb09c3), U64_C(0xe81c09cf70aba15d), U64_C(0x05168060589b44e2), U64_C(0x5e100c05408bec7c), U64_C(0xc2028f2308fb9381), U64_C(0x9904034610eb3b1f), U64_C(0x740e8ae938dbdea0), U64_C(0x2f08068c20cb763e), U64_C(0x512a91a5a83b2047), U64_C(0x0a2c1dc0b02b88d9), U64_C(0xe726946f981b6d66), U64_C(0xbc20180a800bc5f8), U64_C(0x20329b2cc87bba05), U64_C(0x7b341749d06b129b), U64_C(0x963e9ee6f85bf724), U64_C(0xcd381283e04b5fba) }, /* 4 */ { U64_C(0x0000000000000000), U64_C(0x0321658cba93c138), U64_C(0x0642ca05693b9f70), U64_C(0x0563af89d3a85e48), U64_C(0x0c84890ad27623e0), U64_C(0x0fa5ec8668e5e2d8), U64_C(0x0ac6430fbb4dbc90), U64_C(0x09e7268301de7da8), U64_C(0x18150f14b9ec46dd), U64_C(0x1b346a98037f87e5), U64_C(0x1e57c511d0d7d9ad), U64_C(0x1d76a09d6a441895), U64_C(0x1491861e6b9a653d), U64_C(0x17b0e392d109a405), U64_C(0x12d34c1b02a1fa4d), U64_C(0x11f22997b8323b75), U64_C(0x302a1e286fc58ca7), U64_C(0x330b7ba4d5564d9f), U64_C(0x3668d42d06fe13d7), U64_C(0x3549b1a1bc6dd2ef), U64_C(0x3cae9722bdb3af47), U64_C(0x3f8ff2ae07206e7f), U64_C(0x3aec5d27d4883037), U64_C(0x39cd38ab6e1bf10f), U64_C(0x283f113cd629ca7a), U64_C(0x2b1e74b06cba0b42), U64_C(0x2e7ddb39bf12550a), U64_C(0x2d5cbeb505819432), U64_C(0x24bb9836045fe99a), U64_C(0x279afdbabecc28a2), U64_C(0x22f952336d6476ea), U64_C(0x21d837bfd7f7b7d2), U64_C(0x60543c50de970553), U64_C(0x637559dc6404c46b), U64_C(0x6616f655b7ac9a23), U64_C(0x653793d90d3f5b1b), U64_C(0x6cd0b55a0ce126b3), U64_C(0x6ff1d0d6b672e78b), U64_C(0x6a927f5f65dab9c3), U64_C(0x69b31ad3df4978fb), U64_C(0x78413344677b438e), U64_C(0x7b6056c8dde882b6), U64_C(0x7e03f9410e40dcfe), U64_C(0x7d229ccdb4d31dc6), U64_C(0x74c5ba4eb50d606e), U64_C(0x77e4dfc20f9ea156), U64_C(0x7287704bdc36ff1e), U64_C(0x71a615c766a53e26), U64_C(0x507e2278b15289f4), U64_C(0x535f47f40bc148cc), U64_C(0x563ce87dd8691684), U64_C(0x551d8df162fad7bc), U64_C(0x5cfaab726324aa14), U64_C(0x5fdbcefed9b76b2c), U64_C(0x5ab861770a1f3564), U64_C(0x599904fbb08cf45c), U64_C(0x486b2d6c08becf29), U64_C(0x4b4a48e0b22d0e11), U64_C(0x4e29e76961855059), U64_C(0x4d0882e5db169161), U64_C(0x44efa466dac8ecc9), U64_C(0x47cec1ea605b2df1), U64_C(0x42ad6e63b3f373b9), U64_C(0x418c0bef0960b281), U64_C(0xc0a878a0a1330aa6), U64_C(0xc3891d2c1ba0cb9e), U64_C(0xc6eab2a5c80895d6), U64_C(0xc5cbd729729b54ee), U64_C(0xcc2cf1aa73452946), U64_C(0xcf0d9426c9d6e87e), U64_C(0xca6e3baf1a7eb636), U64_C(0xc94f5e23a0ed770e), U64_C(0xd8bd77b418df4c7b), U64_C(0xdb9c1238a24c8d43), U64_C(0xdeffbdb171e4d30b), U64_C(0xddded83dcb771233), U64_C(0xd439febecaa96f9b), U64_C(0xd7189b32703aaea3), U64_C(0xd27b34bba392f0eb), U64_C(0xd15a5137190131d3), U64_C(0xf0826688cef68601), U64_C(0xf3a3030474654739), U64_C(0xf6c0ac8da7cd1971), U64_C(0xf5e1c9011d5ed849), U64_C(0xfc06ef821c80a5e1), U64_C(0xff278a0ea61364d9), U64_C(0xfa44258775bb3a91), U64_C(0xf965400bcf28fba9), U64_C(0xe897699c771ac0dc), U64_C(0xebb60c10cd8901e4), U64_C(0xeed5a3991e215fac), U64_C(0xedf4c615a4b29e94), U64_C(0xe413e096a56ce33c), U64_C(0xe732851a1fff2204), U64_C(0xe2512a93cc577c4c), U64_C(0xe1704f1f76c4bd74), U64_C(0xa0fc44f07fa40ff5), U64_C(0xa3dd217cc537cecd), U64_C(0xa6be8ef5169f9085), U64_C(0xa59feb79ac0c51bd), U64_C(0xac78cdfaadd22c15), U64_C(0xaf59a8761741ed2d), U64_C(0xaa3a07ffc4e9b365), U64_C(0xa91b62737e7a725d), U64_C(0xb8e94be4c6484928), U64_C(0xbbc82e687cdb8810), U64_C(0xbeab81e1af73d658), U64_C(0xbd8ae46d15e01760), U64_C(0xb46dc2ee143e6ac8), U64_C(0xb74ca762aeadabf0), U64_C(0xb22f08eb7d05f5b8), U64_C(0xb10e6d67c7963480), U64_C(0x90d65ad810618352), U64_C(0x93f73f54aaf2426a), U64_C(0x969490dd795a1c22), U64_C(0x95b5f551c3c9dd1a), U64_C(0x9c52d3d2c217a0b2), U64_C(0x9f73b65e7884618a), U64_C(0x9a1019d7ab2c3fc2), U64_C(0x99317c5b11bffefa), U64_C(0x88c355cca98dc58f), U64_C(0x8be23040131e04b7), U64_C(0x8e819fc9c0b65aff), U64_C(0x8da0fa457a259bc7), U64_C(0x8447dcc67bfbe66f), U64_C(0x8766b94ac1682757), U64_C(0x820516c312c0791f), U64_C(0x8124734fa853b827), U64_C(0x9d4df05d5f661451), U64_C(0x9e6c95d1e5f5d569), U64_C(0x9b0f3a58365d8b21), U64_C(0x982e5fd48cce4a19), U64_C(0x91c979578d1037b1), U64_C(0x92e81cdb3783f689), U64_C(0x978bb352e42ba8c1), U64_C(0x94aad6de5eb869f9), U64_C(0x8558ff49e68a528c), U64_C(0x86799ac55c1993b4), U64_C(0x831a354c8fb1cdfc), U64_C(0x803b50c035220cc4), U64_C(0x89dc764334fc716c), U64_C(0x8afd13cf8e6fb054), U64_C(0x8f9ebc465dc7ee1c), U64_C(0x8cbfd9cae7542f24), U64_C(0xad67ee7530a398f6), U64_C(0xae468bf98a3059ce), U64_C(0xab25247059980786), U64_C(0xa80441fce30bc6be), U64_C(0xa1e3677fe2d5bb16), U64_C(0xa2c202f358467a2e), U64_C(0xa7a1ad7a8bee2466), U64_C(0xa480c8f6317de55e), U64_C(0xb572e161894fde2b), U64_C(0xb65384ed33dc1f13), U64_C(0xb3302b64e074415b), U64_C(0xb0114ee85ae78063), U64_C(0xb9f6686b5b39fdcb), U64_C(0xbad70de7e1aa3cf3), U64_C(0xbfb4a26e320262bb), U64_C(0xbc95c7e28891a383), U64_C(0xfd19cc0d81f11102), U64_C(0xfe38a9813b62d03a), U64_C(0xfb5b0608e8ca8e72), U64_C(0xf87a638452594f4a), U64_C(0xf19d4507538732e2), U64_C(0xf2bc208be914f3da), U64_C(0xf7df8f023abcad92), U64_C(0xf4feea8e802f6caa), U64_C(0xe50cc319381d57df), U64_C(0xe62da695828e96e7), U64_C(0xe34e091c5126c8af), U64_C(0xe06f6c90ebb50997), U64_C(0xe9884a13ea6b743f), U64_C(0xeaa92f9f50f8b507), U64_C(0xefca80168350eb4f), U64_C(0xecebe59a39c32a77), U64_C(0xcd33d225ee349da5), U64_C(0xce12b7a954a75c9d), U64_C(0xcb711820870f02d5), U64_C(0xc8507dac3d9cc3ed), U64_C(0xc1b75b2f3c42be45), U64_C(0xc2963ea386d17f7d), U64_C(0xc7f5912a55792135), U64_C(0xc4d4f4a6efeae00d), U64_C(0xd526dd3157d8db78), U64_C(0xd607b8bded4b1a40), U64_C(0xd36417343ee34408), U64_C(0xd04572b884708530), U64_C(0xd9a2543b85aef898), U64_C(0xda8331b73f3d39a0), U64_C(0xdfe09e3eec9567e8), U64_C(0xdcc1fbb25606a6d0), U64_C(0x5de588fdfe551ef7), U64_C(0x5ec4ed7144c6dfcf), U64_C(0x5ba742f8976e8187), U64_C(0x588627742dfd40bf), U64_C(0x516101f72c233d17), U64_C(0x5240647b96b0fc2f), U64_C(0x5723cbf24518a267), U64_C(0x5402ae7eff8b635f), U64_C(0x45f087e947b9582a), U64_C(0x46d1e265fd2a9912), U64_C(0x43b24dec2e82c75a), U64_C(0x4093286094110662), U64_C(0x49740ee395cf7bca), U64_C(0x4a556b6f2f5cbaf2), U64_C(0x4f36c4e6fcf4e4ba), U64_C(0x4c17a16a46672582), U64_C(0x6dcf96d591909250), U64_C(0x6eeef3592b035368), U64_C(0x6b8d5cd0f8ab0d20), U64_C(0x68ac395c4238cc18), U64_C(0x614b1fdf43e6b1b0), U64_C(0x626a7a53f9757088), U64_C(0x6709d5da2add2ec0), U64_C(0x6428b056904eeff8), U64_C(0x75da99c1287cd48d), U64_C(0x76fbfc4d92ef15b5), U64_C(0x739853c441474bfd), U64_C(0x70b93648fbd48ac5), U64_C(0x795e10cbfa0af76d), U64_C(0x7a7f754740993655), U64_C(0x7f1cdace9331681d), U64_C(0x7c3dbf4229a2a925), U64_C(0x3db1b4ad20c21ba4), U64_C(0x3e90d1219a51da9c), U64_C(0x3bf37ea849f984d4), U64_C(0x38d21b24f36a45ec), U64_C(0x31353da7f2b43844), U64_C(0x3214582b4827f97c), U64_C(0x3777f7a29b8fa734), U64_C(0x3456922e211c660c), U64_C(0x25a4bbb9992e5d79), U64_C(0x2685de3523bd9c41), U64_C(0x23e671bcf015c209), U64_C(0x20c714304a860331), U64_C(0x292032b34b587e99), U64_C(0x2a01573ff1cbbfa1), U64_C(0x2f62f8b62263e1e9), U64_C(0x2c439d3a98f020d1), U64_C(0x0d9baa854f079703), U64_C(0x0ebacf09f594563b), U64_C(0x0bd96080263c0873), U64_C(0x08f8050c9cafc94b), U64_C(0x011f238f9d71b4e3), U64_C(0x023e460327e275db), U64_C(0x075de98af44a2b93), U64_C(0x047c8c064ed9eaab), U64_C(0x158ea591f6ebd1de), U64_C(0x16afc01d4c7810e6), U64_C(0x13cc6f949fd04eae), U64_C(0x10ed0a1825438f96), U64_C(0x190a2c9b249df23e), U64_C(0x1a2b49179e0e3306), U64_C(0x1f48e69e4da66d4e), U64_C(0x1c698312f735ac76) }, /* 5 */ { U64_C(0x0000000000000000), U64_C(0xaccc9ca9328a8950), U64_C(0x4585254f64090fa0), U64_C(0xe949b9e6568386f0), U64_C(0x8a174a9ec8121e5d), U64_C(0x26dbd637fa98970d), U64_C(0xcf926fd1ac1b11fd), U64_C(0x635ef3789e9198ad), U64_C(0x092e94218d243cba), U64_C(0xa5e20888bfaeb5ea), U64_C(0x4cabb16ee92d331a), U64_C(0xe0672dc7dba7ba4a), U64_C(0x8339debf453622e7), U64_C(0x2ff5421677bcabb7), U64_C(0xc6bcfbf0213f2d47), U64_C(0x6a70675913b5a417), U64_C(0x125c354207487869), U64_C(0xbe90a9eb35c2f139), U64_C(0x57d9100d634177c9), U64_C(0xfb158ca451cbfe99), U64_C(0x984b7fdccf5a6634), U64_C(0x3487e375fdd0ef64), U64_C(0xddce5a93ab536994), U64_C(0x7102c63a99d9e0c4), U64_C(0x1b72a1638a6c44d3), U64_C(0xb7be3dcab8e6cd83), U64_C(0x5ef7842cee654b73), U64_C(0xf23b1885dcefc223), U64_C(0x9165ebfd427e5a8e), U64_C(0x3da9775470f4d3de), U64_C(0xd4e0ceb22677552e), U64_C(0x782c521b14fddc7e), U64_C(0x24b86a840e90f0d2), U64_C(0x8874f62d3c1a7982), U64_C(0x613d4fcb6a99ff72), U64_C(0xcdf1d36258137622), U64_C(0xaeaf201ac682ee8f), U64_C(0x0263bcb3f40867df), U64_C(0xeb2a0555a28be12f), U64_C(0x47e699fc9001687f), U64_C(0x2d96fea583b4cc68), U64_C(0x815a620cb13e4538), U64_C(0x6813dbeae7bdc3c8), U64_C(0xc4df4743d5374a98), U64_C(0xa781b43b4ba6d235), U64_C(0x0b4d2892792c5b65), U64_C(0xe20491742fafdd95), U64_C(0x4ec80ddd1d2554c5), U64_C(0x36e45fc609d888bb), U64_C(0x9a28c36f3b5201eb), U64_C(0x73617a896dd1871b), U64_C(0xdfade6205f5b0e4b), U64_C(0xbcf31558c1ca96e6), U64_C(0x103f89f1f3401fb6), U64_C(0xf9763017a5c39946), U64_C(0x55baacbe97491016), U64_C(0x3fcacbe784fcb401), U64_C(0x9306574eb6763d51), U64_C(0x7a4feea8e0f5bba1), U64_C(0xd6837201d27f32f1), U64_C(0xb5dd81794ceeaa5c), U64_C(0x19111dd07e64230c), U64_C(0xf058a43628e7a5fc), U64_C(0x5c94389f1a6d2cac), U64_C(0x486dd4151c3dfdb9), U64_C(0xe4a148bc2eb774e9), U64_C(0x0de8f15a7834f219), U64_C(0xa1246df34abe7b49), U64_C(0xc27a9e8bd42fe3e4), U64_C(0x6eb60222e6a56ab4), U64_C(0x87ffbbc4b026ec44), U64_C(0x2b33276d82ac6514), U64_C(0x414340349119c103), U64_C(0xed8fdc9da3934853), U64_C(0x04c6657bf510cea3), U64_C(0xa80af9d2c79a47f3), U64_C(0xcb540aaa590bdf5e), U64_C(0x679896036b81560e), U64_C(0x8ed12fe53d02d0fe), U64_C(0x221db34c0f8859ae), U64_C(0x5a31e1571b7585d0), U64_C(0xf6fd7dfe29ff0c80), U64_C(0x1fb4c4187f7c8a70), U64_C(0xb37858b14df60320), U64_C(0xd026abc9d3679b8d), U64_C(0x7cea3760e1ed12dd), U64_C(0x95a38e86b76e942d), U64_C(0x396f122f85e41d7d), U64_C(0x531f75769651b96a), U64_C(0xffd3e9dfa4db303a), U64_C(0x169a5039f258b6ca), U64_C(0xba56cc90c0d23f9a), U64_C(0xd9083fe85e43a737), U64_C(0x75c4a3416cc92e67), U64_C(0x9c8d1aa73a4aa897), U64_C(0x3041860e08c021c7), U64_C(0x6cd5be9112ad0d6b), U64_C(0xc01922382027843b), U64_C(0x29509bde76a402cb), U64_C(0x859c0777442e8b9b), U64_C(0xe6c2f40fdabf1336), U64_C(0x4a0e68a6e8359a66), U64_C(0xa347d140beb61c96), U64_C(0x0f8b4de98c3c95c6), U64_C(0x65fb2ab09f8931d1), U64_C(0xc937b619ad03b881), U64_C(0x207e0ffffb803e71), U64_C(0x8cb29356c90ab721), U64_C(0xefec602e579b2f8c), U64_C(0x4320fc876511a6dc), U64_C(0xaa6945613392202c), U64_C(0x06a5d9c80118a97c), U64_C(0x7e898bd315e57502), U64_C(0xd245177a276ffc52), U64_C(0x3b0cae9c71ec7aa2), U64_C(0x97c032354366f3f2), U64_C(0xf49ec14dddf76b5f), U64_C(0x58525de4ef7de20f), U64_C(0xb11be402b9fe64ff), U64_C(0x1dd778ab8b74edaf), U64_C(0x77a71ff298c149b8), U64_C(0xdb6b835baa4bc0e8), U64_C(0x32223abdfcc84618), U64_C(0x9eeea614ce42cf48), U64_C(0xfdb0556c50d357e5), U64_C(0x517cc9c56259deb5), U64_C(0xb835702334da5845), U64_C(0x14f9ec8a0650d115), U64_C(0x90dab52a387ae76f), U64_C(0x3c1629830af06e3f), U64_C(0xd55f90655c73e8cf), U64_C(0x79930ccc6ef9619f), U64_C(0x1acdffb4f068f932), U64_C(0xb601631dc2e27062), U64_C(0x5f48dafb9461f692), U64_C(0xf3844652a6eb7fc2), U64_C(0x99f4210bb55edbd5), U64_C(0x3538bda287d45285), U64_C(0xdc710444d157d475), U64_C(0x70bd98ede3dd5d25), U64_C(0x13e36b957d4cc588), U64_C(0xbf2ff73c4fc64cd8), U64_C(0x56664eda1945ca28), U64_C(0xfaaad2732bcf4378), U64_C(0x828680683f329f06), U64_C(0x2e4a1cc10db81656), U64_C(0xc703a5275b3b90a6), U64_C(0x6bcf398e69b119f6), U64_C(0x0891caf6f720815b), U64_C(0xa45d565fc5aa080b), U64_C(0x4d14efb993298efb), U64_C(0xe1d87310a1a307ab), U64_C(0x8ba81449b216a3bc), U64_C(0x276488e0809c2aec), U64_C(0xce2d3106d61fac1c), U64_C(0x62e1adafe495254c), U64_C(0x01bf5ed77a04bde1), U64_C(0xad73c27e488e34b1), U64_C(0x443a7b981e0db241), U64_C(0xe8f6e7312c873b11), U64_C(0xb462dfae36ea17bd), U64_C(0x18ae430704609eed), U64_C(0xf1e7fae152e3181d), U64_C(0x5d2b66486069914d), U64_C(0x3e759530fef809e0), U64_C(0x92b90999cc7280b0), U64_C(0x7bf0b07f9af10640), U64_C(0xd73c2cd6a87b8f10), U64_C(0xbd4c4b8fbbce2b07), U64_C(0x1180d7268944a257), U64_C(0xf8c96ec0dfc724a7), U64_C(0x5405f269ed4dadf7), U64_C(0x375b011173dc355a), U64_C(0x9b979db84156bc0a), U64_C(0x72de245e17d53afa), U64_C(0xde12b8f7255fb3aa), U64_C(0xa63eeaec31a26fd4), U64_C(0x0af276450328e684), U64_C(0xe3bbcfa355ab6074), U64_C(0x4f77530a6721e924), U64_C(0x2c29a072f9b07189), U64_C(0x80e53cdbcb3af8d9), U64_C(0x69ac853d9db97e29), U64_C(0xc5601994af33f779), U64_C(0xaf107ecdbc86536e), U64_C(0x03dce2648e0cda3e), U64_C(0xea955b82d88f5cce), U64_C(0x4659c72bea05d59e), U64_C(0x2507345374944d33), U64_C(0x89cba8fa461ec463), U64_C(0x6082111c109d4293), U64_C(0xcc4e8db52217cbc3), U64_C(0xd8b7613f24471ad6), U64_C(0x747bfd9616cd9386), U64_C(0x9d324470404e1576), U64_C(0x31fed8d972c49c26), U64_C(0x52a02ba1ec55048b), U64_C(0xfe6cb708dedf8ddb), U64_C(0x17250eee885c0b2b), U64_C(0xbbe99247bad6827b), U64_C(0xd199f51ea963266c), U64_C(0x7d5569b79be9af3c), U64_C(0x941cd051cd6a29cc), U64_C(0x38d04cf8ffe0a09c), U64_C(0x5b8ebf8061713831), U64_C(0xf742232953fbb161), U64_C(0x1e0b9acf05783791), U64_C(0xb2c7066637f2bec1), U64_C(0xcaeb547d230f62bf), U64_C(0x6627c8d41185ebef), U64_C(0x8f6e713247066d1f), U64_C(0x23a2ed9b758ce44f), U64_C(0x40fc1ee3eb1d7ce2), U64_C(0xec30824ad997f5b2), U64_C(0x05793bac8f147342), U64_C(0xa9b5a705bd9efa12), U64_C(0xc3c5c05cae2b5e05), U64_C(0x6f095cf59ca1d755), U64_C(0x8640e513ca2251a5), U64_C(0x2a8c79baf8a8d8f5), U64_C(0x49d28ac266394058), U64_C(0xe51e166b54b3c908), U64_C(0x0c57af8d02304ff8), U64_C(0xa09b332430bac6a8), U64_C(0xfc0f0bbb2ad7ea04), U64_C(0x50c39712185d6354), U64_C(0xb98a2ef44edee5a4), U64_C(0x1546b25d7c546cf4), U64_C(0x76184125e2c5f459), U64_C(0xdad4dd8cd04f7d09), U64_C(0x339d646a86ccfbf9), U64_C(0x9f51f8c3b44672a9), U64_C(0xf5219f9aa7f3d6be), U64_C(0x59ed033395795fee), U64_C(0xb0a4bad5c3fad91e), U64_C(0x1c68267cf170504e), U64_C(0x7f36d5046fe1c8e3), U64_C(0xd3fa49ad5d6b41b3), U64_C(0x3ab3f04b0be8c743), U64_C(0x967f6ce239624e13), U64_C(0xee533ef92d9f926d), U64_C(0x429fa2501f151b3d), U64_C(0xabd61bb649969dcd), U64_C(0x071a871f7b1c149d), U64_C(0x64447467e58d8c30), U64_C(0xc888e8ced7070560), U64_C(0x21c1512881848390), U64_C(0x8d0dcd81b30e0ac0), U64_C(0xe77daad8a0bbaed7), U64_C(0x4bb1367192312787), U64_C(0xa2f88f97c4b2a177), U64_C(0x0e34133ef6382827), U64_C(0x6d6ae04668a9b08a), U64_C(0xc1a67cef5a2339da), U64_C(0x28efc5090ca0bf2a), U64_C(0x842359a03e2a367a) }, /* 6 */ { U64_C(0x0000000000000000), U64_C(0x46b60f011a83988e), U64_C(0x8c711e02341b2d01), U64_C(0xcac711032e98b58f), U64_C(0x05e23c0468365a02), U64_C(0x4354330572b5c28c), U64_C(0x899322065c2d7703), U64_C(0xcf252d0746aeef8d), U64_C(0x0ad97808d06cb404), U64_C(0x4c6f7709caef2c8a), U64_C(0x86a8660ae4779905), U64_C(0xc01e690bfef4018b), U64_C(0x0f3b440cb85aee06), U64_C(0x498d4b0da2d97688), U64_C(0x834a5a0e8c41c307), U64_C(0xc5fc550f96c25b89), U64_C(0x14aff010bdd87508), U64_C(0x5219ff11a75bed86), U64_C(0x98deee1289c35809), U64_C(0xde68e1139340c087), U64_C(0x114dcc14d5ee2f0a), U64_C(0x57fbc315cf6db784), U64_C(0x9d3cd216e1f5020b), U64_C(0xdb8add17fb769a85), U64_C(0x1e7688186db4c10c), U64_C(0x58c0871977375982), U64_C(0x9207961a59afec0d), U64_C(0xd4b1991b432c7483), U64_C(0x1b94b41c05829b0e), U64_C(0x5d22bb1d1f010380), U64_C(0x97e5aa1e3199b60f), U64_C(0xd153a51f2b1a2e81), U64_C(0x2843fd2067adea10), U64_C(0x6ef5f2217d2e729e), U64_C(0xa432e32253b6c711), U64_C(0xe284ec2349355f9f), U64_C(0x2da1c1240f9bb012), U64_C(0x6b17ce251518289c), U64_C(0xa1d0df263b809d13), U64_C(0xe766d0272103059d), U64_C(0x229a8528b7c15e14), U64_C(0x642c8a29ad42c69a), U64_C(0xaeeb9b2a83da7315), U64_C(0xe85d942b9959eb9b), U64_C(0x2778b92cdff70416), U64_C(0x61ceb62dc5749c98), U64_C(0xab09a72eebec2917), U64_C(0xedbfa82ff16fb199), U64_C(0x3cec0d30da759f18), U64_C(0x7a5a0231c0f60796), U64_C(0xb09d1332ee6eb219), U64_C(0xf62b1c33f4ed2a97), U64_C(0x390e3134b243c51a), U64_C(0x7fb83e35a8c05d94), U64_C(0xb57f2f368658e81b), U64_C(0xf3c920379cdb7095), U64_C(0x363575380a192b1c), U64_C(0x70837a39109ab392), U64_C(0xba446b3a3e02061d), U64_C(0xfcf2643b24819e93), U64_C(0x33d7493c622f711e), U64_C(0x7561463d78ace990), U64_C(0xbfa6573e56345c1f), U64_C(0xf910583f4cb7c491), U64_C(0x5086e740ce47c920), U64_C(0x1630e841d4c451ae), U64_C(0xdcf7f942fa5ce421), U64_C(0x9a41f643e0df7caf), U64_C(0x5564db44a6719322), U64_C(0x13d2d445bcf20bac), U64_C(0xd915c546926abe23), U64_C(0x9fa3ca4788e926ad), U64_C(0x5a5f9f481e2b7d24), U64_C(0x1ce9904904a8e5aa), U64_C(0xd62e814a2a305025), U64_C(0x90988e4b30b3c8ab), U64_C(0x5fbda34c761d2726), U64_C(0x190bac4d6c9ebfa8), U64_C(0xd3ccbd4e42060a27), U64_C(0x957ab24f588592a9), U64_C(0x44291750739fbc28), U64_C(0x029f1851691c24a6), U64_C(0xc858095247849129), U64_C(0x8eee06535d0709a7), U64_C(0x41cb2b541ba9e62a), U64_C(0x077d2455012a7ea4), U64_C(0xcdba35562fb2cb2b), U64_C(0x8b0c3a57353153a5), U64_C(0x4ef06f58a3f3082c), U64_C(0x08466059b97090a2), U64_C(0xc281715a97e8252d), U64_C(0x84377e5b8d6bbda3), U64_C(0x4b12535ccbc5522e), U64_C(0x0da45c5dd146caa0), U64_C(0xc7634d5effde7f2f), U64_C(0x81d5425fe55de7a1), U64_C(0x78c51a60a9ea2330), U64_C(0x3e731561b369bbbe), U64_C(0xf4b404629df10e31), U64_C(0xb2020b63877296bf), U64_C(0x7d272664c1dc7932), U64_C(0x3b912965db5fe1bc), U64_C(0xf1563866f5c75433), U64_C(0xb7e03767ef44ccbd), U64_C(0x721c626879869734), U64_C(0x34aa6d6963050fba), U64_C(0xfe6d7c6a4d9dba35), U64_C(0xb8db736b571e22bb), U64_C(0x77fe5e6c11b0cd36), U64_C(0x3148516d0b3355b8), U64_C(0xfb8f406e25abe037), U64_C(0xbd394f6f3f2878b9), U64_C(0x6c6aea7014325638), U64_C(0x2adce5710eb1ceb6), U64_C(0xe01bf47220297b39), U64_C(0xa6adfb733aaae3b7), U64_C(0x6988d6747c040c3a), U64_C(0x2f3ed975668794b4), U64_C(0xe5f9c876481f213b), U64_C(0xa34fc777529cb9b5), U64_C(0x66b39278c45ee23c), U64_C(0x20059d79dedd7ab2), U64_C(0xeac28c7af045cf3d), U64_C(0xac74837beac657b3), U64_C(0x6351ae7cac68b83e), U64_C(0x25e7a17db6eb20b0), U64_C(0xef20b07e9873953f), U64_C(0xa996bf7f82f00db1), U64_C(0xa011d380818e8f40), U64_C(0xe6a7dc819b0d17ce), U64_C(0x2c60cd82b595a241), U64_C(0x6ad6c283af163acf), U64_C(0xa5f3ef84e9b8d542), U64_C(0xe345e085f33b4dcc), U64_C(0x2982f186dda3f843), U64_C(0x6f34fe87c72060cd), U64_C(0xaac8ab8851e23b44), U64_C(0xec7ea4894b61a3ca), U64_C(0x26b9b58a65f91645), U64_C(0x600fba8b7f7a8ecb), U64_C(0xaf2a978c39d46146), U64_C(0xe99c988d2357f9c8), U64_C(0x235b898e0dcf4c47), U64_C(0x65ed868f174cd4c9), U64_C(0xb4be23903c56fa48), U64_C(0xf2082c9126d562c6), U64_C(0x38cf3d92084dd749), U64_C(0x7e79329312ce4fc7), U64_C(0xb15c1f945460a04a), U64_C(0xf7ea10954ee338c4), U64_C(0x3d2d0196607b8d4b), U64_C(0x7b9b0e977af815c5), U64_C(0xbe675b98ec3a4e4c), U64_C(0xf8d15499f6b9d6c2), U64_C(0x3216459ad821634d), U64_C(0x74a04a9bc2a2fbc3), U64_C(0xbb85679c840c144e), U64_C(0xfd33689d9e8f8cc0), U64_C(0x37f4799eb017394f), U64_C(0x7142769faa94a1c1), U64_C(0x88522ea0e6236550), U64_C(0xcee421a1fca0fdde), U64_C(0x042330a2d2384851), U64_C(0x42953fa3c8bbd0df), U64_C(0x8db012a48e153f52), U64_C(0xcb061da59496a7dc), U64_C(0x01c10ca6ba0e1253), U64_C(0x477703a7a08d8add), U64_C(0x828b56a8364fd154), U64_C(0xc43d59a92ccc49da), U64_C(0x0efa48aa0254fc55), U64_C(0x484c47ab18d764db), U64_C(0x87696aac5e798b56), U64_C(0xc1df65ad44fa13d8), U64_C(0x0b1874ae6a62a657), U64_C(0x4dae7baf70e13ed9), U64_C(0x9cfddeb05bfb1058), U64_C(0xda4bd1b1417888d6), U64_C(0x108cc0b26fe03d59), U64_C(0x563acfb37563a5d7), U64_C(0x991fe2b433cd4a5a), U64_C(0xdfa9edb5294ed2d4), U64_C(0x156efcb607d6675b), U64_C(0x53d8f3b71d55ffd5), U64_C(0x9624a6b88b97a45c), U64_C(0xd092a9b991143cd2), U64_C(0x1a55b8babf8c895d), U64_C(0x5ce3b7bba50f11d3), U64_C(0x93c69abce3a1fe5e), U64_C(0xd57095bdf92266d0), U64_C(0x1fb784bed7bad35f), U64_C(0x59018bbfcd394bd1), U64_C(0xf09734c04fc94660), U64_C(0xb6213bc1554adeee), U64_C(0x7ce62ac27bd26b61), U64_C(0x3a5025c36151f3ef), U64_C(0xf57508c427ff1c62), U64_C(0xb3c307c53d7c84ec), U64_C(0x790416c613e43163), U64_C(0x3fb219c70967a9ed), U64_C(0xfa4e4cc89fa5f264), U64_C(0xbcf843c985266aea), U64_C(0x763f52caabbedf65), U64_C(0x30895dcbb13d47eb), U64_C(0xffac70ccf793a866), U64_C(0xb91a7fcded1030e8), U64_C(0x73dd6ecec3888567), U64_C(0x356b61cfd90b1de9), U64_C(0xe438c4d0f2113368), U64_C(0xa28ecbd1e892abe6), U64_C(0x6849dad2c60a1e69), U64_C(0x2effd5d3dc8986e7), U64_C(0xe1daf8d49a27696a), U64_C(0xa76cf7d580a4f1e4), U64_C(0x6dabe6d6ae3c446b), U64_C(0x2b1de9d7b4bfdce5), U64_C(0xeee1bcd8227d876c), U64_C(0xa857b3d938fe1fe2), U64_C(0x6290a2da1666aa6d), U64_C(0x2426addb0ce532e3), U64_C(0xeb0380dc4a4bdd6e), U64_C(0xadb58fdd50c845e0), U64_C(0x67729ede7e50f06f), U64_C(0x21c491df64d368e1), U64_C(0xd8d4c9e02864ac70), U64_C(0x9e62c6e132e734fe), U64_C(0x54a5d7e21c7f8171), U64_C(0x1213d8e306fc19ff), U64_C(0xdd36f5e44052f672), U64_C(0x9b80fae55ad16efc), U64_C(0x5147ebe67449db73), U64_C(0x17f1e4e76eca43fd), U64_C(0xd20db1e8f8081874), U64_C(0x94bbbee9e28b80fa), U64_C(0x5e7cafeacc133575), U64_C(0x18caa0ebd690adfb), U64_C(0xd7ef8dec903e4276), U64_C(0x915982ed8abddaf8), U64_C(0x5b9e93eea4256f77), U64_C(0x1d289cefbea6f7f9), U64_C(0xcc7b39f095bcd978), U64_C(0x8acd36f18f3f41f6), U64_C(0x400a27f2a1a7f479), U64_C(0x06bc28f3bb246cf7), U64_C(0xc99905f4fd8a837a), U64_C(0x8f2f0af5e7091bf4), U64_C(0x45e81bf6c991ae7b), U64_C(0x035e14f7d31236f5), U64_C(0xc6a241f845d06d7c), U64_C(0x80144ef95f53f5f2), U64_C(0x4ad35ffa71cb407d), U64_C(0x0c6550fb6b48d8f3), U64_C(0xc3407dfc2de6377e), U64_C(0x85f672fd3765aff0), U64_C(0x4f3163fe19fd1a7f), U64_C(0x09876cff037e82f1) }, /* 7 */ { U64_C(0x0000000000000000), U64_C(0x83478b07b2468764), U64_C(0x1b8e0b0e798c13c8), U64_C(0x98c98009cbca94ac), U64_C(0x3601161cf205268d), U64_C(0xb5469d1b4043a1e9), U64_C(0x2d8f1d128b893545), U64_C(0xaec8961539cfb221), U64_C(0x6c022c38f90a4c07), U64_C(0xef45a73f4b4ccb63), U64_C(0x778c273680865fcf), U64_C(0xf4cbac3132c0d8ab), U64_C(0x5a033a240b0f6a8a), U64_C(0xd944b123b949edee), U64_C(0x418d312a72837942), U64_C(0xc2caba2dc0c5fe26), U64_C(0xd8045870ef14980e), U64_C(0x5b43d3775d521f6a), U64_C(0xc38a537e96988bc6), U64_C(0x40cdd87924de0ca2), U64_C(0xee054e6c1d11be83), U64_C(0x6d42c56baf5739e7), U64_C(0xf58b4562649dad4b), U64_C(0x76ccce65d6db2a2f), U64_C(0xb4067448161ed409), U64_C(0x3741ff4fa458536d), U64_C(0xaf887f466f92c7c1), U64_C(0x2ccff441ddd440a5), U64_C(0x82076254e41bf284), U64_C(0x0140e953565d75e0), U64_C(0x9989695a9d97e14c), U64_C(0x1acee25d2fd16628), U64_C(0xad08b0e0c3282d1c), U64_C(0x2e4f3be7716eaa78), U64_C(0xb686bbeebaa43ed4), U64_C(0x35c130e908e2b9b0), U64_C(0x9b09a6fc312d0b91), U64_C(0x184e2dfb836b8cf5), U64_C(0x8087adf248a11859), U64_C(0x03c026f5fae79f3d), U64_C(0xc10a9cd83a22611b), U64_C(0x424d17df8864e67f), U64_C(0xda8497d643ae72d3), U64_C(0x59c31cd1f1e8f5b7), U64_C(0xf70b8ac4c8274796), U64_C(0x744c01c37a61c0f2), U64_C(0xec8581cab1ab545e), U64_C(0x6fc20acd03edd33a), U64_C(0x750ce8902c3cb512), U64_C(0xf64b63979e7a3276), U64_C(0x6e82e39e55b0a6da), U64_C(0xedc56899e7f621be), U64_C(0x430dfe8cde39939f), U64_C(0xc04a758b6c7f14fb), U64_C(0x5883f582a7b58057), U64_C(0xdbc47e8515f30733), U64_C(0x190ec4a8d536f915), U64_C(0x9a494faf67707e71), U64_C(0x0280cfa6acbaeadd), U64_C(0x81c744a11efc6db9), U64_C(0x2f0fd2b42733df98), U64_C(0xac4859b3957558fc), U64_C(0x3481d9ba5ebfcc50), U64_C(0xb7c652bdecf94b34), U64_C(0x47107ddd9b505a38), U64_C(0xc457f6da2916dd5c), U64_C(0x5c9e76d3e2dc49f0), U64_C(0xdfd9fdd4509ace94), U64_C(0x71116bc169557cb5), U64_C(0xf256e0c6db13fbd1), U64_C(0x6a9f60cf10d96f7d), U64_C(0xe9d8ebc8a29fe819), U64_C(0x2b1251e5625a163f), U64_C(0xa855dae2d01c915b), U64_C(0x309c5aeb1bd605f7), U64_C(0xb3dbd1eca9908293), U64_C(0x1d1347f9905f30b2), U64_C(0x9e54ccfe2219b7d6), U64_C(0x069d4cf7e9d3237a), U64_C(0x85dac7f05b95a41e), U64_C(0x9f1425ad7444c236), U64_C(0x1c53aeaac6024552), U64_C(0x849a2ea30dc8d1fe), U64_C(0x07dda5a4bf8e569a), U64_C(0xa91533b18641e4bb), U64_C(0x2a52b8b6340763df), U64_C(0xb29b38bfffcdf773), U64_C(0x31dcb3b84d8b7017), U64_C(0xf31609958d4e8e31), U64_C(0x705182923f080955), U64_C(0xe898029bf4c29df9), U64_C(0x6bdf899c46841a9d), U64_C(0xc5171f897f4ba8bc), U64_C(0x4650948ecd0d2fd8), U64_C(0xde99148706c7bb74), U64_C(0x5dde9f80b4813c10), U64_C(0xea18cd3d58787724), U64_C(0x695f463aea3ef040), U64_C(0xf196c63321f464ec), U64_C(0x72d14d3493b2e388), U64_C(0xdc19db21aa7d51a9), U64_C(0x5f5e5026183bd6cd), U64_C(0xc797d02fd3f14261), U64_C(0x44d05b2861b7c505), U64_C(0x861ae105a1723b23), U64_C(0x055d6a021334bc47), U64_C(0x9d94ea0bd8fe28eb), U64_C(0x1ed3610c6ab8af8f), U64_C(0xb01bf71953771dae), U64_C(0x335c7c1ee1319aca), U64_C(0xab95fc172afb0e66), U64_C(0x28d2771098bd8902), U64_C(0x321c954db76cef2a), U64_C(0xb15b1e4a052a684e), U64_C(0x29929e43cee0fce2), U64_C(0xaad515447ca67b86), U64_C(0x041d83514569c9a7), U64_C(0x875a0856f72f4ec3), U64_C(0x1f93885f3ce5da6f), U64_C(0x9cd403588ea35d0b), U64_C(0x5e1eb9754e66a32d), U64_C(0xdd593272fc202449), U64_C(0x4590b27b37eab0e5), U64_C(0xc6d7397c85ac3781), U64_C(0x681faf69bc6385a0), U64_C(0xeb58246e0e2502c4), U64_C(0x7391a467c5ef9668), U64_C(0xf0d62f6077a9110c), U64_C(0x8e20faa72ba0b470), U64_C(0x0d6771a099e63314), U64_C(0x95aef1a9522ca7b8), U64_C(0x16e97aaee06a20dc), U64_C(0xb821ecbbd9a592fd), U64_C(0x3b6667bc6be31599), U64_C(0xa3afe7b5a0298135), U64_C(0x20e86cb2126f0651), U64_C(0xe222d69fd2aaf877), U64_C(0x61655d9860ec7f13), U64_C(0xf9acdd91ab26ebbf), U64_C(0x7aeb569619606cdb), U64_C(0xd423c08320afdefa), U64_C(0x57644b8492e9599e), U64_C(0xcfadcb8d5923cd32), U64_C(0x4cea408aeb654a56), U64_C(0x5624a2d7c4b42c7e), U64_C(0xd56329d076f2ab1a), U64_C(0x4daaa9d9bd383fb6), U64_C(0xceed22de0f7eb8d2), U64_C(0x6025b4cb36b10af3), U64_C(0xe3623fcc84f78d97), U64_C(0x7babbfc54f3d193b), U64_C(0xf8ec34c2fd7b9e5f), U64_C(0x3a268eef3dbe6079), U64_C(0xb96105e88ff8e71d), U64_C(0x21a885e1443273b1), U64_C(0xa2ef0ee6f674f4d5), U64_C(0x0c2798f3cfbb46f4), U64_C(0x8f6013f47dfdc190), U64_C(0x17a993fdb637553c), U64_C(0x94ee18fa0471d258), U64_C(0x23284a47e888996c), U64_C(0xa06fc1405ace1e08), U64_C(0x38a6414991048aa4), U64_C(0xbbe1ca4e23420dc0), U64_C(0x15295c5b1a8dbfe1), U64_C(0x966ed75ca8cb3885), U64_C(0x0ea757556301ac29), U64_C(0x8de0dc52d1472b4d), U64_C(0x4f2a667f1182d56b), U64_C(0xcc6ded78a3c4520f), U64_C(0x54a46d71680ec6a3), U64_C(0xd7e3e676da4841c7), U64_C(0x792b7063e387f3e6), U64_C(0xfa6cfb6451c17482), U64_C(0x62a57b6d9a0be02e), U64_C(0xe1e2f06a284d674a), U64_C(0xfb2c1237079c0162), U64_C(0x786b9930b5da8606), U64_C(0xe0a219397e1012aa), U64_C(0x63e5923ecc5695ce), U64_C(0xcd2d042bf59927ef), U64_C(0x4e6a8f2c47dfa08b), U64_C(0xd6a30f258c153427), U64_C(0x55e484223e53b343), U64_C(0x972e3e0ffe964d65), U64_C(0x1469b5084cd0ca01), U64_C(0x8ca03501871a5ead), U64_C(0x0fe7be06355cd9c9), U64_C(0xa12f28130c936be8), U64_C(0x2268a314bed5ec8c), U64_C(0xbaa1231d751f7820), U64_C(0x39e6a81ac759ff44), U64_C(0xc930877ab0f0ee48), U64_C(0x4a770c7d02b6692c), U64_C(0xd2be8c74c97cfd80), U64_C(0x51f907737b3a7ae4), U64_C(0xff31916642f5c8c5), U64_C(0x7c761a61f0b34fa1), U64_C(0xe4bf9a683b79db0d), U64_C(0x67f8116f893f5c69), U64_C(0xa532ab4249faa24f), U64_C(0x26752045fbbc252b), U64_C(0xbebca04c3076b187), U64_C(0x3dfb2b4b823036e3), U64_C(0x9333bd5ebbff84c2), U64_C(0x1074365909b903a6), U64_C(0x88bdb650c273970a), U64_C(0x0bfa3d577035106e), U64_C(0x1134df0a5fe47646), U64_C(0x9273540deda2f122), U64_C(0x0abad4042668658e), U64_C(0x89fd5f03942ee2ea), U64_C(0x2735c916ade150cb), U64_C(0xa47242111fa7d7af), U64_C(0x3cbbc218d46d4303), U64_C(0xbffc491f662bc467), U64_C(0x7d36f332a6ee3a41), U64_C(0xfe71783514a8bd25), U64_C(0x66b8f83cdf622989), U64_C(0xe5ff733b6d24aeed), U64_C(0x4b37e52e54eb1ccc), U64_C(0xc8706e29e6ad9ba8), U64_C(0x50b9ee202d670f04), U64_C(0xd3fe65279f218860), U64_C(0x6438379a73d8c354), U64_C(0xe77fbc9dc19e4430), U64_C(0x7fb63c940a54d09c), U64_C(0xfcf1b793b81257f8), U64_C(0x5239218681dde5d9), U64_C(0xd17eaa81339b62bd), U64_C(0x49b72a88f851f611), U64_C(0xcaf0a18f4a177175), U64_C(0x083a1ba28ad28f53), U64_C(0x8b7d90a538940837), U64_C(0x13b410acf35e9c9b), U64_C(0x90f39bab41181bff), U64_C(0x3e3b0dbe78d7a9de), U64_C(0xbd7c86b9ca912eba), U64_C(0x25b506b0015bba16), U64_C(0xa6f28db7b31d3d72), U64_C(0xbc3c6fea9ccc5b5a), U64_C(0x3f7be4ed2e8adc3e), U64_C(0xa7b264e4e5404892), U64_C(0x24f5efe35706cff6), U64_C(0x8a3d79f66ec97dd7), U64_C(0x097af2f1dc8ffab3), U64_C(0x91b372f817456e1f), U64_C(0x12f4f9ffa503e97b), U64_C(0xd03e43d265c6175d), U64_C(0x5379c8d5d7809039), U64_C(0xcbb048dc1c4a0495), U64_C(0x48f7c3dbae0c83f1), U64_C(0xe63f55ce97c331d0), U64_C(0x6578dec92585b6b4), U64_C(0xfdb15ec0ee4f2218), U64_C(0x7ef6d5c75c09a57c) }, }; static u64 strido (u64 l) { u64 t = 0; t^= stribog_table[0][(l >> 0) & 255]; t^= stribog_table[1][(l >> 8) & 255]; t^= stribog_table[2][(l >> 16) & 255]; t^= stribog_table[3][(l >> 24) & 255]; t^= stribog_table[4][(l >> 32) & 255]; t^= stribog_table[5][(l >> 40) & 255]; t^= stribog_table[6][(l >> 48) & 255]; t^= stribog_table[7][(l >> 56) & 255]; return t; } #endif static const u64 C16[13][16] = { { U64_C(0xdd806559f2a64507), U64_C(0x05767436cc744d23), U64_C(0xa2422a08a460d315), U64_C(0x4b7ce09192676901), U64_C(0x714eb88d7585c4fc), U64_C(0x2f6a76432e45d016), U64_C(0xebcb2f81c0657c1f), U64_C(0xb1085bda1ecadae9) }, { U64_C(0xe679047021b19bb7), U64_C(0x55dda21bd7cbcd56), U64_C(0x5cb561c2db0aa7ca), U64_C(0x9ab5176b12d69958), U64_C(0x61d55e0f16b50131), U64_C(0xf3feea720a232b98), U64_C(0x4fe39d460f70b5d7), U64_C(0x6fa3b58aa99d2f1a) }, { U64_C(0x991e96f50aba0ab2), U64_C(0xc2b6f443867adb31), U64_C(0xc1c93a376062db09), U64_C(0xd3e20fe490359eb1), U64_C(0xf2ea7514b1297b7b), U64_C(0x06f15e5f529c1f8b), U64_C(0x0a39fc286a3d8435), U64_C(0xf574dcac2bce2fc7) }, { U64_C(0x220cbebc84e3d12e), U64_C(0x3453eaa193e837f1), U64_C(0xd8b71333935203be), U64_C(0xa9d72c82ed03d675), U64_C(0x9d721cad685e353f), U64_C(0x488e857e335c3c7d), U64_C(0xf948e1a05d71e4dd), U64_C(0xef1fdfb3e81566d2) }, { U64_C(0x601758fd7c6cfe57), U64_C(0x7a56a27ea9ea63f5), U64_C(0xdfff00b723271a16), U64_C(0xbfcd1747253af5a3), U64_C(0x359e35d7800fffbd), U64_C(0x7f151c1f1686104a), U64_C(0x9a3f410c6ca92363), U64_C(0x4bea6bacad474799) }, { U64_C(0xfa68407a46647d6e), U64_C(0xbf71c57236904f35), U64_C(0x0af21f66c2bec6b6), U64_C(0xcffaa6b71c9ab7b4), U64_C(0x187f9ab49af08ec6), U64_C(0x2d66c4f95142a46c), U64_C(0x6fa4c33b7a3039c0), U64_C(0xae4faeae1d3ad3d9) }, { U64_C(0x8886564d3a14d493), U64_C(0x3517454ca23c4af3), U64_C(0x06476983284a0504), U64_C(0x0992abc52d822c37), U64_C(0xd3473e33197a93c9), U64_C(0x399ec6c7e6bf87c9), U64_C(0x51ac86febf240954), U64_C(0xf4c70e16eeaac5ec) }, { U64_C(0xa47f0dd4bf02e71e), U64_C(0x36acc2355951a8d9), U64_C(0x69d18d2bd1a5c42f), U64_C(0xf4892bcb929b0690), U64_C(0x89b4443b4ddbc49a), U64_C(0x4eb7f8719c36de1e), U64_C(0x03e7aa020c6e4141), U64_C(0x9b1f5b424d93c9a7) }, { U64_C(0x7261445183235adb), U64_C(0x0e38dc92cb1f2a60), U64_C(0x7b2b8a9aa6079c54), U64_C(0x800a440bdbb2ceb1), U64_C(0x3cd955b7e00d0984), U64_C(0x3a7d3a1b25894224), U64_C(0x944c9ad8ec165fde), U64_C(0x378f5a541631229b) }, { U64_C(0x74b4c7fb98459ced), U64_C(0x3698fad1153bb6c3), U64_C(0x7a1e6c303b7652f4), U64_C(0x9fe76702af69334b), U64_C(0x1fffe18a1b336103), U64_C(0x8941e71cff8a78db), U64_C(0x382ae548b2e4f3f3), U64_C(0xabbedea680056f52) }, { U64_C(0x6bcaa4cd81f32d1b), U64_C(0xdea2594ac06fd85d), U64_C(0xefbacd1d7d476e98), U64_C(0x8a1d71efea48b9ca), U64_C(0x2001802114846679), U64_C(0xd8fa6bbbebab0761), U64_C(0x3002c6cd635afe94), U64_C(0x7bcd9ed0efc889fb) }, { U64_C(0x48bc924af11bd720), U64_C(0xfaf417d5d9b21b99), U64_C(0xe71da4aa88e12852), U64_C(0x5d80ef9d1891cc86), U64_C(0xf82012d430219f9b), U64_C(0xcda43c32bcdf1d77), U64_C(0xd21380b00449b17a), U64_C(0x378ee767f11631ba) }, }; static void LPSX (u64 *out, u64 *a, const u64 *b) { int i; u64 temp[8]; for (i = 0; i < 8; i++) temp[i] = a[i] ^ b[i]; for (i = 0; i < 8; i++) { u64 l = ((u64) Pi[ (temp[7] >> (i * 8)) & 0xff] << (7 * 8)) | ((u64) Pi[ (temp[6] >> (i * 8)) & 0xff] << (6 * 8)) | ((u64) Pi[ (temp[5] >> (i * 8)) & 0xff] << (5 * 8)) | ((u64) Pi[ (temp[4] >> (i * 8)) & 0xff] << (4 * 8)) | ((u64) Pi[ (temp[3] >> (i * 8)) & 0xff] << (3 * 8)) | ((u64) Pi[ (temp[2] >> (i * 8)) & 0xff] << (2 * 8)) | ((u64) Pi[ (temp[1] >> (i * 8)) & 0xff] << (1 * 8)) | ((u64) Pi[ (temp[0] >> (i * 8)) & 0xff] << (0 * 8)) | 0; out[i] = strido(l); } } static void xor (u64 *out, u64 *in) { int i; for (i = 0; i < 8; i++) out[i] ^= in[i]; } static void g (u64 *h, u64 *m, u64 *N) { u64 K[8]; u64 T[8]; int i; LPSX (K, h, N); for (i = 0; i < 12; i++) { LPSX (T, K, i == 0 ? m : T); LPSX (K, K, C16[i]); } xor (T, K); xor (T, m); xor (h, T); } static unsigned int transform64 (void *context, const unsigned char *inbuf_arg); static void stribog_init_512 (void *context) { STRIBOG_CONTEXT *hd = context; memset (hd, 0, sizeof (*hd)); hd->bctx.blocksize = 64; hd->bctx.bwrite = transform64; } static void stribog_init_256 (void *context) { STRIBOG_CONTEXT *hd = context; stribog_init_512 (context); memset (hd->h, 1, 64); } static void transform (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count) { u64 M[8]; u64 l; int i; -#ifndef WORDS_BIGENDIAN - memcpy (M, data, 64); -#else - { - byte *p2; - - for (i = 0, p2 = (byte *) M; i < 8; i++, p2 += 8) - { - p2[7] = *data++; - p2[6] = *data++; - p2[5] = *data++; - p2[4] = *data++; - p2[3] = *data++; - p2[2] = *data++; - p2[1] = *data++; - p2[0] = *data++; - } - } -#endif + for (i = 0; i < 8; i++) + M[i] = buf_get_le64(data + i * 8); g (hd->h, M, hd->N); l = hd->N[0]; hd->N[0] += count; if (hd->N[0] < l) { /* overflow */ for (i = 1; i < 8; i++) { hd->N[i]++; if (hd->N[i] != 0) break; } } hd->Sigma[0] += M[0]; for (i = 1; i < 8; i++) if (hd->Sigma[i-1] < M[i-1]) hd->Sigma[i] += M[i] + 1; else hd->Sigma[i] += M[i]; } static unsigned int transform64 (void *context, const unsigned char *inbuf_arg) { STRIBOG_CONTEXT *hd = context; transform (hd, inbuf_arg, 64 * 8); return /* burn_stack */ 768; } /* The routine finally terminates the computation and returns the digest. The handle is prepared for a new cycle, but adding bytes to the handle will the destroy the returned buffer. Returns: 32 bytes with the message the digest. */ static void stribog_final (void *context) { STRIBOG_CONTEXT *hd = context; u64 Z[8] = {}; int i; _gcry_md_block_write (context, NULL, 0); /* flush */ ; /* PAD. It does not count towards message length */ i = hd->bctx.count; /* After flush we have at least one byte free) */ hd->bctx.buf[i++] = 1; while (i < 64) hd->bctx.buf[i++] = 0; transform (hd, hd->bctx.buf, hd->bctx.count * 8); g (hd->h, hd->N, Z); g (hd->h, hd->Sigma, Z); -#ifdef WORDS_BIGENDIAN for (i = 0; i < 8; i++) - { - u64 T = hd->h[i]; - T = ((T & U64_C(0x00ff00ff00ff00ff)) << 8) | - ((T & U64_C(0xff00ff00ff00ff00)) >> 8); - T = ((T & U64_C(0x0000ffff0000ffff)) << 16) | - ((T & U64_C(0xffff0000ffff0000)) >> 16); - T = ((T & U64_C(0x00000000ffffffff)) << 32) | - ((T & U64_C(0xffffffff00000000)) >> 32); - hd->h[i] = T; - } -#endif + hd->h[i] = le_bswap64(hd->h[i]); _gcry_burn_stack (768); } static byte * stribog_read_512 (void *context) { STRIBOG_CONTEXT *hd = context; return hd->result; } static byte * stribog_read_256 (void *context) { STRIBOG_CONTEXT *hd = context; return hd->result + 32; } gcry_md_spec_t _gcry_digest_spec_stribog_256 = { "STRIBOG256", NULL, 0, NULL, 32, stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read_256, sizeof (STRIBOG_CONTEXT) }; gcry_md_spec_t _gcry_digest_spec_stribog_512 = { "STRIBOG512", NULL, 0, NULL, 64, stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read_512, sizeof (STRIBOG_CONTEXT) }; diff --git a/cipher/tiger.c b/cipher/tiger.c index 8f5959b8..df16098e 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -1,878 +1,850 @@ /* tiger.c - The TIGER hash function * Copyright (C) 1998, 2001, 2002, 2003, 2010 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* See http://www.cs.technion.ac.il/~biham/Reports/Tiger/ */ #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "hash-common.h" +#include "bithelp.h" +#include "bufhelp.h" /* We really need a 64 bit type for this code. */ #ifdef HAVE_U64_TYPEDEF typedef struct { gcry_md_block_ctx_t bctx; u64 a, b, c; int variant; /* 0 = old code, 1 = fixed code, 2 - TIGER2. */ } TIGER_CONTEXT; /********************************* * Okay, okay, this is not the fastest code - improvements are welcome. * */ /* Some test vectors: * "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A * "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 * "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" * 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 * "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789" * 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham" * 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" * "eedings of Fast Software Encryption 3, Cambridge." * EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 * "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc" * "eedings of Fast Software Encryption 3, Cambridge, 1996." * 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF" * "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-" * 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 */ static u64 sbox1[256] = { U64_C(0x02aab17cf7e90c5e) /* 0 */, U64_C(0xac424b03e243a8ec) /* 1 */, U64_C(0x72cd5be30dd5fcd3) /* 2 */, U64_C(0x6d019b93f6f97f3a) /* 3 */, U64_C(0xcd9978ffd21f9193) /* 4 */, U64_C(0x7573a1c9708029e2) /* 5 */, U64_C(0xb164326b922a83c3) /* 6 */, U64_C(0x46883eee04915870) /* 7 */, U64_C(0xeaace3057103ece6) /* 8 */, U64_C(0xc54169b808a3535c) /* 9 */, U64_C(0x4ce754918ddec47c) /* 10 */, U64_C(0x0aa2f4dfdc0df40c) /* 11 */, U64_C(0x10b76f18a74dbefa) /* 12 */, U64_C(0xc6ccb6235ad1ab6a) /* 13 */, U64_C(0x13726121572fe2ff) /* 14 */, U64_C(0x1a488c6f199d921e) /* 15 */, U64_C(0x4bc9f9f4da0007ca) /* 16 */, U64_C(0x26f5e6f6e85241c7) /* 17 */, U64_C(0x859079dbea5947b6) /* 18 */, U64_C(0x4f1885c5c99e8c92) /* 19 */, U64_C(0xd78e761ea96f864b) /* 20 */, U64_C(0x8e36428c52b5c17d) /* 21 */, U64_C(0x69cf6827373063c1) /* 22 */, U64_C(0xb607c93d9bb4c56e) /* 23 */, U64_C(0x7d820e760e76b5ea) /* 24 */, U64_C(0x645c9cc6f07fdc42) /* 25 */, U64_C(0xbf38a078243342e0) /* 26 */, U64_C(0x5f6b343c9d2e7d04) /* 27 */, U64_C(0xf2c28aeb600b0ec6) /* 28 */, U64_C(0x6c0ed85f7254bcac) /* 29 */, U64_C(0x71592281a4db4fe5) /* 30 */, U64_C(0x1967fa69ce0fed9f) /* 31 */, U64_C(0xfd5293f8b96545db) /* 32 */, U64_C(0xc879e9d7f2a7600b) /* 33 */, U64_C(0x860248920193194e) /* 34 */, U64_C(0xa4f9533b2d9cc0b3) /* 35 */, U64_C(0x9053836c15957613) /* 36 */, U64_C(0xdb6dcf8afc357bf1) /* 37 */, U64_C(0x18beea7a7a370f57) /* 38 */, U64_C(0x037117ca50b99066) /* 39 */, U64_C(0x6ab30a9774424a35) /* 40 */, U64_C(0xf4e92f02e325249b) /* 41 */, U64_C(0x7739db07061ccae1) /* 42 */, U64_C(0xd8f3b49ceca42a05) /* 43 */, U64_C(0xbd56be3f51382f73) /* 44 */, U64_C(0x45faed5843b0bb28) /* 45 */, U64_C(0x1c813d5c11bf1f83) /* 46 */, U64_C(0x8af0e4b6d75fa169) /* 47 */, U64_C(0x33ee18a487ad9999) /* 48 */, U64_C(0x3c26e8eab1c94410) /* 49 */, U64_C(0xb510102bc0a822f9) /* 50 */, U64_C(0x141eef310ce6123b) /* 51 */, U64_C(0xfc65b90059ddb154) /* 52 */, U64_C(0xe0158640c5e0e607) /* 53 */, U64_C(0x884e079826c3a3cf) /* 54 */, U64_C(0x930d0d9523c535fd) /* 55 */, U64_C(0x35638d754e9a2b00) /* 56 */, U64_C(0x4085fccf40469dd5) /* 57 */, U64_C(0xc4b17ad28be23a4c) /* 58 */, U64_C(0xcab2f0fc6a3e6a2e) /* 59 */, U64_C(0x2860971a6b943fcd) /* 60 */, U64_C(0x3dde6ee212e30446) /* 61 */, U64_C(0x6222f32ae01765ae) /* 62 */, U64_C(0x5d550bb5478308fe) /* 63 */, U64_C(0xa9efa98da0eda22a) /* 64 */, U64_C(0xc351a71686c40da7) /* 65 */, U64_C(0x1105586d9c867c84) /* 66 */, U64_C(0xdcffee85fda22853) /* 67 */, U64_C(0xccfbd0262c5eef76) /* 68 */, U64_C(0xbaf294cb8990d201) /* 69 */, U64_C(0xe69464f52afad975) /* 70 */, U64_C(0x94b013afdf133e14) /* 71 */, U64_C(0x06a7d1a32823c958) /* 72 */, U64_C(0x6f95fe5130f61119) /* 73 */, U64_C(0xd92ab34e462c06c0) /* 74 */, U64_C(0xed7bde33887c71d2) /* 75 */, U64_C(0x79746d6e6518393e) /* 76 */, U64_C(0x5ba419385d713329) /* 77 */, U64_C(0x7c1ba6b948a97564) /* 78 */, U64_C(0x31987c197bfdac67) /* 79 */, U64_C(0xde6c23c44b053d02) /* 80 */, U64_C(0x581c49fed002d64d) /* 81 */, U64_C(0xdd474d6338261571) /* 82 */, U64_C(0xaa4546c3e473d062) /* 83 */, U64_C(0x928fce349455f860) /* 84 */, U64_C(0x48161bbacaab94d9) /* 85 */, U64_C(0x63912430770e6f68) /* 86 */, U64_C(0x6ec8a5e602c6641c) /* 87 */, U64_C(0x87282515337ddd2b) /* 88 */, U64_C(0x2cda6b42034b701b) /* 89 */, U64_C(0xb03d37c181cb096d) /* 90 */, U64_C(0xe108438266c71c6f) /* 91 */, U64_C(0x2b3180c7eb51b255) /* 92 */, U64_C(0xdf92b82f96c08bbc) /* 93 */, U64_C(0x5c68c8c0a632f3ba) /* 94 */, U64_C(0x5504cc861c3d0556) /* 95 */, U64_C(0xabbfa4e55fb26b8f) /* 96 */, U64_C(0x41848b0ab3baceb4) /* 97 */, U64_C(0xb334a273aa445d32) /* 98 */, U64_C(0xbca696f0a85ad881) /* 99 */, U64_C(0x24f6ec65b528d56c) /* 100 */, U64_C(0x0ce1512e90f4524a) /* 101 */, U64_C(0x4e9dd79d5506d35a) /* 102 */, U64_C(0x258905fac6ce9779) /* 103 */, U64_C(0x2019295b3e109b33) /* 104 */, U64_C(0xf8a9478b73a054cc) /* 105 */, U64_C(0x2924f2f934417eb0) /* 106 */, U64_C(0x3993357d536d1bc4) /* 107 */, U64_C(0x38a81ac21db6ff8b) /* 108 */, U64_C(0x47c4fbf17d6016bf) /* 109 */, U64_C(0x1e0faadd7667e3f5) /* 110 */, U64_C(0x7abcff62938beb96) /* 111 */, U64_C(0xa78dad948fc179c9) /* 112 */, U64_C(0x8f1f98b72911e50d) /* 113 */, U64_C(0x61e48eae27121a91) /* 114 */, U64_C(0x4d62f7ad31859808) /* 115 */, U64_C(0xeceba345ef5ceaeb) /* 116 */, U64_C(0xf5ceb25ebc9684ce) /* 117 */, U64_C(0xf633e20cb7f76221) /* 118 */, U64_C(0xa32cdf06ab8293e4) /* 119 */, U64_C(0x985a202ca5ee2ca4) /* 120 */, U64_C(0xcf0b8447cc8a8fb1) /* 121 */, U64_C(0x9f765244979859a3) /* 122 */, U64_C(0xa8d516b1a1240017) /* 123 */, U64_C(0x0bd7ba3ebb5dc726) /* 124 */, U64_C(0xe54bca55b86adb39) /* 125 */, U64_C(0x1d7a3afd6c478063) /* 126 */, U64_C(0x519ec608e7669edd) /* 127 */, U64_C(0x0e5715a2d149aa23) /* 128 */, U64_C(0x177d4571848ff194) /* 129 */, U64_C(0xeeb55f3241014c22) /* 130 */, U64_C(0x0f5e5ca13a6e2ec2) /* 131 */, U64_C(0x8029927b75f5c361) /* 132 */, U64_C(0xad139fabc3d6e436) /* 133 */, U64_C(0x0d5df1a94ccf402f) /* 134 */, U64_C(0x3e8bd948bea5dfc8) /* 135 */, U64_C(0xa5a0d357bd3ff77e) /* 136 */, U64_C(0xa2d12e251f74f645) /* 137 */, U64_C(0x66fd9e525e81a082) /* 138 */, U64_C(0x2e0c90ce7f687a49) /* 139 */, U64_C(0xc2e8bcbeba973bc5) /* 140 */, U64_C(0x000001bce509745f) /* 141 */, U64_C(0x423777bbe6dab3d6) /* 142 */, U64_C(0xd1661c7eaef06eb5) /* 143 */, U64_C(0xa1781f354daacfd8) /* 144 */, U64_C(0x2d11284a2b16affc) /* 145 */, U64_C(0xf1fc4f67fa891d1f) /* 146 */, U64_C(0x73ecc25dcb920ada) /* 147 */, U64_C(0xae610c22c2a12651) /* 148 */, U64_C(0x96e0a810d356b78a) /* 149 */, U64_C(0x5a9a381f2fe7870f) /* 150 */, U64_C(0xd5ad62ede94e5530) /* 151 */, U64_C(0xd225e5e8368d1427) /* 152 */, U64_C(0x65977b70c7af4631) /* 153 */, U64_C(0x99f889b2de39d74f) /* 154 */, U64_C(0x233f30bf54e1d143) /* 155 */, U64_C(0x9a9675d3d9a63c97) /* 156 */, U64_C(0x5470554ff334f9a8) /* 157 */, U64_C(0x166acb744a4f5688) /* 158 */, U64_C(0x70c74caab2e4aead) /* 159 */, U64_C(0xf0d091646f294d12) /* 160 */, U64_C(0x57b82a89684031d1) /* 161 */, U64_C(0xefd95a5a61be0b6b) /* 162 */, U64_C(0x2fbd12e969f2f29a) /* 163 */, U64_C(0x9bd37013feff9fe8) /* 164 */, U64_C(0x3f9b0404d6085a06) /* 165 */, U64_C(0x4940c1f3166cfe15) /* 166 */, U64_C(0x09542c4dcdf3defb) /* 167 */, U64_C(0xb4c5218385cd5ce3) /* 168 */, U64_C(0xc935b7dc4462a641) /* 169 */, U64_C(0x3417f8a68ed3b63f) /* 170 */, U64_C(0xb80959295b215b40) /* 171 */, U64_C(0xf99cdaef3b8c8572) /* 172 */, U64_C(0x018c0614f8fcb95d) /* 173 */, U64_C(0x1b14accd1a3acdf3) /* 174 */, U64_C(0x84d471f200bb732d) /* 175 */, U64_C(0xc1a3110e95e8da16) /* 176 */, U64_C(0x430a7220bf1a82b8) /* 177 */, U64_C(0xb77e090d39df210e) /* 178 */, U64_C(0x5ef4bd9f3cd05e9d) /* 179 */, U64_C(0x9d4ff6da7e57a444) /* 180 */, U64_C(0xda1d60e183d4a5f8) /* 181 */, U64_C(0xb287c38417998e47) /* 182 */, U64_C(0xfe3edc121bb31886) /* 183 */, U64_C(0xc7fe3ccc980ccbef) /* 184 */, U64_C(0xe46fb590189bfd03) /* 185 */, U64_C(0x3732fd469a4c57dc) /* 186 */, U64_C(0x7ef700a07cf1ad65) /* 187 */, U64_C(0x59c64468a31d8859) /* 188 */, U64_C(0x762fb0b4d45b61f6) /* 189 */, U64_C(0x155baed099047718) /* 190 */, U64_C(0x68755e4c3d50baa6) /* 191 */, U64_C(0xe9214e7f22d8b4df) /* 192 */, U64_C(0x2addbf532eac95f4) /* 193 */, U64_C(0x32ae3909b4bd0109) /* 194 */, U64_C(0x834df537b08e3450) /* 195 */, U64_C(0xfa209da84220728d) /* 196 */, U64_C(0x9e691d9b9efe23f7) /* 197 */, U64_C(0x0446d288c4ae8d7f) /* 198 */, U64_C(0x7b4cc524e169785b) /* 199 */, U64_C(0x21d87f0135ca1385) /* 200 */, U64_C(0xcebb400f137b8aa5) /* 201 */, U64_C(0x272e2b66580796be) /* 202 */, U64_C(0x3612264125c2b0de) /* 203 */, U64_C(0x057702bdad1efbb2) /* 204 */, U64_C(0xd4babb8eacf84be9) /* 205 */, U64_C(0x91583139641bc67b) /* 206 */, U64_C(0x8bdc2de08036e024) /* 207 */, U64_C(0x603c8156f49f68ed) /* 208 */, U64_C(0xf7d236f7dbef5111) /* 209 */, U64_C(0x9727c4598ad21e80) /* 210 */, U64_C(0xa08a0896670a5fd7) /* 211 */, U64_C(0xcb4a8f4309eba9cb) /* 212 */, U64_C(0x81af564b0f7036a1) /* 213 */, U64_C(0xc0b99aa778199abd) /* 214 */, U64_C(0x959f1ec83fc8e952) /* 215 */, U64_C(0x8c505077794a81b9) /* 216 */, U64_C(0x3acaaf8f056338f0) /* 217 */, U64_C(0x07b43f50627a6778) /* 218 */, U64_C(0x4a44ab49f5eccc77) /* 219 */, U64_C(0x3bc3d6e4b679ee98) /* 220 */, U64_C(0x9cc0d4d1cf14108c) /* 221 */, U64_C(0x4406c00b206bc8a0) /* 222 */, U64_C(0x82a18854c8d72d89) /* 223 */, U64_C(0x67e366b35c3c432c) /* 224 */, U64_C(0xb923dd61102b37f2) /* 225 */, U64_C(0x56ab2779d884271d) /* 226 */, U64_C(0xbe83e1b0ff1525af) /* 227 */, U64_C(0xfb7c65d4217e49a9) /* 228 */, U64_C(0x6bdbe0e76d48e7d4) /* 229 */, U64_C(0x08df828745d9179e) /* 230 */, U64_C(0x22ea6a9add53bd34) /* 231 */, U64_C(0xe36e141c5622200a) /* 232 */, U64_C(0x7f805d1b8cb750ee) /* 233 */, U64_C(0xafe5c7a59f58e837) /* 234 */, U64_C(0xe27f996a4fb1c23c) /* 235 */, U64_C(0xd3867dfb0775f0d0) /* 236 */, U64_C(0xd0e673de6e88891a) /* 237 */, U64_C(0x123aeb9eafb86c25) /* 238 */, U64_C(0x30f1d5d5c145b895) /* 239 */, U64_C(0xbb434a2dee7269e7) /* 240 */, U64_C(0x78cb67ecf931fa38) /* 241 */, U64_C(0xf33b0372323bbf9c) /* 242 */, U64_C(0x52d66336fb279c74) /* 243 */, U64_C(0x505f33ac0afb4eaa) /* 244 */, U64_C(0xe8a5cd99a2cce187) /* 245 */, U64_C(0x534974801e2d30bb) /* 246 */, U64_C(0x8d2d5711d5876d90) /* 247 */, U64_C(0x1f1a412891bc038e) /* 248 */, U64_C(0xd6e2e71d82e56648) /* 249 */, U64_C(0x74036c3a497732b7) /* 250 */, U64_C(0x89b67ed96361f5ab) /* 251 */, U64_C(0xffed95d8f1ea02a2) /* 252 */, U64_C(0xe72b3bd61464d43d) /* 253 */, U64_C(0xa6300f170bdc4820) /* 254 */, U64_C(0xebc18760ed78a77a) /* 255 */ }; static u64 sbox2[256] = { U64_C(0xe6a6be5a05a12138) /* 256 */, U64_C(0xb5a122a5b4f87c98) /* 257 */, U64_C(0x563c6089140b6990) /* 258 */, U64_C(0x4c46cb2e391f5dd5) /* 259 */, U64_C(0xd932addbc9b79434) /* 260 */, U64_C(0x08ea70e42015aff5) /* 261 */, U64_C(0xd765a6673e478cf1) /* 262 */, U64_C(0xc4fb757eab278d99) /* 263 */, U64_C(0xdf11c6862d6e0692) /* 264 */, U64_C(0xddeb84f10d7f3b16) /* 265 */, U64_C(0x6f2ef604a665ea04) /* 266 */, U64_C(0x4a8e0f0ff0e0dfb3) /* 267 */, U64_C(0xa5edeef83dbcba51) /* 268 */, U64_C(0xfc4f0a2a0ea4371e) /* 269 */, U64_C(0xe83e1da85cb38429) /* 270 */, U64_C(0xdc8ff882ba1b1ce2) /* 271 */, U64_C(0xcd45505e8353e80d) /* 272 */, U64_C(0x18d19a00d4db0717) /* 273 */, U64_C(0x34a0cfeda5f38101) /* 274 */, U64_C(0x0be77e518887caf2) /* 275 */, U64_C(0x1e341438b3c45136) /* 276 */, U64_C(0xe05797f49089ccf9) /* 277 */, U64_C(0xffd23f9df2591d14) /* 278 */, U64_C(0x543dda228595c5cd) /* 279 */, U64_C(0x661f81fd99052a33) /* 280 */, U64_C(0x8736e641db0f7b76) /* 281 */, U64_C(0x15227725418e5307) /* 282 */, U64_C(0xe25f7f46162eb2fa) /* 283 */, U64_C(0x48a8b2126c13d9fe) /* 284 */, U64_C(0xafdc541792e76eea) /* 285 */, U64_C(0x03d912bfc6d1898f) /* 286 */, U64_C(0x31b1aafa1b83f51b) /* 287 */, U64_C(0xf1ac2796e42ab7d9) /* 288 */, U64_C(0x40a3a7d7fcd2ebac) /* 289 */, U64_C(0x1056136d0afbbcc5) /* 290 */, U64_C(0x7889e1dd9a6d0c85) /* 291 */, U64_C(0xd33525782a7974aa) /* 292 */, U64_C(0xa7e25d09078ac09b) /* 293 */, U64_C(0xbd4138b3eac6edd0) /* 294 */, U64_C(0x920abfbe71eb9e70) /* 295 */, U64_C(0xa2a5d0f54fc2625c) /* 296 */, U64_C(0xc054e36b0b1290a3) /* 297 */, U64_C(0xf6dd59ff62fe932b) /* 298 */, U64_C(0x3537354511a8ac7d) /* 299 */, U64_C(0xca845e9172fadcd4) /* 300 */, U64_C(0x84f82b60329d20dc) /* 301 */, U64_C(0x79c62ce1cd672f18) /* 302 */, U64_C(0x8b09a2add124642c) /* 303 */, U64_C(0xd0c1e96a19d9e726) /* 304 */, U64_C(0x5a786a9b4ba9500c) /* 305 */, U64_C(0x0e020336634c43f3) /* 306 */, U64_C(0xc17b474aeb66d822) /* 307 */, U64_C(0x6a731ae3ec9baac2) /* 308 */, U64_C(0x8226667ae0840258) /* 309 */, U64_C(0x67d4567691caeca5) /* 310 */, U64_C(0x1d94155c4875adb5) /* 311 */, U64_C(0x6d00fd985b813fdf) /* 312 */, U64_C(0x51286efcb774cd06) /* 313 */, U64_C(0x5e8834471fa744af) /* 314 */, U64_C(0xf72ca0aee761ae2e) /* 315 */, U64_C(0xbe40e4cdaee8e09a) /* 316 */, U64_C(0xe9970bbb5118f665) /* 317 */, U64_C(0x726e4beb33df1964) /* 318 */, U64_C(0x703b000729199762) /* 319 */, U64_C(0x4631d816f5ef30a7) /* 320 */, U64_C(0xb880b5b51504a6be) /* 321 */, U64_C(0x641793c37ed84b6c) /* 322 */, U64_C(0x7b21ed77f6e97d96) /* 323 */, U64_C(0x776306312ef96b73) /* 324 */, U64_C(0xae528948e86ff3f4) /* 325 */, U64_C(0x53dbd7f286a3f8f8) /* 326 */, U64_C(0x16cadce74cfc1063) /* 327 */, U64_C(0x005c19bdfa52c6dd) /* 328 */, U64_C(0x68868f5d64d46ad3) /* 329 */, U64_C(0x3a9d512ccf1e186a) /* 330 */, U64_C(0x367e62c2385660ae) /* 331 */, U64_C(0xe359e7ea77dcb1d7) /* 332 */, U64_C(0x526c0773749abe6e) /* 333 */, U64_C(0x735ae5f9d09f734b) /* 334 */, U64_C(0x493fc7cc8a558ba8) /* 335 */, U64_C(0xb0b9c1533041ab45) /* 336 */, U64_C(0x321958ba470a59bd) /* 337 */, U64_C(0x852db00b5f46c393) /* 338 */, U64_C(0x91209b2bd336b0e5) /* 339 */, U64_C(0x6e604f7d659ef19f) /* 340 */, U64_C(0xb99a8ae2782ccb24) /* 341 */, U64_C(0xccf52ab6c814c4c7) /* 342 */, U64_C(0x4727d9afbe11727b) /* 343 */, U64_C(0x7e950d0c0121b34d) /* 344 */, U64_C(0x756f435670ad471f) /* 345 */, U64_C(0xf5add442615a6849) /* 346 */, U64_C(0x4e87e09980b9957a) /* 347 */, U64_C(0x2acfa1df50aee355) /* 348 */, U64_C(0xd898263afd2fd556) /* 349 */, U64_C(0xc8f4924dd80c8fd6) /* 350 */, U64_C(0xcf99ca3d754a173a) /* 351 */, U64_C(0xfe477bacaf91bf3c) /* 352 */, U64_C(0xed5371f6d690c12d) /* 353 */, U64_C(0x831a5c285e687094) /* 354 */, U64_C(0xc5d3c90a3708a0a4) /* 355 */, U64_C(0x0f7f903717d06580) /* 356 */, U64_C(0x19f9bb13b8fdf27f) /* 357 */, U64_C(0xb1bd6f1b4d502843) /* 358 */, U64_C(0x1c761ba38fff4012) /* 359 */, U64_C(0x0d1530c4e2e21f3b) /* 360 */, U64_C(0x8943ce69a7372c8a) /* 361 */, U64_C(0xe5184e11feb5ce66) /* 362 */, U64_C(0x618bdb80bd736621) /* 363 */, U64_C(0x7d29bad68b574d0b) /* 364 */, U64_C(0x81bb613e25e6fe5b) /* 365 */, U64_C(0x071c9c10bc07913f) /* 366 */, U64_C(0xc7beeb7909ac2d97) /* 367 */, U64_C(0xc3e58d353bc5d757) /* 368 */, U64_C(0xeb017892f38f61e8) /* 369 */, U64_C(0xd4effb9c9b1cc21a) /* 370 */, U64_C(0x99727d26f494f7ab) /* 371 */, U64_C(0xa3e063a2956b3e03) /* 372 */, U64_C(0x9d4a8b9a4aa09c30) /* 373 */, U64_C(0x3f6ab7d500090fb4) /* 374 */, U64_C(0x9cc0f2a057268ac0) /* 375 */, U64_C(0x3dee9d2dedbf42d1) /* 376 */, U64_C(0x330f49c87960a972) /* 377 */, U64_C(0xc6b2720287421b41) /* 378 */, U64_C(0x0ac59ec07c00369c) /* 379 */, U64_C(0xef4eac49cb353425) /* 380 */, U64_C(0xf450244eef0129d8) /* 381 */, U64_C(0x8acc46e5caf4deb6) /* 382 */, U64_C(0x2ffeab63989263f7) /* 383 */, U64_C(0x8f7cb9fe5d7a4578) /* 384 */, U64_C(0x5bd8f7644e634635) /* 385 */, U64_C(0x427a7315bf2dc900) /* 386 */, U64_C(0x17d0c4aa2125261c) /* 387 */, U64_C(0x3992486c93518e50) /* 388 */, U64_C(0xb4cbfee0a2d7d4c3) /* 389 */, U64_C(0x7c75d6202c5ddd8d) /* 390 */, U64_C(0xdbc295d8e35b6c61) /* 391 */, U64_C(0x60b369d302032b19) /* 392 */, U64_C(0xce42685fdce44132) /* 393 */, U64_C(0x06f3ddb9ddf65610) /* 394 */, U64_C(0x8ea4d21db5e148f0) /* 395 */, U64_C(0x20b0fce62fcd496f) /* 396 */, U64_C(0x2c1b912358b0ee31) /* 397 */, U64_C(0xb28317b818f5a308) /* 398 */, U64_C(0xa89c1e189ca6d2cf) /* 399 */, U64_C(0x0c6b18576aaadbc8) /* 400 */, U64_C(0xb65deaa91299fae3) /* 401 */, U64_C(0xfb2b794b7f1027e7) /* 402 */, U64_C(0x04e4317f443b5beb) /* 403 */, U64_C(0x4b852d325939d0a6) /* 404 */, U64_C(0xd5ae6beefb207ffc) /* 405 */, U64_C(0x309682b281c7d374) /* 406 */, U64_C(0xbae309a194c3b475) /* 407 */, U64_C(0x8cc3f97b13b49f05) /* 408 */, U64_C(0x98a9422ff8293967) /* 409 */, U64_C(0x244b16b01076ff7c) /* 410 */, U64_C(0xf8bf571c663d67ee) /* 411 */, U64_C(0x1f0d6758eee30da1) /* 412 */, U64_C(0xc9b611d97adeb9b7) /* 413 */, U64_C(0xb7afd5887b6c57a2) /* 414 */, U64_C(0x6290ae846b984fe1) /* 415 */, U64_C(0x94df4cdeacc1a5fd) /* 416 */, U64_C(0x058a5bd1c5483aff) /* 417 */, U64_C(0x63166cc142ba3c37) /* 418 */, U64_C(0x8db8526eb2f76f40) /* 419 */, U64_C(0xe10880036f0d6d4e) /* 420 */, U64_C(0x9e0523c9971d311d) /* 421 */, U64_C(0x45ec2824cc7cd691) /* 422 */, U64_C(0x575b8359e62382c9) /* 423 */, U64_C(0xfa9e400dc4889995) /* 424 */, U64_C(0xd1823ecb45721568) /* 425 */, U64_C(0xdafd983b8206082f) /* 426 */, U64_C(0xaa7d29082386a8cb) /* 427 */, U64_C(0x269fcd4403b87588) /* 428 */, U64_C(0x1b91f5f728bdd1e0) /* 429 */, U64_C(0xe4669f39040201f6) /* 430 */, U64_C(0x7a1d7c218cf04ade) /* 431 */, U64_C(0x65623c29d79ce5ce) /* 432 */, U64_C(0x2368449096c00bb1) /* 433 */, U64_C(0xab9bf1879da503ba) /* 434 */, U64_C(0xbc23ecb1a458058e) /* 435 */, U64_C(0x9a58df01bb401ecc) /* 436 */, U64_C(0xa070e868a85f143d) /* 437 */, U64_C(0x4ff188307df2239e) /* 438 */, U64_C(0x14d565b41a641183) /* 439 */, U64_C(0xee13337452701602) /* 440 */, U64_C(0x950e3dcf3f285e09) /* 441 */, U64_C(0x59930254b9c80953) /* 442 */, U64_C(0x3bf299408930da6d) /* 443 */, U64_C(0xa955943f53691387) /* 444 */, U64_C(0xa15edecaa9cb8784) /* 445 */, U64_C(0x29142127352be9a0) /* 446 */, U64_C(0x76f0371fff4e7afb) /* 447 */, U64_C(0x0239f450274f2228) /* 448 */, U64_C(0xbb073af01d5e868b) /* 449 */, U64_C(0xbfc80571c10e96c1) /* 450 */, U64_C(0xd267088568222e23) /* 451 */, U64_C(0x9671a3d48e80b5b0) /* 452 */, U64_C(0x55b5d38ae193bb81) /* 453 */, U64_C(0x693ae2d0a18b04b8) /* 454 */, U64_C(0x5c48b4ecadd5335f) /* 455 */, U64_C(0xfd743b194916a1ca) /* 456 */, U64_C(0x2577018134be98c4) /* 457 */, U64_C(0xe77987e83c54a4ad) /* 458 */, U64_C(0x28e11014da33e1b9) /* 459 */, U64_C(0x270cc59e226aa213) /* 460 */, U64_C(0x71495f756d1a5f60) /* 461 */, U64_C(0x9be853fb60afef77) /* 462 */, U64_C(0xadc786a7f7443dbf) /* 463 */, U64_C(0x0904456173b29a82) /* 464 */, U64_C(0x58bc7a66c232bd5e) /* 465 */, U64_C(0xf306558c673ac8b2) /* 466 */, U64_C(0x41f639c6b6c9772a) /* 467 */, U64_C(0x216defe99fda35da) /* 468 */, U64_C(0x11640cc71c7be615) /* 469 */, U64_C(0x93c43694565c5527) /* 470 */, U64_C(0xea038e6246777839) /* 471 */, U64_C(0xf9abf3ce5a3e2469) /* 472 */, U64_C(0x741e768d0fd312d2) /* 473 */, U64_C(0x0144b883ced652c6) /* 474 */, U64_C(0xc20b5a5ba33f8552) /* 475 */, U64_C(0x1ae69633c3435a9d) /* 476 */, U64_C(0x97a28ca4088cfdec) /* 477 */, U64_C(0x8824a43c1e96f420) /* 478 */, U64_C(0x37612fa66eeea746) /* 479 */, U64_C(0x6b4cb165f9cf0e5a) /* 480 */, U64_C(0x43aa1c06a0abfb4a) /* 481 */, U64_C(0x7f4dc26ff162796b) /* 482 */, U64_C(0x6cbacc8e54ed9b0f) /* 483 */, U64_C(0xa6b7ffefd2bb253e) /* 484 */, U64_C(0x2e25bc95b0a29d4f) /* 485 */, U64_C(0x86d6a58bdef1388c) /* 486 */, U64_C(0xded74ac576b6f054) /* 487 */, U64_C(0x8030bdbc2b45805d) /* 488 */, U64_C(0x3c81af70e94d9289) /* 489 */, U64_C(0x3eff6dda9e3100db) /* 490 */, U64_C(0xb38dc39fdfcc8847) /* 491 */, U64_C(0x123885528d17b87e) /* 492 */, U64_C(0xf2da0ed240b1b642) /* 493 */, U64_C(0x44cefadcd54bf9a9) /* 494 */, U64_C(0x1312200e433c7ee6) /* 495 */, U64_C(0x9ffcc84f3a78c748) /* 496 */, U64_C(0xf0cd1f72248576bb) /* 497 */, U64_C(0xec6974053638cfe4) /* 498 */, U64_C(0x2ba7b67c0cec4e4c) /* 499 */, U64_C(0xac2f4df3e5ce32ed) /* 500 */, U64_C(0xcb33d14326ea4c11) /* 501 */, U64_C(0xa4e9044cc77e58bc) /* 502 */, U64_C(0x5f513293d934fcef) /* 503 */, U64_C(0x5dc9645506e55444) /* 504 */, U64_C(0x50de418f317de40a) /* 505 */, U64_C(0x388cb31a69dde259) /* 506 */, U64_C(0x2db4a83455820a86) /* 507 */, U64_C(0x9010a91e84711ae9) /* 508 */, U64_C(0x4df7f0b7b1498371) /* 509 */, U64_C(0xd62a2eabc0977179) /* 510 */, U64_C(0x22fac097aa8d5c0e) /* 511 */ }; static u64 sbox3[256] = { U64_C(0xf49fcc2ff1daf39b) /* 512 */, U64_C(0x487fd5c66ff29281) /* 513 */, U64_C(0xe8a30667fcdca83f) /* 514 */, U64_C(0x2c9b4be3d2fcce63) /* 515 */, U64_C(0xda3ff74b93fbbbc2) /* 516 */, U64_C(0x2fa165d2fe70ba66) /* 517 */, U64_C(0xa103e279970e93d4) /* 518 */, U64_C(0xbecdec77b0e45e71) /* 519 */, U64_C(0xcfb41e723985e497) /* 520 */, U64_C(0xb70aaa025ef75017) /* 521 */, U64_C(0xd42309f03840b8e0) /* 522 */, U64_C(0x8efc1ad035898579) /* 523 */, U64_C(0x96c6920be2b2abc5) /* 524 */, U64_C(0x66af4163375a9172) /* 525 */, U64_C(0x2174abdcca7127fb) /* 526 */, U64_C(0xb33ccea64a72ff41) /* 527 */, U64_C(0xf04a4933083066a5) /* 528 */, U64_C(0x8d970acdd7289af5) /* 529 */, U64_C(0x8f96e8e031c8c25e) /* 530 */, U64_C(0xf3fec02276875d47) /* 531 */, U64_C(0xec7bf310056190dd) /* 532 */, U64_C(0xf5adb0aebb0f1491) /* 533 */, U64_C(0x9b50f8850fd58892) /* 534 */, U64_C(0x4975488358b74de8) /* 535 */, U64_C(0xa3354ff691531c61) /* 536 */, U64_C(0x0702bbe481d2c6ee) /* 537 */, U64_C(0x89fb24057deded98) /* 538 */, U64_C(0xac3075138596e902) /* 539 */, U64_C(0x1d2d3580172772ed) /* 540 */, U64_C(0xeb738fc28e6bc30d) /* 541 */, U64_C(0x5854ef8f63044326) /* 542 */, U64_C(0x9e5c52325add3bbe) /* 543 */, U64_C(0x90aa53cf325c4623) /* 544 */, U64_C(0xc1d24d51349dd067) /* 545 */, U64_C(0x2051cfeea69ea624) /* 546 */, U64_C(0x13220f0a862e7e4f) /* 547 */, U64_C(0xce39399404e04864) /* 548 */, U64_C(0xd9c42ca47086fcb7) /* 549 */, U64_C(0x685ad2238a03e7cc) /* 550 */, U64_C(0x066484b2ab2ff1db) /* 551 */, U64_C(0xfe9d5d70efbf79ec) /* 552 */, U64_C(0x5b13b9dd9c481854) /* 553 */, U64_C(0x15f0d475ed1509ad) /* 554 */, U64_C(0x0bebcd060ec79851) /* 555 */, U64_C(0xd58c6791183ab7f8) /* 556 */, U64_C(0xd1187c5052f3eee4) /* 557 */, U64_C(0xc95d1192e54e82ff) /* 558 */, U64_C(0x86eea14cb9ac6ca2) /* 559 */, U64_C(0x3485beb153677d5d) /* 560 */, U64_C(0xdd191d781f8c492a) /* 561 */, U64_C(0xf60866baa784ebf9) /* 562 */, U64_C(0x518f643ba2d08c74) /* 563 */, U64_C(0x8852e956e1087c22) /* 564 */, U64_C(0xa768cb8dc410ae8d) /* 565 */, U64_C(0x38047726bfec8e1a) /* 566 */, U64_C(0xa67738b4cd3b45aa) /* 567 */, U64_C(0xad16691cec0dde19) /* 568 */, U64_C(0xc6d4319380462e07) /* 569 */, U64_C(0xc5a5876d0ba61938) /* 570 */, U64_C(0x16b9fa1fa58fd840) /* 571 */, U64_C(0x188ab1173ca74f18) /* 572 */, U64_C(0xabda2f98c99c021f) /* 573 */, U64_C(0x3e0580ab134ae816) /* 574 */, U64_C(0x5f3b05b773645abb) /* 575 */, U64_C(0x2501a2be5575f2f6) /* 576 */, U64_C(0x1b2f74004e7e8ba9) /* 577 */, U64_C(0x1cd7580371e8d953) /* 578 */, U64_C(0x7f6ed89562764e30) /* 579 */, U64_C(0xb15926ff596f003d) /* 580 */, U64_C(0x9f65293da8c5d6b9) /* 581 */, U64_C(0x6ecef04dd690f84c) /* 582 */, U64_C(0x4782275fff33af88) /* 583 */, U64_C(0xe41433083f820801) /* 584 */, U64_C(0xfd0dfe409a1af9b5) /* 585 */, U64_C(0x4325a3342cdb396b) /* 586 */, U64_C(0x8ae77e62b301b252) /* 587 */, U64_C(0xc36f9e9f6655615a) /* 588 */, U64_C(0x85455a2d92d32c09) /* 589 */, U64_C(0xf2c7dea949477485) /* 590 */, U64_C(0x63cfb4c133a39eba) /* 591 */, U64_C(0x83b040cc6ebc5462) /* 592 */, U64_C(0x3b9454c8fdb326b0) /* 593 */, U64_C(0x56f56a9e87ffd78c) /* 594 */, U64_C(0x2dc2940d99f42bc6) /* 595 */, U64_C(0x98f7df096b096e2d) /* 596 */, U64_C(0x19a6e01e3ad852bf) /* 597 */, U64_C(0x42a99ccbdbd4b40b) /* 598 */, U64_C(0xa59998af45e9c559) /* 599 */, U64_C(0x366295e807d93186) /* 600 */, U64_C(0x6b48181bfaa1f773) /* 601 */, U64_C(0x1fec57e2157a0a1d) /* 602 */, U64_C(0x4667446af6201ad5) /* 603 */, U64_C(0xe615ebcacfb0f075) /* 604 */, U64_C(0xb8f31f4f68290778) /* 605 */, U64_C(0x22713ed6ce22d11e) /* 606 */, U64_C(0x3057c1a72ec3c93b) /* 607 */, U64_C(0xcb46acc37c3f1f2f) /* 608 */, U64_C(0xdbb893fd02aaf50e) /* 609 */, U64_C(0x331fd92e600b9fcf) /* 610 */, U64_C(0xa498f96148ea3ad6) /* 611 */, U64_C(0xa8d8426e8b6a83ea) /* 612 */, U64_C(0xa089b274b7735cdc) /* 613 */, U64_C(0x87f6b3731e524a11) /* 614 */, U64_C(0x118808e5cbc96749) /* 615 */, U64_C(0x9906e4c7b19bd394) /* 616 */, U64_C(0xafed7f7e9b24a20c) /* 617 */, U64_C(0x6509eadeeb3644a7) /* 618 */, U64_C(0x6c1ef1d3e8ef0ede) /* 619 */, U64_C(0xb9c97d43e9798fb4) /* 620 */, U64_C(0xa2f2d784740c28a3) /* 621 */, U64_C(0x7b8496476197566f) /* 622 */, U64_C(0x7a5be3e6b65f069d) /* 623 */, U64_C(0xf96330ed78be6f10) /* 624 */, U64_C(0xeee60de77a076a15) /* 625 */, U64_C(0x2b4bee4aa08b9bd0) /* 626 */, U64_C(0x6a56a63ec7b8894e) /* 627 */, U64_C(0x02121359ba34fef4) /* 628 */, U64_C(0x4cbf99f8283703fc) /* 629 */, U64_C(0x398071350caf30c8) /* 630 */, U64_C(0xd0a77a89f017687a) /* 631 */, U64_C(0xf1c1a9eb9e423569) /* 632 */, U64_C(0x8c7976282dee8199) /* 633 */, U64_C(0x5d1737a5dd1f7abd) /* 634 */, U64_C(0x4f53433c09a9fa80) /* 635 */, U64_C(0xfa8b0c53df7ca1d9) /* 636 */, U64_C(0x3fd9dcbc886ccb77) /* 637 */, U64_C(0xc040917ca91b4720) /* 638 */, U64_C(0x7dd00142f9d1dcdf) /* 639 */, U64_C(0x8476fc1d4f387b58) /* 640 */, U64_C(0x23f8e7c5f3316503) /* 641 */, U64_C(0x032a2244e7e37339) /* 642 */, U64_C(0x5c87a5d750f5a74b) /* 643 */, U64_C(0x082b4cc43698992e) /* 644 */, U64_C(0xdf917becb858f63c) /* 645 */, U64_C(0x3270b8fc5bf86dda) /* 646 */, U64_C(0x10ae72bb29b5dd76) /* 647 */, U64_C(0x576ac94e7700362b) /* 648 */, U64_C(0x1ad112dac61efb8f) /* 649 */, U64_C(0x691bc30ec5faa427) /* 650 */, U64_C(0xff246311cc327143) /* 651 */, U64_C(0x3142368e30e53206) /* 652 */, U64_C(0x71380e31e02ca396) /* 653 */, U64_C(0x958d5c960aad76f1) /* 654 */, U64_C(0xf8d6f430c16da536) /* 655 */, U64_C(0xc8ffd13f1be7e1d2) /* 656 */, U64_C(0x7578ae66004ddbe1) /* 657 */, U64_C(0x05833f01067be646) /* 658 */, U64_C(0xbb34b5ad3bfe586d) /* 659 */, U64_C(0x095f34c9a12b97f0) /* 660 */, U64_C(0x247ab64525d60ca8) /* 661 */, U64_C(0xdcdbc6f3017477d1) /* 662 */, U64_C(0x4a2e14d4decad24d) /* 663 */, U64_C(0xbdb5e6d9be0a1eeb) /* 664 */, U64_C(0x2a7e70f7794301ab) /* 665 */, U64_C(0xdef42d8a270540fd) /* 666 */, U64_C(0x01078ec0a34c22c1) /* 667 */, U64_C(0xe5de511af4c16387) /* 668 */, U64_C(0x7ebb3a52bd9a330a) /* 669 */, U64_C(0x77697857aa7d6435) /* 670 */, U64_C(0x004e831603ae4c32) /* 671 */, U64_C(0xe7a21020ad78e312) /* 672 */, U64_C(0x9d41a70c6ab420f2) /* 673 */, U64_C(0x28e06c18ea1141e6) /* 674 */, U64_C(0xd2b28cbd984f6b28) /* 675 */, U64_C(0x26b75f6c446e9d83) /* 676 */, U64_C(0xba47568c4d418d7f) /* 677 */, U64_C(0xd80badbfe6183d8e) /* 678 */, U64_C(0x0e206d7f5f166044) /* 679 */, U64_C(0xe258a43911cbca3e) /* 680 */, U64_C(0x723a1746b21dc0bc) /* 681 */, U64_C(0xc7caa854f5d7cdd3) /* 682 */, U64_C(0x7cac32883d261d9c) /* 683 */, U64_C(0x7690c26423ba942c) /* 684 */, U64_C(0x17e55524478042b8) /* 685 */, U64_C(0xe0be477656a2389f) /* 686 */, U64_C(0x4d289b5e67ab2da0) /* 687 */, U64_C(0x44862b9c8fbbfd31) /* 688 */, U64_C(0xb47cc8049d141365) /* 689 */, U64_C(0x822c1b362b91c793) /* 690 */, U64_C(0x4eb14655fb13dfd8) /* 691 */, U64_C(0x1ecbba0714e2a97b) /* 692 */, U64_C(0x6143459d5cde5f14) /* 693 */, U64_C(0x53a8fbf1d5f0ac89) /* 694 */, U64_C(0x97ea04d81c5e5b00) /* 695 */, U64_C(0x622181a8d4fdb3f3) /* 696 */, U64_C(0xe9bcd341572a1208) /* 697 */, U64_C(0x1411258643cce58a) /* 698 */, U64_C(0x9144c5fea4c6e0a4) /* 699 */, U64_C(0x0d33d06565cf620f) /* 700 */, U64_C(0x54a48d489f219ca1) /* 701 */, U64_C(0xc43e5eac6d63c821) /* 702 */, U64_C(0xa9728b3a72770daf) /* 703 */, U64_C(0xd7934e7b20df87ef) /* 704 */, U64_C(0xe35503b61a3e86e5) /* 705 */, U64_C(0xcae321fbc819d504) /* 706 */, U64_C(0x129a50b3ac60bfa6) /* 707 */, U64_C(0xcd5e68ea7e9fb6c3) /* 708 */, U64_C(0xb01c90199483b1c7) /* 709 */, U64_C(0x3de93cd5c295376c) /* 710 */, U64_C(0xaed52edf2ab9ad13) /* 711 */, U64_C(0x2e60f512c0a07884) /* 712 */, U64_C(0xbc3d86a3e36210c9) /* 713 */, U64_C(0x35269d9b163951ce) /* 714 */, U64_C(0x0c7d6e2ad0cdb5fa) /* 715 */, U64_C(0x59e86297d87f5733) /* 716 */, U64_C(0x298ef221898db0e7) /* 717 */, U64_C(0x55000029d1a5aa7e) /* 718 */, U64_C(0x8bc08ae1b5061b45) /* 719 */, U64_C(0xc2c31c2b6c92703a) /* 720 */, U64_C(0x94cc596baf25ef42) /* 721 */, U64_C(0x0a1d73db22540456) /* 722 */, U64_C(0x04b6a0f9d9c4179a) /* 723 */, U64_C(0xeffdafa2ae3d3c60) /* 724 */, U64_C(0xf7c8075bb49496c4) /* 725 */, U64_C(0x9cc5c7141d1cd4e3) /* 726 */, U64_C(0x78bd1638218e5534) /* 727 */, U64_C(0xb2f11568f850246a) /* 728 */, U64_C(0xedfabcfa9502bc29) /* 729 */, U64_C(0x796ce5f2da23051b) /* 730 */, U64_C(0xaae128b0dc93537c) /* 731 */, U64_C(0x3a493da0ee4b29ae) /* 732 */, U64_C(0xb5df6b2c416895d7) /* 733 */, U64_C(0xfcabbd25122d7f37) /* 734 */, U64_C(0x70810b58105dc4b1) /* 735 */, U64_C(0xe10fdd37f7882a90) /* 736 */, U64_C(0x524dcab5518a3f5c) /* 737 */, U64_C(0x3c9e85878451255b) /* 738 */, U64_C(0x4029828119bd34e2) /* 739 */, U64_C(0x74a05b6f5d3ceccb) /* 740 */, U64_C(0xb610021542e13eca) /* 741 */, U64_C(0x0ff979d12f59e2ac) /* 742 */, U64_C(0x6037da27e4f9cc50) /* 743 */, U64_C(0x5e92975a0df1847d) /* 744 */, U64_C(0xd66de190d3e623fe) /* 745 */, U64_C(0x5032d6b87b568048) /* 746 */, U64_C(0x9a36b7ce8235216e) /* 747 */, U64_C(0x80272a7a24f64b4a) /* 748 */, U64_C(0x93efed8b8c6916f7) /* 749 */, U64_C(0x37ddbff44cce1555) /* 750 */, U64_C(0x4b95db5d4b99bd25) /* 751 */, U64_C(0x92d3fda169812fc0) /* 752 */, U64_C(0xfb1a4a9a90660bb6) /* 753 */, U64_C(0x730c196946a4b9b2) /* 754 */, U64_C(0x81e289aa7f49da68) /* 755 */, U64_C(0x64669a0f83b1a05f) /* 756 */, U64_C(0x27b3ff7d9644f48b) /* 757 */, U64_C(0xcc6b615c8db675b3) /* 758 */, U64_C(0x674f20b9bcebbe95) /* 759 */, U64_C(0x6f31238275655982) /* 760 */, U64_C(0x5ae488713e45cf05) /* 761 */, U64_C(0xbf619f9954c21157) /* 762 */, U64_C(0xeabac46040a8eae9) /* 763 */, U64_C(0x454c6fe9f2c0c1cd) /* 764 */, U64_C(0x419cf6496412691c) /* 765 */, U64_C(0xd3dc3bef265b0f70) /* 766 */, U64_C(0x6d0e60f5c3578a9e) /* 767 */ }; static u64 sbox4[256] = { U64_C(0x5b0e608526323c55) /* 768 */, U64_C(0x1a46c1a9fa1b59f5) /* 769 */, U64_C(0xa9e245a17c4c8ffa) /* 770 */, U64_C(0x65ca5159db2955d7) /* 771 */, U64_C(0x05db0a76ce35afc2) /* 772 */, U64_C(0x81eac77ea9113d45) /* 773 */, U64_C(0x528ef88ab6ac0a0d) /* 774 */, U64_C(0xa09ea253597be3ff) /* 775 */, U64_C(0x430ddfb3ac48cd56) /* 776 */, U64_C(0xc4b3a67af45ce46f) /* 777 */, U64_C(0x4ececfd8fbe2d05e) /* 778 */, U64_C(0x3ef56f10b39935f0) /* 779 */, U64_C(0x0b22d6829cd619c6) /* 780 */, U64_C(0x17fd460a74df2069) /* 781 */, U64_C(0x6cf8cc8e8510ed40) /* 782 */, U64_C(0xd6c824bf3a6ecaa7) /* 783 */, U64_C(0x61243d581a817049) /* 784 */, U64_C(0x048bacb6bbc163a2) /* 785 */, U64_C(0xd9a38ac27d44cc32) /* 786 */, U64_C(0x7fddff5baaf410ab) /* 787 */, U64_C(0xad6d495aa804824b) /* 788 */, U64_C(0xe1a6a74f2d8c9f94) /* 789 */, U64_C(0xd4f7851235dee8e3) /* 790 */, U64_C(0xfd4b7f886540d893) /* 791 */, U64_C(0x247c20042aa4bfda) /* 792 */, U64_C(0x096ea1c517d1327c) /* 793 */, U64_C(0xd56966b4361a6685) /* 794 */, U64_C(0x277da5c31221057d) /* 795 */, U64_C(0x94d59893a43acff7) /* 796 */, U64_C(0x64f0c51ccdc02281) /* 797 */, U64_C(0x3d33bcc4ff6189db) /* 798 */, U64_C(0xe005cb184ce66af1) /* 799 */, U64_C(0xff5ccd1d1db99bea) /* 800 */, U64_C(0xb0b854a7fe42980f) /* 801 */, U64_C(0x7bd46a6a718d4b9f) /* 802 */, U64_C(0xd10fa8cc22a5fd8c) /* 803 */, U64_C(0xd31484952be4bd31) /* 804 */, U64_C(0xc7fa975fcb243847) /* 805 */, U64_C(0x4886ed1e5846c407) /* 806 */, U64_C(0x28cddb791eb70b04) /* 807 */, U64_C(0xc2b00be2f573417f) /* 808 */, U64_C(0x5c9590452180f877) /* 809 */, U64_C(0x7a6bddfff370eb00) /* 810 */, U64_C(0xce509e38d6d9d6a4) /* 811 */, U64_C(0xebeb0f00647fa702) /* 812 */, U64_C(0x1dcc06cf76606f06) /* 813 */, U64_C(0xe4d9f28ba286ff0a) /* 814 */, U64_C(0xd85a305dc918c262) /* 815 */, U64_C(0x475b1d8732225f54) /* 816 */, U64_C(0x2d4fb51668ccb5fe) /* 817 */, U64_C(0xa679b9d9d72bba20) /* 818 */, U64_C(0x53841c0d912d43a5) /* 819 */, U64_C(0x3b7eaa48bf12a4e8) /* 820 */, U64_C(0x781e0e47f22f1ddf) /* 821 */, U64_C(0xeff20ce60ab50973) /* 822 */, U64_C(0x20d261d19dffb742) /* 823 */, U64_C(0x16a12b03062a2e39) /* 824 */, U64_C(0x1960eb2239650495) /* 825 */, U64_C(0x251c16fed50eb8b8) /* 826 */, U64_C(0x9ac0c330f826016e) /* 827 */, U64_C(0xed152665953e7671) /* 828 */, U64_C(0x02d63194a6369570) /* 829 */, U64_C(0x5074f08394b1c987) /* 830 */, U64_C(0x70ba598c90b25ce1) /* 831 */, U64_C(0x794a15810b9742f6) /* 832 */, U64_C(0x0d5925e9fcaf8c6c) /* 833 */, U64_C(0x3067716cd868744e) /* 834 */, U64_C(0x910ab077e8d7731b) /* 835 */, U64_C(0x6a61bbdb5ac42f61) /* 836 */, U64_C(0x93513efbf0851567) /* 837 */, U64_C(0xf494724b9e83e9d5) /* 838 */, U64_C(0xe887e1985c09648d) /* 839 */, U64_C(0x34b1d3c675370cfd) /* 840 */, U64_C(0xdc35e433bc0d255d) /* 841 */, U64_C(0xd0aab84234131be0) /* 842 */, U64_C(0x08042a50b48b7eaf) /* 843 */, U64_C(0x9997c4ee44a3ab35) /* 844 */, U64_C(0x829a7b49201799d0) /* 845 */, U64_C(0x263b8307b7c54441) /* 846 */, U64_C(0x752f95f4fd6a6ca6) /* 847 */, U64_C(0x927217402c08c6e5) /* 848 */, U64_C(0x2a8ab754a795d9ee) /* 849 */, U64_C(0xa442f7552f72943d) /* 850 */, U64_C(0x2c31334e19781208) /* 851 */, U64_C(0x4fa98d7ceaee6291) /* 852 */, U64_C(0x55c3862f665db309) /* 853 */, U64_C(0xbd0610175d53b1f3) /* 854 */, U64_C(0x46fe6cb840413f27) /* 855 */, U64_C(0x3fe03792df0cfa59) /* 856 */, U64_C(0xcfe700372eb85e8f) /* 857 */, U64_C(0xa7be29e7adbce118) /* 858 */, U64_C(0xe544ee5cde8431dd) /* 859 */, U64_C(0x8a781b1b41f1873e) /* 860 */, U64_C(0xa5c94c78a0d2f0e7) /* 861 */, U64_C(0x39412e2877b60728) /* 862 */, U64_C(0xa1265ef3afc9a62c) /* 863 */, U64_C(0xbcc2770c6a2506c5) /* 864 */, U64_C(0x3ab66dd5dce1ce12) /* 865 */, U64_C(0xe65499d04a675b37) /* 866 */, U64_C(0x7d8f523481bfd216) /* 867 */, U64_C(0x0f6f64fcec15f389) /* 868 */, U64_C(0x74efbe618b5b13c8) /* 869 */, U64_C(0xacdc82b714273e1d) /* 870 */, U64_C(0xdd40bfe003199d17) /* 871 */, U64_C(0x37e99257e7e061f8) /* 872 */, U64_C(0xfa52626904775aaa) /* 873 */, U64_C(0x8bbbf63a463d56f9) /* 874 */, U64_C(0xf0013f1543a26e64) /* 875 */, U64_C(0xa8307e9f879ec898) /* 876 */, U64_C(0xcc4c27a4150177cc) /* 877 */, U64_C(0x1b432f2cca1d3348) /* 878 */, U64_C(0xde1d1f8f9f6fa013) /* 879 */, U64_C(0x606602a047a7ddd6) /* 880 */, U64_C(0xd237ab64cc1cb2c7) /* 881 */, U64_C(0x9b938e7225fcd1d3) /* 882 */, U64_C(0xec4e03708e0ff476) /* 883 */, U64_C(0xfeb2fbda3d03c12d) /* 884 */, U64_C(0xae0bced2ee43889a) /* 885 */, U64_C(0x22cb8923ebfb4f43) /* 886 */, U64_C(0x69360d013cf7396d) /* 887 */, U64_C(0x855e3602d2d4e022) /* 888 */, U64_C(0x073805bad01f784c) /* 889 */, U64_C(0x33e17a133852f546) /* 890 */, U64_C(0xdf4874058ac7b638) /* 891 */, U64_C(0xba92b29c678aa14a) /* 892 */, U64_C(0x0ce89fc76cfaadcd) /* 893 */, U64_C(0x5f9d4e0908339e34) /* 894 */, U64_C(0xf1afe9291f5923b9) /* 895 */, U64_C(0x6e3480f60f4a265f) /* 896 */, U64_C(0xeebf3a2ab29b841c) /* 897 */, U64_C(0xe21938a88f91b4ad) /* 898 */, U64_C(0x57dfeff845c6d3c3) /* 899 */, U64_C(0x2f006b0bf62caaf2) /* 900 */, U64_C(0x62f479ef6f75ee78) /* 901 */, U64_C(0x11a55ad41c8916a9) /* 902 */, U64_C(0xf229d29084fed453) /* 903 */, U64_C(0x42f1c27b16b000e6) /* 904 */, U64_C(0x2b1f76749823c074) /* 905 */, U64_C(0x4b76eca3c2745360) /* 906 */, U64_C(0x8c98f463b91691bd) /* 907 */, U64_C(0x14bcc93cf1ade66a) /* 908 */, U64_C(0x8885213e6d458397) /* 909 */, U64_C(0x8e177df0274d4711) /* 910 */, U64_C(0xb49b73b5503f2951) /* 911 */, U64_C(0x10168168c3f96b6b) /* 912 */, U64_C(0x0e3d963b63cab0ae) /* 913 */, U64_C(0x8dfc4b5655a1db14) /* 914 */, U64_C(0xf789f1356e14de5c) /* 915 */, U64_C(0x683e68af4e51dac1) /* 916 */, U64_C(0xc9a84f9d8d4b0fd9) /* 917 */, U64_C(0x3691e03f52a0f9d1) /* 918 */, U64_C(0x5ed86e46e1878e80) /* 919 */, U64_C(0x3c711a0e99d07150) /* 920 */, U64_C(0x5a0865b20c4e9310) /* 921 */, U64_C(0x56fbfc1fe4f0682e) /* 922 */, U64_C(0xea8d5de3105edf9b) /* 923 */, U64_C(0x71abfdb12379187a) /* 924 */, U64_C(0x2eb99de1bee77b9c) /* 925 */, U64_C(0x21ecc0ea33cf4523) /* 926 */, U64_C(0x59a4d7521805c7a1) /* 927 */, U64_C(0x3896f5eb56ae7c72) /* 928 */, U64_C(0xaa638f3db18f75dc) /* 929 */, U64_C(0x9f39358dabe9808e) /* 930 */, U64_C(0xb7defa91c00b72ac) /* 931 */, U64_C(0x6b5541fd62492d92) /* 932 */, U64_C(0x6dc6dee8f92e4d5b) /* 933 */, U64_C(0x353f57abc4beea7e) /* 934 */, U64_C(0x735769d6da5690ce) /* 935 */, U64_C(0x0a234aa642391484) /* 936 */, U64_C(0xf6f9508028f80d9d) /* 937 */, U64_C(0xb8e319a27ab3f215) /* 938 */, U64_C(0x31ad9c1151341a4d) /* 939 */, U64_C(0x773c22a57bef5805) /* 940 */, U64_C(0x45c7561a07968633) /* 941 */, U64_C(0xf913da9e249dbe36) /* 942 */, U64_C(0xda652d9b78a64c68) /* 943 */, U64_C(0x4c27a97f3bc334ef) /* 944 */, U64_C(0x76621220e66b17f4) /* 945 */, U64_C(0x967743899acd7d0b) /* 946 */, U64_C(0xf3ee5bcae0ed6782) /* 947 */, U64_C(0x409f753600c879fc) /* 948 */, U64_C(0x06d09a39b5926db6) /* 949 */, U64_C(0x6f83aeb0317ac588) /* 950 */, U64_C(0x01e6ca4a86381f21) /* 951 */, U64_C(0x66ff3462d19f3025) /* 952 */, U64_C(0x72207c24ddfd3bfb) /* 953 */, U64_C(0x4af6b6d3e2ece2eb) /* 954 */, U64_C(0x9c994dbec7ea08de) /* 955 */, U64_C(0x49ace597b09a8bc4) /* 956 */, U64_C(0xb38c4766cf0797ba) /* 957 */, U64_C(0x131b9373c57c2a75) /* 958 */, U64_C(0xb1822cce61931e58) /* 959 */, U64_C(0x9d7555b909ba1c0c) /* 960 */, U64_C(0x127fafdd937d11d2) /* 961 */, U64_C(0x29da3badc66d92e4) /* 962 */, U64_C(0xa2c1d57154c2ecbc) /* 963 */, U64_C(0x58c5134d82f6fe24) /* 964 */, U64_C(0x1c3ae3515b62274f) /* 965 */, U64_C(0xe907c82e01cb8126) /* 966 */, U64_C(0xf8ed091913e37fcb) /* 967 */, U64_C(0x3249d8f9c80046c9) /* 968 */, U64_C(0x80cf9bede388fb63) /* 969 */, U64_C(0x1881539a116cf19e) /* 970 */, U64_C(0x5103f3f76bd52457) /* 971 */, U64_C(0x15b7e6f5ae47f7a8) /* 972 */, U64_C(0xdbd7c6ded47e9ccf) /* 973 */, U64_C(0x44e55c410228bb1a) /* 974 */, U64_C(0xb647d4255edb4e99) /* 975 */, U64_C(0x5d11882bb8aafc30) /* 976 */, U64_C(0xf5098bbb29d3212a) /* 977 */, U64_C(0x8fb5ea14e90296b3) /* 978 */, U64_C(0x677b942157dd025a) /* 979 */, U64_C(0xfb58e7c0a390acb5) /* 980 */, U64_C(0x89d3674c83bd4a01) /* 981 */, U64_C(0x9e2da4df4bf3b93b) /* 982 */, U64_C(0xfcc41e328cab4829) /* 983 */, U64_C(0x03f38c96ba582c52) /* 984 */, U64_C(0xcad1bdbd7fd85db2) /* 985 */, U64_C(0xbbb442c16082ae83) /* 986 */, U64_C(0xb95fe86ba5da9ab0) /* 987 */, U64_C(0xb22e04673771a93f) /* 988 */, U64_C(0x845358c9493152d8) /* 989 */, U64_C(0xbe2a488697b4541e) /* 990 */, U64_C(0x95a2dc2dd38e6966) /* 991 */, U64_C(0xc02c11ac923c852b) /* 992 */, U64_C(0x2388b1990df2a87b) /* 993 */, U64_C(0x7c8008fa1b4f37be) /* 994 */, U64_C(0x1f70d0c84d54e503) /* 995 */, U64_C(0x5490adec7ece57d4) /* 996 */, U64_C(0x002b3c27d9063a3a) /* 997 */, U64_C(0x7eaea3848030a2bf) /* 998 */, U64_C(0xc602326ded2003c0) /* 999 */, U64_C(0x83a7287d69a94086) /* 1000 */, U64_C(0xc57a5fcb30f57a8a) /* 1001 */, U64_C(0xb56844e479ebe779) /* 1002 */, U64_C(0xa373b40f05dcbce9) /* 1003 */, U64_C(0xd71a786e88570ee2) /* 1004 */, U64_C(0x879cbacdbde8f6a0) /* 1005 */, U64_C(0x976ad1bcc164a32f) /* 1006 */, U64_C(0xab21e25e9666d78b) /* 1007 */, U64_C(0x901063aae5e5c33c) /* 1008 */, U64_C(0x9818b34448698d90) /* 1009 */, U64_C(0xe36487ae3e1e8abb) /* 1010 */, U64_C(0xafbdf931893bdcb4) /* 1011 */, U64_C(0x6345a0dc5fbbd519) /* 1012 */, U64_C(0x8628fe269b9465ca) /* 1013 */, U64_C(0x1e5d01603f9c51ec) /* 1014 */, U64_C(0x4de44006a15049b7) /* 1015 */, U64_C(0xbf6c70e5f776cbb1) /* 1016 */, U64_C(0x411218f2ef552bed) /* 1017 */, U64_C(0xcb0c0708705a36a3) /* 1018 */, U64_C(0xe74d14754f986044) /* 1019 */, U64_C(0xcd56d9430ea8280e) /* 1020 */, U64_C(0xc12591d7535f5065) /* 1021 */, U64_C(0xc83223f1720aef96) /* 1022 */, U64_C(0xc3a0396f7363a51f) /* 1023 */ }; static unsigned int transform ( void *ctx, const unsigned char *data ); static void do_init (void *context, int variant) { TIGER_CONTEXT *hd = context; hd->a = 0x0123456789abcdefLL; hd->b = 0xfedcba9876543210LL; hd->c = 0xf096a5b4c3b2e187LL; hd->bctx.nblocks = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; hd->variant = variant; } static void tiger_init (void *context) { do_init (context, 0); } static void tiger1_init (void *context) { do_init (context, 1); } static void tiger2_init (void *context) { do_init (context, 2); } static void tiger_round( u64 *ra, u64 *rb, u64 *rc, u64 x, int mul ) { u64 a = *ra; u64 b = *rb; u64 c = *rc; c ^= x; a -= ( sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ] ^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ]); b += ( sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ] ^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ]); b *= mul; *ra = a; *rb = b; *rc = c; } static void pass( u64 *ra, u64 *rb, u64 *rc, u64 *x, int mul ) { u64 a = *ra; u64 b = *rb; u64 c = *rc; tiger_round( &a, &b, &c, x[0], mul ); tiger_round( &b, &c, &a, x[1], mul ); tiger_round( &c, &a, &b, x[2], mul ); tiger_round( &a, &b, &c, x[3], mul ); tiger_round( &b, &c, &a, x[4], mul ); tiger_round( &c, &a, &b, x[5], mul ); tiger_round( &a, &b, &c, x[6], mul ); tiger_round( &b, &c, &a, x[7], mul ); *ra = a; *rb = b; *rc = c; } static void key_schedule( u64 *x ) { x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL; x[1] ^= x[0]; x[2] += x[1]; x[3] -= x[2] ^ ((~x[1]) << 19 ); x[4] ^= x[3]; x[5] += x[4]; x[6] -= x[5] ^ ((~x[4]) >> 23 ); x[7] ^= x[6]; x[0] += x[7]; x[1] -= x[0] ^ ((~x[7]) << 19 ); x[2] ^= x[1]; x[3] += x[2]; x[4] -= x[3] ^ ((~x[2]) >> 23 ); x[5] ^= x[4]; x[6] += x[5]; x[7] -= x[6] ^ 0x0123456789abcdefLL; } /**************** * Transform the message DATA which consists of 512 bytes (8 words) */ static unsigned int transform ( void *ctx, const unsigned char *data ) { TIGER_CONTEXT *hd = ctx; u64 a,b,c,aa,bb,cc; u64 x[8]; -#ifdef WORDS_BIGENDIAN -#define MKWORD(d,n) \ - ( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \ - | ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \ - | ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \ - | ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) ) - x[0] = MKWORD(data, 0); - x[1] = MKWORD(data, 1); - x[2] = MKWORD(data, 2); - x[3] = MKWORD(data, 3); - x[4] = MKWORD(data, 4); - x[5] = MKWORD(data, 5); - x[6] = MKWORD(data, 6); - x[7] = MKWORD(data, 7); -#undef MKWORD -#else - memcpy( &x[0], data, 64 ); -#endif + int i; + + for ( i = 0; i < 8; i++ ) + x[i] = buf_get_le64(data + i * 8); /* save */ a = aa = hd->a; b = bb = hd->b; c = cc = hd->c; pass( &a, &b, &c, x, 5); key_schedule( x ); pass( &c, &a, &b, x, 7); key_schedule( x ); pass( &b, &c, &a, x, 9); /* feedforward */ a ^= aa; b -= bb; c += cc; /* store */ hd->a = a; hd->b = b; hd->c = c; return /*burn_stack*/ 21*8+11*sizeof(void*); } /* The routine terminates the computation */ static void tiger_final( void *context ) { TIGER_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; unsigned int burn; byte pad = hd->variant == 2? 0x80 : 0x01; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; /* multiply by 64 to make a byte count */ lsb = t << 6; msb = t >> 26; /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) msb++; /* multiply by 8 to make a bit count */ t = lsb; lsb <<= 3; msb <<= 3; msb |= t >> 29; if( hd->bctx.count < 56 ) /* enough room */ { hd->bctx.buf[hd->bctx.count++] = pad; while( hd->bctx.count < 56 ) hd->bctx.buf[hd->bctx.count++] = 0; /* pad */ } else /* need one extra block */ { hd->bctx.buf[hd->bctx.count++] = pad; /* pad character */ while( hd->bctx.count < 64 ) hd->bctx.buf[hd->bctx.count++] = 0; _gcry_md_block_write(hd, NULL, 0); /* flush */; memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */ } /* append the 64 bit count */ - hd->bctx.buf[56] = lsb ; - hd->bctx.buf[57] = lsb >> 8; - hd->bctx.buf[58] = lsb >> 16; - hd->bctx.buf[59] = lsb >> 24; - hd->bctx.buf[60] = msb ; - hd->bctx.buf[61] = msb >> 8; - hd->bctx.buf[62] = msb >> 16; - hd->bctx.buf[63] = msb >> 24; + buf_put_le32(hd->bctx.buf + 56, lsb); + buf_put_le32(hd->bctx.buf + 60, msb); burn = transform( hd, hd->bctx.buf ); _gcry_burn_stack (burn); p = hd->bctx.buf; -#ifdef WORDS_BIGENDIAN -#define X(a) do { *(u64*)p = hd->a ; p += 8; } while(0) -#else /* little endian */ -#define X(a) do { *p++ = hd->a >> 56; *p++ = hd->a >> 48; \ - *p++ = hd->a >> 40; *p++ = hd->a >> 32; \ - *p++ = hd->a >> 24; *p++ = hd->a >> 16; \ - *p++ = hd->a >> 8; *p++ = hd->a; } while(0) -#endif -#define Y(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \ - *p++ = hd->a >> 16; *p++ = hd->a >> 24; \ - *p++ = hd->a >> 32; *p++ = hd->a >> 40; \ - *p++ = hd->a >> 48; *p++ = hd->a >> 56; } while(0) +#define X(a) do { *(u64*)p = be_bswap64(hd->a); p += 8; } while(0) +#define Y(a) do { *(u64*)p = le_bswap64(hd->a); p += 8; } while(0) if (hd->variant == 0) { X(a); X(b); X(c); } else { Y(a); Y(b); Y(c); } #undef X #undef Y } static byte * tiger_read( void *context ) { TIGER_CONTEXT *hd = context; return hd->bctx.buf; } /* This is the old TIGER variant based on the unfixed reference implementation. IT was used in GnupG up to 1.3.2. We don't provide an OID anymore because that would not be correct. */ gcry_md_spec_t _gcry_digest_spec_tiger = { "TIGER192", NULL, 0, NULL, 24, tiger_init, _gcry_md_block_write, tiger_final, tiger_read, sizeof (TIGER_CONTEXT) }; /* This is the fixed TIGER implementation. */ static byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */ { 0x30, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0c, 0x02, 0x05, 0x00, 0x04, 0x18 }; static gcry_md_oid_spec_t oid_spec_tiger1[] = { /* GNU.digestAlgorithm TIGER */ { "1.3.6.1.4.1.11591.12.2" }, { NULL } }; gcry_md_spec_t _gcry_digest_spec_tiger1 = { "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24, tiger1_init, _gcry_md_block_write, tiger_final, tiger_read, sizeof (TIGER_CONTEXT) }; /* This is TIGER2 which usues a changed padding algorithm. */ gcry_md_spec_t _gcry_digest_spec_tiger2 = { "TIGER2", NULL, 0, NULL, 24, tiger2_init, _gcry_md_block_write, tiger_final, tiger_read, sizeof (TIGER_CONTEXT) }; #endif /* HAVE_U64_TYPEDEF */ diff --git a/cipher/twofish.c b/cipher/twofish.c index 70cdb475..17b3aa3f 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -1,1318 +1,1317 @@ /* Twofish for GPG * Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. * Written by Matthew Skala , July 26, 1998 * 256-bit key length added March 20, 1999 * Some modifications to reduce the text size by Werner Koch, April, 1998 * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ******************************************************************** * * This code is a "clean room" implementation, written from the paper * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available * through http://www.counterpane.com/twofish.html * * For background information on multiplication in finite fields, used for * the matrix operations in the key schedule, see the book _Contemporary * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the * Third Edition. * * Only the 128- and 256-bit key sizes are supported. This code is intended * for GNU C on a 32-bit system, but it should work almost anywhere. Loops * are unrolled, precomputation tables are used, etc., for maximum speed at * some cost in memory consumption. */ #include #include #include #include /* for memcmp() */ #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" #include "cipher-selftest.h" #define TWOFISH_BLOCKSIZE 16 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) # define USE_AMD64_ASM 1 #endif /* Prototype for the self-test function. */ static const char *selftest(void); /* Structure for an expanded Twofish key. s contains the key-dependent * S-boxes composed with the MDS matrix; w contains the eight "whitening" * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ typedef struct { u32 s[4][256], w[8], k[32]; } TWOFISH_context; /* These two tables are the q0 and q1 permutations, exactly as described in * the Twofish paper. */ static const byte q0[256] = { 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 }; static const byte q1[256] = { 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 }; /* These MDS tables are actually tables of MDS composed with q0 and q1, * because it is only ever used that way and we can save some time by * precomputing. Of course the main saving comes from precomputing the * GF(2^8) multiplication involved in the MDS matrix multiply; by looking * things up in these tables we reduce the matrix multiply to four lookups * and three XORs. Semi-formally, the definition of these tables is: * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T * where ^T means "transpose", the matrix multiply is performed in GF(2^8) * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described * by Schneier et al, and I'm casually glossing over the byte/word * conversion issues. */ static const u32 mds[4][256] = { {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} }; /* The exp_to_poly and poly_to_exp tables are used to perform efficient * operations in GF(2^8) represented as GF(2)[x]/w(x) where * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the * definition of the RS matrix in the key schedule. Elements of that field * are polynomials of degree not greater than 7 and all coefficients 0 or 1, * which can be represented naturally by bytes (just substitute x=2). In that * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) * multiplication is inefficient without hardware support. To multiply * faster, I make use of the fact x is a generator for the nonzero elements, * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for * some n in 0..254. Note that that caret is exponentiation in GF(2^8), * *not* polynomial notation. So if I want to compute pq where p and q are * in GF(2^8), I can just say: * 1. if p=0 or q=0 then pq=0 * 2. otherwise, find m and n such that p=x^m and q=x^n * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq * The translations in steps 2 and 3 are looked up in the tables * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this * in action, look at the CALC_S macro. As additional wrinkles, note that * one of my operands is always a constant, so the poly_to_exp lookup on it * is done in advance; I included the original values in the comments so * readers can have some chance of recognizing that this *is* the RS matrix * from the Twofish paper. I've only included the table entries I actually * need; I never do a lookup on a variable input of zero and the biggest * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll * never sum to more than 491. I'm repeating part of the exp_to_poly table * so that I don't have to do mod-255 reduction in the exponent arithmetic. * Since I know my constant operands are never zero, I only have to worry * about zero values in the variable operand, and I do it with a simple * conditional branch. I know conditionals are expensive, but I couldn't * see a non-horrible way of avoiding them, and I did manage to group the * statements so that each if covers four group multiplications. */ static const byte poly_to_exp[255] = { 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, 0x85, 0xC8, 0xA1 }; static const byte exp_to_poly[492] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB }; /* The table constants are indices of * S-box entries, preprocessed through q0 and q1. */ static byte calc_sb_tbl[512] = { 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 }; /* Macro to perform one column of the RS matrix multiplication. The * parameters a, b, c, and d are the four bytes of output; i is the index * of the key bytes, and w, x, y, and z, are the column of constants from * the RS matrix, preprocessed through the poly_to_exp table. */ #define CALC_S(a, b, c, d, i, w, x, y, z) \ if (key[i]) { \ tmp = poly_to_exp[key[i] - 1]; \ (a) ^= exp_to_poly[tmp + (w)]; \ (b) ^= exp_to_poly[tmp + (x)]; \ (c) ^= exp_to_poly[tmp + (y)]; \ (d) ^= exp_to_poly[tmp + (z)]; \ } /* Macros to calculate the key-dependent S-boxes for a 128-bit key using * the S vector from CALC_S. CALC_SB_2 computes a single entry in all * four S-boxes, where i is the index of the entry to compute, and a and b * are the index numbers preprocessed through the q0 and q1 tables * respectively. CALC_SB is simply a convenience to make the code shorter; * it calls CALC_SB_2 four times with consecutive indices from i to i+3, * using the remaining parameters two by two. */ #define CALC_SB_2(i, a, b) \ ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] #define CALC_SB(i, a, b, c, d, e, f, g, h) \ CALC_SB_2 (i, a, b); CALC_SB_2 ((i)+1, c, d); \ CALC_SB_2 ((i)+2, e, f); CALC_SB_2 ((i)+3, g, h) /* Macros exactly like CALC_SB and CALC_SB_2, but for 256-bit keys. */ #define CALC_SB256_2(i, a, b) \ ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; #define CALC_SB256(i, a, b, c, d, e, f, g, h) \ CALC_SB256_2 (i, a, b); CALC_SB256_2 ((i)+1, c, d); \ CALC_SB256_2 ((i)+2, e, f); CALC_SB256_2 ((i)+3, g, h) /* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the * last two stages of the h() function for a given index (either 2i or 2i+1). * a, b, c, and d are the four bytes going into the last two stages. For * 128-bit keys, this is the entire h() function and a and c are the index * preprocessed through q0 and q1 respectively; for longer keys they are the * output of previous stages. j is the index of the first key byte to use. * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 * twice, doing the Pseudo-Hadamard Transform, and doing the necessary * rotations. Its parameters are: a, the array to write the results into, * j, the index of the first output entry, k and l, the preprocessed indices * for index 2i, and m and n, the preprocessed indices for index 2i+1. * CALC_K256_2 expands CALC_K_2 to handle 256-bit keys, by doing two * additional lookup-and-XOR stages. The parameters a and b are the index * preprocessed through q0 and q1 respectively; j is the index of the first * key byte to use. CALC_K256 is identical to CALC_K but for using the * CALC_K256_2 macro instead of CALC_K_2. */ #define CALC_K_2(a, b, c, d, j) \ mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] #define CALC_K(a, j, k, l, m, n) \ x = CALC_K_2 (k, l, k, l, 0); \ y = CALC_K_2 (m, n, m, n, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) #define CALC_K256_2(a, b, j) \ CALC_K_2 (q0[q1[b ^ key[(j) + 24]] ^ key[(j) + 16]], \ q1[q1[a ^ key[(j) + 25]] ^ key[(j) + 17]], \ q0[q0[a ^ key[(j) + 26]] ^ key[(j) + 18]], \ q1[q0[b ^ key[(j) + 27]] ^ key[(j) + 19]], j) #define CALC_K256(a, j, k, l, m, n) \ x = CALC_K256_2 (k, l, 0); \ y = CALC_K256_2 (m, n, 4); \ y = (y << 8) + (y >> 24); \ x += y; y += x; ctx->a[j] = x; \ ctx->a[(j) + 1] = (y << 9) + (y >> 23) /* Perform the key setup. Note that this works only with 128- and 256-bit * keys, despite the API that looks like it might support other sizes. */ static gcry_err_code_t do_twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen) { int i, j, k; /* Temporaries for CALC_K. */ u32 x, y; /* The S vector used to key the S-boxes, split up into individual bytes. * 128-bit keys use only sa through sh; 256-bit use all of them. */ byte sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; byte si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; /* Temporary for CALC_S. */ byte tmp; /* Flags for self-test. */ static int initialized = 0; static const char *selftest_failed=0; /* Check key length. */ if( ( ( keylen - 16 ) | 16 ) != 16 ) return GPG_ERR_INV_KEYLEN; /* Do self-test if necessary. */ if (!initialized) { initialized = 1; selftest_failed = selftest (); if( selftest_failed ) log_error("%s\n", selftest_failed ); } if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; /* Compute the first two words of the S vector. The magic numbers are * the entries of the RS matrix, preprocessed through poly_to_exp. The * numbers in the comments are the original (polynomial form) matrix * entries. */ CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ if (keylen == 32) /* 256-bit key */ { /* Calculate the remaining two words of the S vector */ CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ /* Compute the S-boxes. */ for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) { CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); } /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); } else { /* Compute the S-boxes. */ for(i=j=0,k=1; i < 256; i++, j += 2, k += 2 ) { CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); } /* Calculate whitening and round subkeys. The constants are * indices of subkeys, preprocessed through q0 and q1. */ CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); } return 0; } static gcry_err_code_t twofish_setkey (void *context, const byte *key, unsigned int keylen) { TWOFISH_context *ctx = context; int rc = do_twofish_setkey (ctx, key, keylen); _gcry_burn_stack (23+6*sizeof(void*)); return rc; } #ifdef USE_AMD64_ASM /* Assembly implementations of Twofish. */ extern void _gcry_twofish_amd64_encrypt_block(const TWOFISH_context *c, byte *out, const byte *in); extern void _gcry_twofish_amd64_decrypt_block(const TWOFISH_context *c, byte *out, const byte *in); /* These assembly implementations process three blocks in parallel. */ extern void _gcry_twofish_amd64_ctr_enc(const TWOFISH_context *c, byte *out, const byte *in, byte *ctr); extern void _gcry_twofish_amd64_cbc_dec(const TWOFISH_context *c, byte *out, const byte *in, byte *iv); extern void _gcry_twofish_amd64_cfb_dec(const TWOFISH_context *c, byte *out, const byte *in, byte *iv); #else /*!USE_AMD64_ASM*/ /* Macros to compute the g() function in the encryption and decryption * rounds. G1 is the straight g() function; G2 includes the 8-bit * rotation for the high 32-bit word. */ #define G1(a) \ (ctx->s[0][(a) & 0xFF]) ^ (ctx->s[1][((a) >> 8) & 0xFF]) \ ^ (ctx->s[2][((a) >> 16) & 0xFF]) ^ (ctx->s[3][(a) >> 24]) #define G2(b) \ (ctx->s[1][(b) & 0xFF]) ^ (ctx->s[2][((b) >> 8) & 0xFF]) \ ^ (ctx->s[3][((b) >> 16) & 0xFF]) ^ (ctx->s[0][(b) >> 24]) /* Encryption and decryption Feistel rounds. Each one calls the two g() * macros, does the PHT, and performs the XOR and the appropriate bit * rotations. The parameters are the round number (used to select subkeys), * and the four 32-bit chunks of the text. */ #define ENCROUND(n, a, b, c, d) \ x = G1 (a); y = G2 (b); \ x += y; y += x + ctx->k[2 * (n) + 1]; \ (c) ^= x + ctx->k[2 * (n)]; \ (c) = ((c) >> 1) + ((c) << 31); \ (d) = (((d) << 1)+((d) >> 31)) ^ y #define DECROUND(n, a, b, c, d) \ x = G1 (a); y = G2 (b); \ x += y; y += x; \ (d) ^= y + ctx->k[2 * (n) + 1]; \ (d) = ((d) >> 1) + ((d) << 31); \ (c) = (((c) << 1)+((c) >> 31)); \ (c) ^= (x + ctx->k[2 * (n)]) /* Encryption and decryption cycles; each one is simply two Feistel rounds * with the 32-bit chunks re-ordered to simulate the "swap" */ #define ENCCYCLE(n) \ ENCROUND (2 * (n), a, b, c, d); \ ENCROUND (2 * (n) + 1, c, d, a, b) #define DECCYCLE(n) \ DECROUND (2 * (n) + 1, c, d, a, b); \ DECROUND (2 * (n), a, b, c, d) /* Macros to convert the input and output bytes into 32-bit words, * and simultaneously perform the whitening step. INPACK packs word * number n into the variable named by x, using whitening subkey number m. * OUTUNPACK unpacks word number n from the variable named by x, using * whitening subkey number m. */ #define INPACK(n, x, m) \ - x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ - ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + x = buf_get_le32(in + (n) * 4); \ + x ^= ctx->w[m] #define OUTUNPACK(n, x, m) \ x ^= ctx->w[m]; \ - out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ - out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + buf_put_le32(out + (n) * 4, x) #endif /*!USE_AMD64_ASM*/ /* Encrypt one block. in and out may be the same. */ #ifdef USE_AMD64_ASM static void do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { _gcry_twofish_amd64_encrypt_block(ctx, out, in); } static unsigned int twofish_encrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; _gcry_twofish_amd64_encrypt_block(ctx, out, in); return /*burn_stack*/ (4*sizeof (void*)); } #else /*!USE_AMD64_ASM*/ static void do_twofish_encrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK (0, a, 0); INPACK (1, b, 1); INPACK (2, c, 2); INPACK (3, d, 3); /* Encryption Feistel cycles. */ ENCCYCLE (0); ENCCYCLE (1); ENCCYCLE (2); ENCCYCLE (3); ENCCYCLE (4); ENCCYCLE (5); ENCCYCLE (6); ENCCYCLE (7); /* Output whitening and unpacking. */ OUTUNPACK (0, c, 4); OUTUNPACK (1, d, 5); OUTUNPACK (2, a, 6); OUTUNPACK (3, b, 7); } static unsigned int twofish_encrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; do_twofish_encrypt (ctx, out, in); return /*burn_stack*/ (24+3*sizeof (void*)); } #endif /*!USE_AMD64_ASM*/ /* Decrypt one block. in and out may be the same. */ #ifdef USE_AMD64_ASM static void do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { _gcry_twofish_amd64_decrypt_block(ctx, out, in); } static unsigned int twofish_decrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; _gcry_twofish_amd64_decrypt_block(ctx, out, in); return /*burn_stack*/ (4*sizeof (void*)); } #else /*!USE_AMD64_ASM*/ static void do_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in) { /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK (0, c, 4); INPACK (1, d, 5); INPACK (2, a, 6); INPACK (3, b, 7); /* Encryption Feistel cycles. */ DECCYCLE (7); DECCYCLE (6); DECCYCLE (5); DECCYCLE (4); DECCYCLE (3); DECCYCLE (2); DECCYCLE (1); DECCYCLE (0); /* Output whitening and unpacking. */ OUTUNPACK (0, a, 0); OUTUNPACK (1, b, 1); OUTUNPACK (2, c, 2); OUTUNPACK (3, d, 3); } static unsigned int twofish_decrypt (void *context, byte *out, const byte *in) { TWOFISH_context *ctx = context; do_twofish_decrypt (ctx, out, in); return /*burn_stack*/ (24+3*sizeof (void*)); } #endif /*!USE_AMD64_ASM*/ /* Bulk encryption of complete blocks in CTR mode. This function is only intended for the bulk encryption feature of cipher.c. CTR is expected to be of size TWOFISH_BLOCKSIZE. */ void _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char tmpbuf[TWOFISH_BLOCKSIZE]; int burn_stack_depth = 24 + 3 * sizeof (void*); int i; #ifdef USE_AMD64_ASM { if (nblocks >= 3 && burn_stack_depth < 8 * sizeof(void*)) burn_stack_depth = 8 * sizeof(void*); /* Process data in 3 block chunks. */ while (nblocks >= 3) { _gcry_twofish_amd64_ctr_enc(ctx, outbuf, inbuf, ctr); nblocks -= 3; outbuf += 3 * TWOFISH_BLOCKSIZE; inbuf += 3 * TWOFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ /* TODO: use caching instead? */ } #endif for ( ;nblocks; nblocks-- ) { /* Encrypt the counter. */ do_twofish_encrypt(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ buf_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE); outbuf += TWOFISH_BLOCKSIZE; inbuf += TWOFISH_BLOCKSIZE; /* Increment the counter. */ for (i = TWOFISH_BLOCKSIZE; i > 0; i--) { ctr[i-1]++; if (ctr[i-1]) break; } } wipememory(tmpbuf, sizeof(tmpbuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CBC mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char savebuf[TWOFISH_BLOCKSIZE]; int burn_stack_depth = 24 + 3 * sizeof (void*); #ifdef USE_AMD64_ASM { if (nblocks >= 3 && burn_stack_depth < 9 * sizeof(void*)) burn_stack_depth = 9 * sizeof(void*); /* Process data in 3 block chunks. */ while (nblocks >= 3) { _gcry_twofish_amd64_cbc_dec(ctx, outbuf, inbuf, iv); nblocks -= 3; outbuf += 3 * TWOFISH_BLOCKSIZE; inbuf += 3 * TWOFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { /* We need to save INBUF away because it may be identical to OUTBUF. */ memcpy(savebuf, inbuf, TWOFISH_BLOCKSIZE); do_twofish_decrypt (ctx, outbuf, inbuf); buf_xor(outbuf, outbuf, iv, TWOFISH_BLOCKSIZE); memcpy(iv, savebuf, TWOFISH_BLOCKSIZE); inbuf += TWOFISH_BLOCKSIZE; outbuf += TWOFISH_BLOCKSIZE; } wipememory(savebuf, sizeof(savebuf)); _gcry_burn_stack(burn_stack_depth); } /* Bulk decryption of complete blocks in CFB mode. This function is only intended for the bulk encryption feature of cipher.c. */ void _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 24 + 3 * sizeof (void*); #ifdef USE_AMD64_ASM { if (nblocks >= 3 && burn_stack_depth < 8 * sizeof(void*)) burn_stack_depth = 8 * sizeof(void*); /* Process data in 3 block chunks. */ while (nblocks >= 3) { _gcry_twofish_amd64_cfb_dec(ctx, outbuf, inbuf, iv); nblocks -= 3; outbuf += 3 * TWOFISH_BLOCKSIZE; inbuf += 3 * TWOFISH_BLOCKSIZE; } /* Use generic code to handle smaller chunks... */ } #endif for ( ;nblocks; nblocks-- ) { do_twofish_encrypt(ctx, iv, iv); buf_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE); outbuf += TWOFISH_BLOCKSIZE; inbuf += TWOFISH_BLOCKSIZE; } _gcry_burn_stack(burn_stack_depth); } /* Run the self-tests for TWOFISH-CTR, tests IV increment of bulk CTR encryption. Returns NULL on success. */ static const char * selftest_ctr (void) { const int nblocks = 3+1; const int blocksize = TWOFISH_BLOCKSIZE; const int context_size = sizeof(TWOFISH_context); return _gcry_selftest_helper_ctr("TWOFISH", &twofish_setkey, &twofish_encrypt, &_gcry_twofish_ctr_enc, nblocks, blocksize, context_size); } /* Run the self-tests for TWOFISH-CBC, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cbc (void) { const int nblocks = 3+2; const int blocksize = TWOFISH_BLOCKSIZE; const int context_size = sizeof(TWOFISH_context); return _gcry_selftest_helper_cbc("TWOFISH", &twofish_setkey, &twofish_encrypt, &_gcry_twofish_cbc_dec, nblocks, blocksize, context_size); } /* Run the self-tests for TWOFISH-CFB, tests bulk CBC decryption. Returns NULL on success. */ static const char * selftest_cfb (void) { const int nblocks = 3+2; const int blocksize = TWOFISH_BLOCKSIZE; const int context_size = sizeof(TWOFISH_context); return _gcry_selftest_helper_cfb("TWOFISH", &twofish_setkey, &twofish_encrypt, &_gcry_twofish_cfb_dec, nblocks, blocksize, context_size); } /* Test a single encryption and decryption with each key size. */ static const char* selftest (void) { TWOFISH_context ctx; /* Expanded key. */ byte scratch[16]; /* Encryption/decryption result buffer. */ const char *r; /* Test vectors for single encryption/decryption. Note that I am using * the vectors from the Twofish paper's "known answer test", I=3 for * 128-bit and I=4 for 256-bit, instead of the all-0 vectors from the * "intermediate value test", because an all-0 key would trigger all the * special cases in the RS matrix multiply, leaving the math untested. */ static byte plaintext[16] = { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }; static byte key[16] = { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }; static const byte ciphertext[16] = { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 }; static byte plaintext_256[16] = { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }; static byte key_256[32] = { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }; static const byte ciphertext_256[16] = { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA }; twofish_setkey (&ctx, key, sizeof(key)); twofish_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "Twofish-128 test encryption failed."; twofish_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "Twofish-128 test decryption failed."; twofish_setkey (&ctx, key_256, sizeof(key_256)); twofish_encrypt (&ctx, scratch, plaintext_256); if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) return "Twofish-256 test encryption failed."; twofish_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) return "Twofish-256 test decryption failed."; if ((r = selftest_ctr()) != NULL) return r; if ((r = selftest_cbc()) != NULL) return r; if ((r = selftest_cfb()) != NULL) return r; return NULL; } /* More complete test program. This does 1000 encryptions and decryptions * with each of 250 128-bit keys and 2000 encryptions and decryptions with * each of 125 256-bit keys, using a feedback scheme similar to a Feistel * cipher, so as to be sure of testing all the table entries pretty * thoroughly. We keep changing the keys so as to get a more meaningful * performance number, since the key setup is non-trivial for Twofish. */ #ifdef TEST #include #include #include int main() { TWOFISH_context ctx; /* Expanded key. */ int i, j; /* Loop counters. */ const char *encrypt_msg; /* Message to print regarding encryption test; * the printf is done outside the loop to avoid * stuffing up the timing. */ clock_t timer; /* For computing elapsed time. */ /* Test buffer. */ byte buffer[4][16] = { {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} }; /* Expected outputs for the million-operation test */ static const byte test_encrypt[4][16] = { {0xC8, 0x23, 0xB8, 0xB7, 0x6B, 0xFE, 0x91, 0x13, 0x2F, 0xA7, 0x5E, 0xE6, 0x94, 0x77, 0x6F, 0x6B}, {0x90, 0x36, 0xD8, 0x29, 0xD5, 0x96, 0xC2, 0x8E, 0xE4, 0xFF, 0x76, 0xBC, 0xE5, 0x77, 0x88, 0x27}, {0xB8, 0x78, 0x69, 0xAF, 0x42, 0x8B, 0x48, 0x64, 0xF7, 0xE9, 0xF3, 0x9C, 0x42, 0x18, 0x7B, 0x73}, {0x7A, 0x88, 0xFB, 0xEB, 0x90, 0xA4, 0xB4, 0xA8, 0x43, 0xA3, 0x1D, 0xF1, 0x26, 0xC4, 0x53, 0x57} }; static const byte test_decrypt[4][16] = { {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} }; /* Start the timer ticking. */ timer = clock (); /* Encryption test. */ for (i = 0; i < 125; i++) { twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); for (j = 0; j < 1000; j++) twofish_encrypt (&ctx, buffer[2], buffer[2]); twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); for (j = 0; j < 1000; j++) twofish_encrypt (&ctx, buffer[3], buffer[3]); twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); for (j = 0; j < 1000; j++) { twofish_encrypt (&ctx, buffer[0], buffer[0]); twofish_encrypt (&ctx, buffer[1], buffer[1]); } } encrypt_msg = memcmp (buffer, test_encrypt, sizeof (test_encrypt)) ? "encryption failure!\n" : "encryption OK!\n"; /* Decryption test. */ for (i = 0; i < 125; i++) { twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); for (j = 0; j < 1000; j++) { twofish_decrypt (&ctx, buffer[0], buffer[0]); twofish_decrypt (&ctx, buffer[1], buffer[1]); } twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); for (j = 0; j < 1000; j++) twofish_decrypt (&ctx, buffer[3], buffer[3]); twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); for (j = 0; j < 1000; j++) twofish_decrypt (&ctx, buffer[2], buffer[2]); } /* Stop the timer, and print results. */ timer = clock () - timer; printf (encrypt_msg); printf (memcmp (buffer, test_decrypt, sizeof (test_decrypt)) ? "decryption failure!\n" : "decryption OK!\n"); printf ("elapsed time: %.1f s.\n", (float) timer / CLOCKS_PER_SEC); return 0; } #endif /* TEST */ gcry_cipher_spec_t _gcry_cipher_spec_twofish = { "TWOFISH", NULL, NULL, 16, 256, sizeof (TWOFISH_context), twofish_setkey, twofish_encrypt, twofish_decrypt }; gcry_cipher_spec_t _gcry_cipher_spec_twofish128 = { "TWOFISH128", NULL, NULL, 16, 128, sizeof (TWOFISH_context), twofish_setkey, twofish_encrypt, twofish_decrypt }; diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 2c3beb7e..954640ac 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -1,1401 +1,1384 @@ /* whirlpool.c - Whirlpool hashing algorithm * Copyright (C) 2005 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ /* This is an implementation of the Whirlpool hashing algorithm, which has been developed by Vincent Rijmen and Paulo S. L. M. Barreto; it's homepage is located at: http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html The S-Boxes and the structure of the main transformation function, which implements an optimized version of the algorithm, is taken from the reference implementation available from http://www.larc.usp.br/~pbarreto/whirlpool.zip */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" -#include "bithelp.h" +#include "bufhelp.h" /* Size of a whirlpool block (in bytes). */ #define BLOCK_SIZE 64 /* Number of rounds. */ #define R 10 /* Types. */ typedef u64 whirlpool_block_t[BLOCK_SIZE / 8]; typedef struct { whirlpool_block_t hash_state; unsigned char buffer[BLOCK_SIZE]; size_t count; unsigned char length[32]; } whirlpool_context_t; /* Macros. */ /* Convert the the buffer BUFFER into a block BLOCK, using I as counter. */ #define buffer_to_block(buffer, block, i) \ for (i = 0; i < 8; i++) \ - (block)[i] = ((u64) (0 \ - | (((u64) (buffer)[i * 8 + 0]) << 56) \ - | (((u64) (buffer)[i * 8 + 1]) << 48) \ - | (((u64) (buffer)[i * 8 + 2]) << 40) \ - | (((u64) (buffer)[i * 8 + 3]) << 32) \ - | (((u64) (buffer)[i * 8 + 4]) << 24) \ - | (((u64) (buffer)[i * 8 + 5]) << 16) \ - | (((u64) (buffer)[i * 8 + 6]) << 8) \ - | (((u64) (buffer)[i * 8 + 7]) << 0))); + (block)[i] = buf_get_be64((buffer) + i * 8); /* Convert the block BLOCK into a buffer BUFFER, using I as counter. */ #define block_to_buffer(buffer, block, i) \ for (i = 0; i < 8; i++) \ - { \ - (buffer)[i * 8 + 0] = (block[i] >> 56) & 0xFF; \ - (buffer)[i * 8 + 1] = (block[i] >> 48) & 0xFF; \ - (buffer)[i * 8 + 2] = (block[i] >> 40) & 0xFF; \ - (buffer)[i * 8 + 3] = (block[i] >> 32) & 0xFF; \ - (buffer)[i * 8 + 4] = (block[i] >> 24) & 0xFF; \ - (buffer)[i * 8 + 5] = (block[i] >> 16) & 0xFF; \ - (buffer)[i * 8 + 6] = (block[i] >> 8) & 0xFF; \ - (buffer)[i * 8 + 7] = (block[i] >> 0) & 0xFF; \ - } + buf_put_be64((buffer) + i * 8, (block)[i]); /* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */ #define block_copy(block_dst, block_src, i) \ for (i = 0; i < 8; i++) \ block_dst[i] = block_src[i]; /* XOR the block BLOCK_SRC into BLOCK_DST, using I as counter. */ #define block_xor(block_dst, block_src, i) \ for (i = 0; i < 8; i++) \ block_dst[i] ^= block_src[i]; /* Round constants. */ static const u64 rc[R] = { U64_C (0x1823c6e887b8014f), U64_C (0x36a6d2f5796f9152), U64_C (0x60bc9b8ea30c7b35), U64_C (0x1de0d7c22e4bfe57), U64_C (0x157737e59ff04ada), U64_C (0x58c9290ab1a06b85), U64_C (0xbd5d10f4cb3e0567), U64_C (0xe427418ba77d95d8), U64_C (0xfbee7c66dd17479e), U64_C (0xca2dbf07ad5a8333), }; /* Main lookup boxes. */ static const u64 C0[256] = { U64_C (0x18186018c07830d8), U64_C (0x23238c2305af4626), U64_C (0xc6c63fc67ef991b8), U64_C (0xe8e887e8136fcdfb), U64_C (0x878726874ca113cb), U64_C (0xb8b8dab8a9626d11), U64_C (0x0101040108050209), U64_C (0x4f4f214f426e9e0d), U64_C (0x3636d836adee6c9b), U64_C (0xa6a6a2a6590451ff), U64_C (0xd2d26fd2debdb90c), U64_C (0xf5f5f3f5fb06f70e), U64_C (0x7979f979ef80f296), U64_C (0x6f6fa16f5fcede30), U64_C (0x91917e91fcef3f6d), U64_C (0x52525552aa07a4f8), U64_C (0x60609d6027fdc047), U64_C (0xbcbccabc89766535), U64_C (0x9b9b569baccd2b37), U64_C (0x8e8e028e048c018a), U64_C (0xa3a3b6a371155bd2), U64_C (0x0c0c300c603c186c), U64_C (0x7b7bf17bff8af684), U64_C (0x3535d435b5e16a80), U64_C (0x1d1d741de8693af5), U64_C (0xe0e0a7e05347ddb3), U64_C (0xd7d77bd7f6acb321), U64_C (0xc2c22fc25eed999c), U64_C (0x2e2eb82e6d965c43), U64_C (0x4b4b314b627a9629), U64_C (0xfefedffea321e15d), U64_C (0x575741578216aed5), U64_C (0x15155415a8412abd), U64_C (0x7777c1779fb6eee8), U64_C (0x3737dc37a5eb6e92), U64_C (0xe5e5b3e57b56d79e), U64_C (0x9f9f469f8cd92313), U64_C (0xf0f0e7f0d317fd23), U64_C (0x4a4a354a6a7f9420), U64_C (0xdada4fda9e95a944), U64_C (0x58587d58fa25b0a2), U64_C (0xc9c903c906ca8fcf), U64_C (0x2929a429558d527c), U64_C (0x0a0a280a5022145a), U64_C (0xb1b1feb1e14f7f50), U64_C (0xa0a0baa0691a5dc9), U64_C (0x6b6bb16b7fdad614), U64_C (0x85852e855cab17d9), U64_C (0xbdbdcebd8173673c), U64_C (0x5d5d695dd234ba8f), U64_C (0x1010401080502090), U64_C (0xf4f4f7f4f303f507), U64_C (0xcbcb0bcb16c08bdd), U64_C (0x3e3ef83eedc67cd3), U64_C (0x0505140528110a2d), U64_C (0x676781671fe6ce78), U64_C (0xe4e4b7e47353d597), U64_C (0x27279c2725bb4e02), U64_C (0x4141194132588273), U64_C (0x8b8b168b2c9d0ba7), U64_C (0xa7a7a6a7510153f6), U64_C (0x7d7de97dcf94fab2), U64_C (0x95956e95dcfb3749), U64_C (0xd8d847d88e9fad56), U64_C (0xfbfbcbfb8b30eb70), U64_C (0xeeee9fee2371c1cd), U64_C (0x7c7ced7cc791f8bb), U64_C (0x6666856617e3cc71), U64_C (0xdddd53dda68ea77b), U64_C (0x17175c17b84b2eaf), U64_C (0x4747014702468e45), U64_C (0x9e9e429e84dc211a), U64_C (0xcaca0fca1ec589d4), U64_C (0x2d2db42d75995a58), U64_C (0xbfbfc6bf9179632e), U64_C (0x07071c07381b0e3f), U64_C (0xadad8ead012347ac), U64_C (0x5a5a755aea2fb4b0), U64_C (0x838336836cb51bef), U64_C (0x3333cc3385ff66b6), U64_C (0x636391633ff2c65c), U64_C (0x02020802100a0412), U64_C (0xaaaa92aa39384993), U64_C (0x7171d971afa8e2de), U64_C (0xc8c807c80ecf8dc6), U64_C (0x19196419c87d32d1), U64_C (0x494939497270923b), U64_C (0xd9d943d9869aaf5f), U64_C (0xf2f2eff2c31df931), U64_C (0xe3e3abe34b48dba8), U64_C (0x5b5b715be22ab6b9), U64_C (0x88881a8834920dbc), U64_C (0x9a9a529aa4c8293e), U64_C (0x262698262dbe4c0b), U64_C (0x3232c8328dfa64bf), U64_C (0xb0b0fab0e94a7d59), U64_C (0xe9e983e91b6acff2), U64_C (0x0f0f3c0f78331e77), U64_C (0xd5d573d5e6a6b733), U64_C (0x80803a8074ba1df4), U64_C (0xbebec2be997c6127), U64_C (0xcdcd13cd26de87eb), U64_C (0x3434d034bde46889), U64_C (0x48483d487a759032), U64_C (0xffffdbffab24e354), U64_C (0x7a7af57af78ff48d), U64_C (0x90907a90f4ea3d64), U64_C (0x5f5f615fc23ebe9d), U64_C (0x202080201da0403d), U64_C (0x6868bd6867d5d00f), U64_C (0x1a1a681ad07234ca), U64_C (0xaeae82ae192c41b7), U64_C (0xb4b4eab4c95e757d), U64_C (0x54544d549a19a8ce), U64_C (0x93937693ece53b7f), U64_C (0x222288220daa442f), U64_C (0x64648d6407e9c863), U64_C (0xf1f1e3f1db12ff2a), U64_C (0x7373d173bfa2e6cc), U64_C (0x12124812905a2482), U64_C (0x40401d403a5d807a), U64_C (0x0808200840281048), U64_C (0xc3c32bc356e89b95), U64_C (0xecec97ec337bc5df), U64_C (0xdbdb4bdb9690ab4d), U64_C (0xa1a1bea1611f5fc0), U64_C (0x8d8d0e8d1c830791), U64_C (0x3d3df43df5c97ac8), U64_C (0x97976697ccf1335b), U64_C (0x0000000000000000), U64_C (0xcfcf1bcf36d483f9), U64_C (0x2b2bac2b4587566e), U64_C (0x7676c57697b3ece1), U64_C (0x8282328264b019e6), U64_C (0xd6d67fd6fea9b128), U64_C (0x1b1b6c1bd87736c3), U64_C (0xb5b5eeb5c15b7774), U64_C (0xafaf86af112943be), U64_C (0x6a6ab56a77dfd41d), U64_C (0x50505d50ba0da0ea), U64_C (0x45450945124c8a57), U64_C (0xf3f3ebf3cb18fb38), U64_C (0x3030c0309df060ad), U64_C (0xefef9bef2b74c3c4), U64_C (0x3f3ffc3fe5c37eda), U64_C (0x55554955921caac7), U64_C (0xa2a2b2a2791059db), U64_C (0xeaea8fea0365c9e9), U64_C (0x656589650fecca6a), U64_C (0xbabad2bab9686903), U64_C (0x2f2fbc2f65935e4a), U64_C (0xc0c027c04ee79d8e), U64_C (0xdede5fdebe81a160), U64_C (0x1c1c701ce06c38fc), U64_C (0xfdfdd3fdbb2ee746), U64_C (0x4d4d294d52649a1f), U64_C (0x92927292e4e03976), U64_C (0x7575c9758fbceafa), U64_C (0x06061806301e0c36), U64_C (0x8a8a128a249809ae), U64_C (0xb2b2f2b2f940794b), U64_C (0xe6e6bfe66359d185), U64_C (0x0e0e380e70361c7e), U64_C (0x1f1f7c1ff8633ee7), U64_C (0x6262956237f7c455), U64_C (0xd4d477d4eea3b53a), U64_C (0xa8a89aa829324d81), U64_C (0x96966296c4f43152), U64_C (0xf9f9c3f99b3aef62), U64_C (0xc5c533c566f697a3), U64_C (0x2525942535b14a10), U64_C (0x59597959f220b2ab), U64_C (0x84842a8454ae15d0), U64_C (0x7272d572b7a7e4c5), U64_C (0x3939e439d5dd72ec), U64_C (0x4c4c2d4c5a619816), U64_C (0x5e5e655eca3bbc94), U64_C (0x7878fd78e785f09f), U64_C (0x3838e038ddd870e5), U64_C (0x8c8c0a8c14860598), U64_C (0xd1d163d1c6b2bf17), U64_C (0xa5a5aea5410b57e4), U64_C (0xe2e2afe2434dd9a1), U64_C (0x616199612ff8c24e), U64_C (0xb3b3f6b3f1457b42), U64_C (0x2121842115a54234), U64_C (0x9c9c4a9c94d62508), U64_C (0x1e1e781ef0663cee), U64_C (0x4343114322528661), U64_C (0xc7c73bc776fc93b1), U64_C (0xfcfcd7fcb32be54f), U64_C (0x0404100420140824), U64_C (0x51515951b208a2e3), U64_C (0x99995e99bcc72f25), U64_C (0x6d6da96d4fc4da22), U64_C (0x0d0d340d68391a65), U64_C (0xfafacffa8335e979), U64_C (0xdfdf5bdfb684a369), U64_C (0x7e7ee57ed79bfca9), U64_C (0x242490243db44819), U64_C (0x3b3bec3bc5d776fe), U64_C (0xabab96ab313d4b9a), U64_C (0xcece1fce3ed181f0), U64_C (0x1111441188552299), U64_C (0x8f8f068f0c890383), U64_C (0x4e4e254e4a6b9c04), U64_C (0xb7b7e6b7d1517366), U64_C (0xebeb8beb0b60cbe0), U64_C (0x3c3cf03cfdcc78c1), U64_C (0x81813e817cbf1ffd), U64_C (0x94946a94d4fe3540), U64_C (0xf7f7fbf7eb0cf31c), U64_C (0xb9b9deb9a1676f18), U64_C (0x13134c13985f268b), U64_C (0x2c2cb02c7d9c5851), U64_C (0xd3d36bd3d6b8bb05), U64_C (0xe7e7bbe76b5cd38c), U64_C (0x6e6ea56e57cbdc39), U64_C (0xc4c437c46ef395aa), U64_C (0x03030c03180f061b), U64_C (0x565645568a13acdc), U64_C (0x44440d441a49885e), U64_C (0x7f7fe17fdf9efea0), U64_C (0xa9a99ea921374f88), U64_C (0x2a2aa82a4d825467), U64_C (0xbbbbd6bbb16d6b0a), U64_C (0xc1c123c146e29f87), U64_C (0x53535153a202a6f1), U64_C (0xdcdc57dcae8ba572), U64_C (0x0b0b2c0b58271653), U64_C (0x9d9d4e9d9cd32701), U64_C (0x6c6cad6c47c1d82b), U64_C (0x3131c43195f562a4), U64_C (0x7474cd7487b9e8f3), U64_C (0xf6f6fff6e309f115), U64_C (0x464605460a438c4c), U64_C (0xacac8aac092645a5), U64_C (0x89891e893c970fb5), U64_C (0x14145014a04428b4), U64_C (0xe1e1a3e15b42dfba), U64_C (0x16165816b04e2ca6), U64_C (0x3a3ae83acdd274f7), U64_C (0x6969b9696fd0d206), U64_C (0x09092409482d1241), U64_C (0x7070dd70a7ade0d7), U64_C (0xb6b6e2b6d954716f), U64_C (0xd0d067d0ceb7bd1e), U64_C (0xeded93ed3b7ec7d6), U64_C (0xcccc17cc2edb85e2), U64_C (0x424215422a578468), U64_C (0x98985a98b4c22d2c), U64_C (0xa4a4aaa4490e55ed), U64_C (0x2828a0285d885075), U64_C (0x5c5c6d5cda31b886), U64_C (0xf8f8c7f8933fed6b), U64_C (0x8686228644a411c2), }; static const u64 C1[256] = { U64_C (0xd818186018c07830), U64_C (0x2623238c2305af46), U64_C (0xb8c6c63fc67ef991), U64_C (0xfbe8e887e8136fcd), U64_C (0xcb878726874ca113), U64_C (0x11b8b8dab8a9626d), U64_C (0x0901010401080502), U64_C (0x0d4f4f214f426e9e), U64_C (0x9b3636d836adee6c), U64_C (0xffa6a6a2a6590451), U64_C (0x0cd2d26fd2debdb9), U64_C (0x0ef5f5f3f5fb06f7), U64_C (0x967979f979ef80f2), U64_C (0x306f6fa16f5fcede), U64_C (0x6d91917e91fcef3f), U64_C (0xf852525552aa07a4), U64_C (0x4760609d6027fdc0), U64_C (0x35bcbccabc897665), U64_C (0x379b9b569baccd2b), U64_C (0x8a8e8e028e048c01), U64_C (0xd2a3a3b6a371155b), U64_C (0x6c0c0c300c603c18), U64_C (0x847b7bf17bff8af6), U64_C (0x803535d435b5e16a), U64_C (0xf51d1d741de8693a), U64_C (0xb3e0e0a7e05347dd), U64_C (0x21d7d77bd7f6acb3), U64_C (0x9cc2c22fc25eed99), U64_C (0x432e2eb82e6d965c), U64_C (0x294b4b314b627a96), U64_C (0x5dfefedffea321e1), U64_C (0xd5575741578216ae), U64_C (0xbd15155415a8412a), U64_C (0xe87777c1779fb6ee), U64_C (0x923737dc37a5eb6e), U64_C (0x9ee5e5b3e57b56d7), U64_C (0x139f9f469f8cd923), U64_C (0x23f0f0e7f0d317fd), U64_C (0x204a4a354a6a7f94), U64_C (0x44dada4fda9e95a9), U64_C (0xa258587d58fa25b0), U64_C (0xcfc9c903c906ca8f), U64_C (0x7c2929a429558d52), U64_C (0x5a0a0a280a502214), U64_C (0x50b1b1feb1e14f7f), U64_C (0xc9a0a0baa0691a5d), U64_C (0x146b6bb16b7fdad6), U64_C (0xd985852e855cab17), U64_C (0x3cbdbdcebd817367), U64_C (0x8f5d5d695dd234ba), U64_C (0x9010104010805020), U64_C (0x07f4f4f7f4f303f5), U64_C (0xddcbcb0bcb16c08b), U64_C (0xd33e3ef83eedc67c), U64_C (0x2d0505140528110a), U64_C (0x78676781671fe6ce), U64_C (0x97e4e4b7e47353d5), U64_C (0x0227279c2725bb4e), U64_C (0x7341411941325882), U64_C (0xa78b8b168b2c9d0b), U64_C (0xf6a7a7a6a7510153), U64_C (0xb27d7de97dcf94fa), U64_C (0x4995956e95dcfb37), U64_C (0x56d8d847d88e9fad), U64_C (0x70fbfbcbfb8b30eb), U64_C (0xcdeeee9fee2371c1), U64_C (0xbb7c7ced7cc791f8), U64_C (0x716666856617e3cc), U64_C (0x7bdddd53dda68ea7), U64_C (0xaf17175c17b84b2e), U64_C (0x454747014702468e), U64_C (0x1a9e9e429e84dc21), U64_C (0xd4caca0fca1ec589), U64_C (0x582d2db42d75995a), U64_C (0x2ebfbfc6bf917963), U64_C (0x3f07071c07381b0e), U64_C (0xacadad8ead012347), U64_C (0xb05a5a755aea2fb4), U64_C (0xef838336836cb51b), U64_C (0xb63333cc3385ff66), U64_C (0x5c636391633ff2c6), U64_C (0x1202020802100a04), U64_C (0x93aaaa92aa393849), U64_C (0xde7171d971afa8e2), U64_C (0xc6c8c807c80ecf8d), U64_C (0xd119196419c87d32), U64_C (0x3b49493949727092), U64_C (0x5fd9d943d9869aaf), U64_C (0x31f2f2eff2c31df9), U64_C (0xa8e3e3abe34b48db), U64_C (0xb95b5b715be22ab6), U64_C (0xbc88881a8834920d), U64_C (0x3e9a9a529aa4c829), U64_C (0x0b262698262dbe4c), U64_C (0xbf3232c8328dfa64), U64_C (0x59b0b0fab0e94a7d), U64_C (0xf2e9e983e91b6acf), U64_C (0x770f0f3c0f78331e), U64_C (0x33d5d573d5e6a6b7), U64_C (0xf480803a8074ba1d), U64_C (0x27bebec2be997c61), U64_C (0xebcdcd13cd26de87), U64_C (0x893434d034bde468), U64_C (0x3248483d487a7590), U64_C (0x54ffffdbffab24e3), U64_C (0x8d7a7af57af78ff4), U64_C (0x6490907a90f4ea3d), U64_C (0x9d5f5f615fc23ebe), U64_C (0x3d202080201da040), U64_C (0x0f6868bd6867d5d0), U64_C (0xca1a1a681ad07234), U64_C (0xb7aeae82ae192c41), U64_C (0x7db4b4eab4c95e75), U64_C (0xce54544d549a19a8), U64_C (0x7f93937693ece53b), U64_C (0x2f222288220daa44), U64_C (0x6364648d6407e9c8), U64_C (0x2af1f1e3f1db12ff), U64_C (0xcc7373d173bfa2e6), U64_C (0x8212124812905a24), U64_C (0x7a40401d403a5d80), U64_C (0x4808082008402810), U64_C (0x95c3c32bc356e89b), U64_C (0xdfecec97ec337bc5), U64_C (0x4ddbdb4bdb9690ab), U64_C (0xc0a1a1bea1611f5f), U64_C (0x918d8d0e8d1c8307), U64_C (0xc83d3df43df5c97a), U64_C (0x5b97976697ccf133), U64_C (0x0000000000000000), U64_C (0xf9cfcf1bcf36d483), U64_C (0x6e2b2bac2b458756), U64_C (0xe17676c57697b3ec), U64_C (0xe68282328264b019), U64_C (0x28d6d67fd6fea9b1), U64_C (0xc31b1b6c1bd87736), U64_C (0x74b5b5eeb5c15b77), U64_C (0xbeafaf86af112943), U64_C (0x1d6a6ab56a77dfd4), U64_C (0xea50505d50ba0da0), U64_C (0x5745450945124c8a), U64_C (0x38f3f3ebf3cb18fb), U64_C (0xad3030c0309df060), U64_C (0xc4efef9bef2b74c3), U64_C (0xda3f3ffc3fe5c37e), U64_C (0xc755554955921caa), U64_C (0xdba2a2b2a2791059), U64_C (0xe9eaea8fea0365c9), U64_C (0x6a656589650fecca), U64_C (0x03babad2bab96869), U64_C (0x4a2f2fbc2f65935e), U64_C (0x8ec0c027c04ee79d), U64_C (0x60dede5fdebe81a1), U64_C (0xfc1c1c701ce06c38), U64_C (0x46fdfdd3fdbb2ee7), U64_C (0x1f4d4d294d52649a), U64_C (0x7692927292e4e039), U64_C (0xfa7575c9758fbcea), U64_C (0x3606061806301e0c), U64_C (0xae8a8a128a249809), U64_C (0x4bb2b2f2b2f94079), U64_C (0x85e6e6bfe66359d1), U64_C (0x7e0e0e380e70361c), U64_C (0xe71f1f7c1ff8633e), U64_C (0x556262956237f7c4), U64_C (0x3ad4d477d4eea3b5), U64_C (0x81a8a89aa829324d), U64_C (0x5296966296c4f431), U64_C (0x62f9f9c3f99b3aef), U64_C (0xa3c5c533c566f697), U64_C (0x102525942535b14a), U64_C (0xab59597959f220b2), U64_C (0xd084842a8454ae15), U64_C (0xc57272d572b7a7e4), U64_C (0xec3939e439d5dd72), U64_C (0x164c4c2d4c5a6198), U64_C (0x945e5e655eca3bbc), U64_C (0x9f7878fd78e785f0), U64_C (0xe53838e038ddd870), U64_C (0x988c8c0a8c148605), U64_C (0x17d1d163d1c6b2bf), U64_C (0xe4a5a5aea5410b57), U64_C (0xa1e2e2afe2434dd9), U64_C (0x4e616199612ff8c2), U64_C (0x42b3b3f6b3f1457b), U64_C (0x342121842115a542), U64_C (0x089c9c4a9c94d625), U64_C (0xee1e1e781ef0663c), U64_C (0x6143431143225286), U64_C (0xb1c7c73bc776fc93), U64_C (0x4ffcfcd7fcb32be5), U64_C (0x2404041004201408), U64_C (0xe351515951b208a2), U64_C (0x2599995e99bcc72f), U64_C (0x226d6da96d4fc4da), U64_C (0x650d0d340d68391a), U64_C (0x79fafacffa8335e9), U64_C (0x69dfdf5bdfb684a3), U64_C (0xa97e7ee57ed79bfc), U64_C (0x19242490243db448), U64_C (0xfe3b3bec3bc5d776), U64_C (0x9aabab96ab313d4b), U64_C (0xf0cece1fce3ed181), U64_C (0x9911114411885522), U64_C (0x838f8f068f0c8903), U64_C (0x044e4e254e4a6b9c), U64_C (0x66b7b7e6b7d15173), U64_C (0xe0ebeb8beb0b60cb), U64_C (0xc13c3cf03cfdcc78), U64_C (0xfd81813e817cbf1f), U64_C (0x4094946a94d4fe35), U64_C (0x1cf7f7fbf7eb0cf3), U64_C (0x18b9b9deb9a1676f), U64_C (0x8b13134c13985f26), U64_C (0x512c2cb02c7d9c58), U64_C (0x05d3d36bd3d6b8bb), U64_C (0x8ce7e7bbe76b5cd3), U64_C (0x396e6ea56e57cbdc), U64_C (0xaac4c437c46ef395), U64_C (0x1b03030c03180f06), U64_C (0xdc565645568a13ac), U64_C (0x5e44440d441a4988), U64_C (0xa07f7fe17fdf9efe), U64_C (0x88a9a99ea921374f), U64_C (0x672a2aa82a4d8254), U64_C (0x0abbbbd6bbb16d6b), U64_C (0x87c1c123c146e29f), U64_C (0xf153535153a202a6), U64_C (0x72dcdc57dcae8ba5), U64_C (0x530b0b2c0b582716), U64_C (0x019d9d4e9d9cd327), U64_C (0x2b6c6cad6c47c1d8), U64_C (0xa43131c43195f562), U64_C (0xf37474cd7487b9e8), U64_C (0x15f6f6fff6e309f1), U64_C (0x4c464605460a438c), U64_C (0xa5acac8aac092645), U64_C (0xb589891e893c970f), U64_C (0xb414145014a04428), U64_C (0xbae1e1a3e15b42df), U64_C (0xa616165816b04e2c), U64_C (0xf73a3ae83acdd274), U64_C (0x066969b9696fd0d2), U64_C (0x4109092409482d12), U64_C (0xd77070dd70a7ade0), U64_C (0x6fb6b6e2b6d95471), U64_C (0x1ed0d067d0ceb7bd), U64_C (0xd6eded93ed3b7ec7), U64_C (0xe2cccc17cc2edb85), U64_C (0x68424215422a5784), U64_C (0x2c98985a98b4c22d), U64_C (0xeda4a4aaa4490e55), U64_C (0x752828a0285d8850), U64_C (0x865c5c6d5cda31b8), U64_C (0x6bf8f8c7f8933fed), U64_C (0xc28686228644a411), }; static const u64 C2[256] = { U64_C (0x30d818186018c078), U64_C (0x462623238c2305af), U64_C (0x91b8c6c63fc67ef9), U64_C (0xcdfbe8e887e8136f), U64_C (0x13cb878726874ca1), U64_C (0x6d11b8b8dab8a962), U64_C (0x0209010104010805), U64_C (0x9e0d4f4f214f426e), U64_C (0x6c9b3636d836adee), U64_C (0x51ffa6a6a2a65904), U64_C (0xb90cd2d26fd2debd), U64_C (0xf70ef5f5f3f5fb06), U64_C (0xf2967979f979ef80), U64_C (0xde306f6fa16f5fce), U64_C (0x3f6d91917e91fcef), U64_C (0xa4f852525552aa07), U64_C (0xc04760609d6027fd), U64_C (0x6535bcbccabc8976), U64_C (0x2b379b9b569baccd), U64_C (0x018a8e8e028e048c), U64_C (0x5bd2a3a3b6a37115), U64_C (0x186c0c0c300c603c), U64_C (0xf6847b7bf17bff8a), U64_C (0x6a803535d435b5e1), U64_C (0x3af51d1d741de869), U64_C (0xddb3e0e0a7e05347), U64_C (0xb321d7d77bd7f6ac), U64_C (0x999cc2c22fc25eed), U64_C (0x5c432e2eb82e6d96), U64_C (0x96294b4b314b627a), U64_C (0xe15dfefedffea321), U64_C (0xaed5575741578216), U64_C (0x2abd15155415a841), U64_C (0xeee87777c1779fb6), U64_C (0x6e923737dc37a5eb), U64_C (0xd79ee5e5b3e57b56), U64_C (0x23139f9f469f8cd9), U64_C (0xfd23f0f0e7f0d317), U64_C (0x94204a4a354a6a7f), U64_C (0xa944dada4fda9e95), U64_C (0xb0a258587d58fa25), U64_C (0x8fcfc9c903c906ca), U64_C (0x527c2929a429558d), U64_C (0x145a0a0a280a5022), U64_C (0x7f50b1b1feb1e14f), U64_C (0x5dc9a0a0baa0691a), U64_C (0xd6146b6bb16b7fda), U64_C (0x17d985852e855cab), U64_C (0x673cbdbdcebd8173), U64_C (0xba8f5d5d695dd234), U64_C (0x2090101040108050), U64_C (0xf507f4f4f7f4f303), U64_C (0x8bddcbcb0bcb16c0), U64_C (0x7cd33e3ef83eedc6), U64_C (0x0a2d050514052811), U64_C (0xce78676781671fe6), U64_C (0xd597e4e4b7e47353), U64_C (0x4e0227279c2725bb), U64_C (0x8273414119413258), U64_C (0x0ba78b8b168b2c9d), U64_C (0x53f6a7a7a6a75101), U64_C (0xfab27d7de97dcf94), U64_C (0x374995956e95dcfb), U64_C (0xad56d8d847d88e9f), U64_C (0xeb70fbfbcbfb8b30), U64_C (0xc1cdeeee9fee2371), U64_C (0xf8bb7c7ced7cc791), U64_C (0xcc716666856617e3), U64_C (0xa77bdddd53dda68e), U64_C (0x2eaf17175c17b84b), U64_C (0x8e45474701470246), U64_C (0x211a9e9e429e84dc), U64_C (0x89d4caca0fca1ec5), U64_C (0x5a582d2db42d7599), U64_C (0x632ebfbfc6bf9179), U64_C (0x0e3f07071c07381b), U64_C (0x47acadad8ead0123), U64_C (0xb4b05a5a755aea2f), U64_C (0x1bef838336836cb5), U64_C (0x66b63333cc3385ff), U64_C (0xc65c636391633ff2), U64_C (0x041202020802100a), U64_C (0x4993aaaa92aa3938), U64_C (0xe2de7171d971afa8), U64_C (0x8dc6c8c807c80ecf), U64_C (0x32d119196419c87d), U64_C (0x923b494939497270), U64_C (0xaf5fd9d943d9869a), U64_C (0xf931f2f2eff2c31d), U64_C (0xdba8e3e3abe34b48), U64_C (0xb6b95b5b715be22a), U64_C (0x0dbc88881a883492), U64_C (0x293e9a9a529aa4c8), U64_C (0x4c0b262698262dbe), U64_C (0x64bf3232c8328dfa), U64_C (0x7d59b0b0fab0e94a), U64_C (0xcff2e9e983e91b6a), U64_C (0x1e770f0f3c0f7833), U64_C (0xb733d5d573d5e6a6), U64_C (0x1df480803a8074ba), U64_C (0x6127bebec2be997c), U64_C (0x87ebcdcd13cd26de), U64_C (0x68893434d034bde4), U64_C (0x903248483d487a75), U64_C (0xe354ffffdbffab24), U64_C (0xf48d7a7af57af78f), U64_C (0x3d6490907a90f4ea), U64_C (0xbe9d5f5f615fc23e), U64_C (0x403d202080201da0), U64_C (0xd00f6868bd6867d5), U64_C (0x34ca1a1a681ad072), U64_C (0x41b7aeae82ae192c), U64_C (0x757db4b4eab4c95e), U64_C (0xa8ce54544d549a19), U64_C (0x3b7f93937693ece5), U64_C (0x442f222288220daa), U64_C (0xc86364648d6407e9), U64_C (0xff2af1f1e3f1db12), U64_C (0xe6cc7373d173bfa2), U64_C (0x248212124812905a), U64_C (0x807a40401d403a5d), U64_C (0x1048080820084028), U64_C (0x9b95c3c32bc356e8), U64_C (0xc5dfecec97ec337b), U64_C (0xab4ddbdb4bdb9690), U64_C (0x5fc0a1a1bea1611f), U64_C (0x07918d8d0e8d1c83), U64_C (0x7ac83d3df43df5c9), U64_C (0x335b97976697ccf1), U64_C (0x0000000000000000), U64_C (0x83f9cfcf1bcf36d4), U64_C (0x566e2b2bac2b4587), U64_C (0xece17676c57697b3), U64_C (0x19e68282328264b0), U64_C (0xb128d6d67fd6fea9), U64_C (0x36c31b1b6c1bd877), U64_C (0x7774b5b5eeb5c15b), U64_C (0x43beafaf86af1129), U64_C (0xd41d6a6ab56a77df), U64_C (0xa0ea50505d50ba0d), U64_C (0x8a5745450945124c), U64_C (0xfb38f3f3ebf3cb18), U64_C (0x60ad3030c0309df0), U64_C (0xc3c4efef9bef2b74), U64_C (0x7eda3f3ffc3fe5c3), U64_C (0xaac755554955921c), U64_C (0x59dba2a2b2a27910), U64_C (0xc9e9eaea8fea0365), U64_C (0xca6a656589650fec), U64_C (0x6903babad2bab968), U64_C (0x5e4a2f2fbc2f6593), U64_C (0x9d8ec0c027c04ee7), U64_C (0xa160dede5fdebe81), U64_C (0x38fc1c1c701ce06c), U64_C (0xe746fdfdd3fdbb2e), U64_C (0x9a1f4d4d294d5264), U64_C (0x397692927292e4e0), U64_C (0xeafa7575c9758fbc), U64_C (0x0c3606061806301e), U64_C (0x09ae8a8a128a2498), U64_C (0x794bb2b2f2b2f940), U64_C (0xd185e6e6bfe66359), U64_C (0x1c7e0e0e380e7036), U64_C (0x3ee71f1f7c1ff863), U64_C (0xc4556262956237f7), U64_C (0xb53ad4d477d4eea3), U64_C (0x4d81a8a89aa82932), U64_C (0x315296966296c4f4), U64_C (0xef62f9f9c3f99b3a), U64_C (0x97a3c5c533c566f6), U64_C (0x4a102525942535b1), U64_C (0xb2ab59597959f220), U64_C (0x15d084842a8454ae), U64_C (0xe4c57272d572b7a7), U64_C (0x72ec3939e439d5dd), U64_C (0x98164c4c2d4c5a61), U64_C (0xbc945e5e655eca3b), U64_C (0xf09f7878fd78e785), U64_C (0x70e53838e038ddd8), U64_C (0x05988c8c0a8c1486), U64_C (0xbf17d1d163d1c6b2), U64_C (0x57e4a5a5aea5410b), U64_C (0xd9a1e2e2afe2434d), U64_C (0xc24e616199612ff8), U64_C (0x7b42b3b3f6b3f145), U64_C (0x42342121842115a5), U64_C (0x25089c9c4a9c94d6), U64_C (0x3cee1e1e781ef066), U64_C (0x8661434311432252), U64_C (0x93b1c7c73bc776fc), U64_C (0xe54ffcfcd7fcb32b), U64_C (0x0824040410042014), U64_C (0xa2e351515951b208), U64_C (0x2f2599995e99bcc7), U64_C (0xda226d6da96d4fc4), U64_C (0x1a650d0d340d6839), U64_C (0xe979fafacffa8335), U64_C (0xa369dfdf5bdfb684), U64_C (0xfca97e7ee57ed79b), U64_C (0x4819242490243db4), U64_C (0x76fe3b3bec3bc5d7), U64_C (0x4b9aabab96ab313d), U64_C (0x81f0cece1fce3ed1), U64_C (0x2299111144118855), U64_C (0x03838f8f068f0c89), U64_C (0x9c044e4e254e4a6b), U64_C (0x7366b7b7e6b7d151), U64_C (0xcbe0ebeb8beb0b60), U64_C (0x78c13c3cf03cfdcc), U64_C (0x1ffd81813e817cbf), U64_C (0x354094946a94d4fe), U64_C (0xf31cf7f7fbf7eb0c), U64_C (0x6f18b9b9deb9a167), U64_C (0x268b13134c13985f), U64_C (0x58512c2cb02c7d9c), U64_C (0xbb05d3d36bd3d6b8), U64_C (0xd38ce7e7bbe76b5c), U64_C (0xdc396e6ea56e57cb), U64_C (0x95aac4c437c46ef3), U64_C (0x061b03030c03180f), U64_C (0xacdc565645568a13), U64_C (0x885e44440d441a49), U64_C (0xfea07f7fe17fdf9e), U64_C (0x4f88a9a99ea92137), U64_C (0x54672a2aa82a4d82), U64_C (0x6b0abbbbd6bbb16d), U64_C (0x9f87c1c123c146e2), U64_C (0xa6f153535153a202), U64_C (0xa572dcdc57dcae8b), U64_C (0x16530b0b2c0b5827), U64_C (0x27019d9d4e9d9cd3), U64_C (0xd82b6c6cad6c47c1), U64_C (0x62a43131c43195f5), U64_C (0xe8f37474cd7487b9), U64_C (0xf115f6f6fff6e309), U64_C (0x8c4c464605460a43), U64_C (0x45a5acac8aac0926), U64_C (0x0fb589891e893c97), U64_C (0x28b414145014a044), U64_C (0xdfbae1e1a3e15b42), U64_C (0x2ca616165816b04e), U64_C (0x74f73a3ae83acdd2), U64_C (0xd2066969b9696fd0), U64_C (0x124109092409482d), U64_C (0xe0d77070dd70a7ad), U64_C (0x716fb6b6e2b6d954), U64_C (0xbd1ed0d067d0ceb7), U64_C (0xc7d6eded93ed3b7e), U64_C (0x85e2cccc17cc2edb), U64_C (0x8468424215422a57), U64_C (0x2d2c98985a98b4c2), U64_C (0x55eda4a4aaa4490e), U64_C (0x50752828a0285d88), U64_C (0xb8865c5c6d5cda31), U64_C (0xed6bf8f8c7f8933f), U64_C (0x11c28686228644a4), }; static const u64 C3[256] = { U64_C (0x7830d818186018c0), U64_C (0xaf462623238c2305), U64_C (0xf991b8c6c63fc67e), U64_C (0x6fcdfbe8e887e813), U64_C (0xa113cb878726874c), U64_C (0x626d11b8b8dab8a9), U64_C (0x0502090101040108), U64_C (0x6e9e0d4f4f214f42), U64_C (0xee6c9b3636d836ad), U64_C (0x0451ffa6a6a2a659), U64_C (0xbdb90cd2d26fd2de), U64_C (0x06f70ef5f5f3f5fb), U64_C (0x80f2967979f979ef), U64_C (0xcede306f6fa16f5f), U64_C (0xef3f6d91917e91fc), U64_C (0x07a4f852525552aa), U64_C (0xfdc04760609d6027), U64_C (0x766535bcbccabc89), U64_C (0xcd2b379b9b569bac), U64_C (0x8c018a8e8e028e04), U64_C (0x155bd2a3a3b6a371), U64_C (0x3c186c0c0c300c60), U64_C (0x8af6847b7bf17bff), U64_C (0xe16a803535d435b5), U64_C (0x693af51d1d741de8), U64_C (0x47ddb3e0e0a7e053), U64_C (0xacb321d7d77bd7f6), U64_C (0xed999cc2c22fc25e), U64_C (0x965c432e2eb82e6d), U64_C (0x7a96294b4b314b62), U64_C (0x21e15dfefedffea3), U64_C (0x16aed55757415782), U64_C (0x412abd15155415a8), U64_C (0xb6eee87777c1779f), U64_C (0xeb6e923737dc37a5), U64_C (0x56d79ee5e5b3e57b), U64_C (0xd923139f9f469f8c), U64_C (0x17fd23f0f0e7f0d3), U64_C (0x7f94204a4a354a6a), U64_C (0x95a944dada4fda9e), U64_C (0x25b0a258587d58fa), U64_C (0xca8fcfc9c903c906), U64_C (0x8d527c2929a42955), U64_C (0x22145a0a0a280a50), U64_C (0x4f7f50b1b1feb1e1), U64_C (0x1a5dc9a0a0baa069), U64_C (0xdad6146b6bb16b7f), U64_C (0xab17d985852e855c), U64_C (0x73673cbdbdcebd81), U64_C (0x34ba8f5d5d695dd2), U64_C (0x5020901010401080), U64_C (0x03f507f4f4f7f4f3), U64_C (0xc08bddcbcb0bcb16), U64_C (0xc67cd33e3ef83eed), U64_C (0x110a2d0505140528), U64_C (0xe6ce78676781671f), U64_C (0x53d597e4e4b7e473), U64_C (0xbb4e0227279c2725), U64_C (0x5882734141194132), U64_C (0x9d0ba78b8b168b2c), U64_C (0x0153f6a7a7a6a751), U64_C (0x94fab27d7de97dcf), U64_C (0xfb374995956e95dc), U64_C (0x9fad56d8d847d88e), U64_C (0x30eb70fbfbcbfb8b), U64_C (0x71c1cdeeee9fee23), U64_C (0x91f8bb7c7ced7cc7), U64_C (0xe3cc716666856617), U64_C (0x8ea77bdddd53dda6), U64_C (0x4b2eaf17175c17b8), U64_C (0x468e454747014702), U64_C (0xdc211a9e9e429e84), U64_C (0xc589d4caca0fca1e), U64_C (0x995a582d2db42d75), U64_C (0x79632ebfbfc6bf91), U64_C (0x1b0e3f07071c0738), U64_C (0x2347acadad8ead01), U64_C (0x2fb4b05a5a755aea), U64_C (0xb51bef838336836c), U64_C (0xff66b63333cc3385), U64_C (0xf2c65c636391633f), U64_C (0x0a04120202080210), U64_C (0x384993aaaa92aa39), U64_C (0xa8e2de7171d971af), U64_C (0xcf8dc6c8c807c80e), U64_C (0x7d32d119196419c8), U64_C (0x70923b4949394972), U64_C (0x9aaf5fd9d943d986), U64_C (0x1df931f2f2eff2c3), U64_C (0x48dba8e3e3abe34b), U64_C (0x2ab6b95b5b715be2), U64_C (0x920dbc88881a8834), U64_C (0xc8293e9a9a529aa4), U64_C (0xbe4c0b262698262d), U64_C (0xfa64bf3232c8328d), U64_C (0x4a7d59b0b0fab0e9), U64_C (0x6acff2e9e983e91b), U64_C (0x331e770f0f3c0f78), U64_C (0xa6b733d5d573d5e6), U64_C (0xba1df480803a8074), U64_C (0x7c6127bebec2be99), U64_C (0xde87ebcdcd13cd26), U64_C (0xe468893434d034bd), U64_C (0x75903248483d487a), U64_C (0x24e354ffffdbffab), U64_C (0x8ff48d7a7af57af7), U64_C (0xea3d6490907a90f4), U64_C (0x3ebe9d5f5f615fc2), U64_C (0xa0403d202080201d), U64_C (0xd5d00f6868bd6867), U64_C (0x7234ca1a1a681ad0), U64_C (0x2c41b7aeae82ae19), U64_C (0x5e757db4b4eab4c9), U64_C (0x19a8ce54544d549a), U64_C (0xe53b7f93937693ec), U64_C (0xaa442f222288220d), U64_C (0xe9c86364648d6407), U64_C (0x12ff2af1f1e3f1db), U64_C (0xa2e6cc7373d173bf), U64_C (0x5a24821212481290), U64_C (0x5d807a40401d403a), U64_C (0x2810480808200840), U64_C (0xe89b95c3c32bc356), U64_C (0x7bc5dfecec97ec33), U64_C (0x90ab4ddbdb4bdb96), U64_C (0x1f5fc0a1a1bea161), U64_C (0x8307918d8d0e8d1c), U64_C (0xc97ac83d3df43df5), U64_C (0xf1335b97976697cc), U64_C (0x0000000000000000), U64_C (0xd483f9cfcf1bcf36), U64_C (0x87566e2b2bac2b45), U64_C (0xb3ece17676c57697), U64_C (0xb019e68282328264), U64_C (0xa9b128d6d67fd6fe), U64_C (0x7736c31b1b6c1bd8), U64_C (0x5b7774b5b5eeb5c1), U64_C (0x2943beafaf86af11), U64_C (0xdfd41d6a6ab56a77), U64_C (0x0da0ea50505d50ba), U64_C (0x4c8a574545094512), U64_C (0x18fb38f3f3ebf3cb), U64_C (0xf060ad3030c0309d), U64_C (0x74c3c4efef9bef2b), U64_C (0xc37eda3f3ffc3fe5), U64_C (0x1caac75555495592), U64_C (0x1059dba2a2b2a279), U64_C (0x65c9e9eaea8fea03), U64_C (0xecca6a656589650f), U64_C (0x686903babad2bab9), U64_C (0x935e4a2f2fbc2f65), U64_C (0xe79d8ec0c027c04e), U64_C (0x81a160dede5fdebe), U64_C (0x6c38fc1c1c701ce0), U64_C (0x2ee746fdfdd3fdbb), U64_C (0x649a1f4d4d294d52), U64_C (0xe0397692927292e4), U64_C (0xbceafa7575c9758f), U64_C (0x1e0c360606180630), U64_C (0x9809ae8a8a128a24), U64_C (0x40794bb2b2f2b2f9), U64_C (0x59d185e6e6bfe663), U64_C (0x361c7e0e0e380e70), U64_C (0x633ee71f1f7c1ff8), U64_C (0xf7c4556262956237), U64_C (0xa3b53ad4d477d4ee), U64_C (0x324d81a8a89aa829), U64_C (0xf4315296966296c4), U64_C (0x3aef62f9f9c3f99b), U64_C (0xf697a3c5c533c566), U64_C (0xb14a102525942535), U64_C (0x20b2ab59597959f2), U64_C (0xae15d084842a8454), U64_C (0xa7e4c57272d572b7), U64_C (0xdd72ec3939e439d5), U64_C (0x6198164c4c2d4c5a), U64_C (0x3bbc945e5e655eca), U64_C (0x85f09f7878fd78e7), U64_C (0xd870e53838e038dd), U64_C (0x8605988c8c0a8c14), U64_C (0xb2bf17d1d163d1c6), U64_C (0x0b57e4a5a5aea541), U64_C (0x4dd9a1e2e2afe243), U64_C (0xf8c24e616199612f), U64_C (0x457b42b3b3f6b3f1), U64_C (0xa542342121842115), U64_C (0xd625089c9c4a9c94), U64_C (0x663cee1e1e781ef0), U64_C (0x5286614343114322), U64_C (0xfc93b1c7c73bc776), U64_C (0x2be54ffcfcd7fcb3), U64_C (0x1408240404100420), U64_C (0x08a2e351515951b2), U64_C (0xc72f2599995e99bc), U64_C (0xc4da226d6da96d4f), U64_C (0x391a650d0d340d68), U64_C (0x35e979fafacffa83), U64_C (0x84a369dfdf5bdfb6), U64_C (0x9bfca97e7ee57ed7), U64_C (0xb44819242490243d), U64_C (0xd776fe3b3bec3bc5), U64_C (0x3d4b9aabab96ab31), U64_C (0xd181f0cece1fce3e), U64_C (0x5522991111441188), U64_C (0x8903838f8f068f0c), U64_C (0x6b9c044e4e254e4a), U64_C (0x517366b7b7e6b7d1), U64_C (0x60cbe0ebeb8beb0b), U64_C (0xcc78c13c3cf03cfd), U64_C (0xbf1ffd81813e817c), U64_C (0xfe354094946a94d4), U64_C (0x0cf31cf7f7fbf7eb), U64_C (0x676f18b9b9deb9a1), U64_C (0x5f268b13134c1398), U64_C (0x9c58512c2cb02c7d), U64_C (0xb8bb05d3d36bd3d6), U64_C (0x5cd38ce7e7bbe76b), U64_C (0xcbdc396e6ea56e57), U64_C (0xf395aac4c437c46e), U64_C (0x0f061b03030c0318), U64_C (0x13acdc565645568a), U64_C (0x49885e44440d441a), U64_C (0x9efea07f7fe17fdf), U64_C (0x374f88a9a99ea921), U64_C (0x8254672a2aa82a4d), U64_C (0x6d6b0abbbbd6bbb1), U64_C (0xe29f87c1c123c146), U64_C (0x02a6f153535153a2), U64_C (0x8ba572dcdc57dcae), U64_C (0x2716530b0b2c0b58), U64_C (0xd327019d9d4e9d9c), U64_C (0xc1d82b6c6cad6c47), U64_C (0xf562a43131c43195), U64_C (0xb9e8f37474cd7487), U64_C (0x09f115f6f6fff6e3), U64_C (0x438c4c464605460a), U64_C (0x2645a5acac8aac09), U64_C (0x970fb589891e893c), U64_C (0x4428b414145014a0), U64_C (0x42dfbae1e1a3e15b), U64_C (0x4e2ca616165816b0), U64_C (0xd274f73a3ae83acd), U64_C (0xd0d2066969b9696f), U64_C (0x2d12410909240948), U64_C (0xade0d77070dd70a7), U64_C (0x54716fb6b6e2b6d9), U64_C (0xb7bd1ed0d067d0ce), U64_C (0x7ec7d6eded93ed3b), U64_C (0xdb85e2cccc17cc2e), U64_C (0x578468424215422a), U64_C (0xc22d2c98985a98b4), U64_C (0x0e55eda4a4aaa449), U64_C (0x8850752828a0285d), U64_C (0x31b8865c5c6d5cda), U64_C (0x3fed6bf8f8c7f893), U64_C (0xa411c28686228644), }; static const u64 C4[256] = { U64_C (0xc07830d818186018), U64_C (0x05af462623238c23), U64_C (0x7ef991b8c6c63fc6), U64_C (0x136fcdfbe8e887e8), U64_C (0x4ca113cb87872687), U64_C (0xa9626d11b8b8dab8), U64_C (0x0805020901010401), U64_C (0x426e9e0d4f4f214f), U64_C (0xadee6c9b3636d836), U64_C (0x590451ffa6a6a2a6), U64_C (0xdebdb90cd2d26fd2), U64_C (0xfb06f70ef5f5f3f5), U64_C (0xef80f2967979f979), U64_C (0x5fcede306f6fa16f), U64_C (0xfcef3f6d91917e91), U64_C (0xaa07a4f852525552), U64_C (0x27fdc04760609d60), U64_C (0x89766535bcbccabc), U64_C (0xaccd2b379b9b569b), U64_C (0x048c018a8e8e028e), U64_C (0x71155bd2a3a3b6a3), U64_C (0x603c186c0c0c300c), U64_C (0xff8af6847b7bf17b), U64_C (0xb5e16a803535d435), U64_C (0xe8693af51d1d741d), U64_C (0x5347ddb3e0e0a7e0), U64_C (0xf6acb321d7d77bd7), U64_C (0x5eed999cc2c22fc2), U64_C (0x6d965c432e2eb82e), U64_C (0x627a96294b4b314b), U64_C (0xa321e15dfefedffe), U64_C (0x8216aed557574157), U64_C (0xa8412abd15155415), U64_C (0x9fb6eee87777c177), U64_C (0xa5eb6e923737dc37), U64_C (0x7b56d79ee5e5b3e5), U64_C (0x8cd923139f9f469f), U64_C (0xd317fd23f0f0e7f0), U64_C (0x6a7f94204a4a354a), U64_C (0x9e95a944dada4fda), U64_C (0xfa25b0a258587d58), U64_C (0x06ca8fcfc9c903c9), U64_C (0x558d527c2929a429), U64_C (0x5022145a0a0a280a), U64_C (0xe14f7f50b1b1feb1), U64_C (0x691a5dc9a0a0baa0), U64_C (0x7fdad6146b6bb16b), U64_C (0x5cab17d985852e85), U64_C (0x8173673cbdbdcebd), U64_C (0xd234ba8f5d5d695d), U64_C (0x8050209010104010), U64_C (0xf303f507f4f4f7f4), U64_C (0x16c08bddcbcb0bcb), U64_C (0xedc67cd33e3ef83e), U64_C (0x28110a2d05051405), U64_C (0x1fe6ce7867678167), U64_C (0x7353d597e4e4b7e4), U64_C (0x25bb4e0227279c27), U64_C (0x3258827341411941), U64_C (0x2c9d0ba78b8b168b), U64_C (0x510153f6a7a7a6a7), U64_C (0xcf94fab27d7de97d), U64_C (0xdcfb374995956e95), U64_C (0x8e9fad56d8d847d8), U64_C (0x8b30eb70fbfbcbfb), U64_C (0x2371c1cdeeee9fee), U64_C (0xc791f8bb7c7ced7c), U64_C (0x17e3cc7166668566), U64_C (0xa68ea77bdddd53dd), U64_C (0xb84b2eaf17175c17), U64_C (0x02468e4547470147), U64_C (0x84dc211a9e9e429e), U64_C (0x1ec589d4caca0fca), U64_C (0x75995a582d2db42d), U64_C (0x9179632ebfbfc6bf), U64_C (0x381b0e3f07071c07), U64_C (0x012347acadad8ead), U64_C (0xea2fb4b05a5a755a), U64_C (0x6cb51bef83833683), U64_C (0x85ff66b63333cc33), U64_C (0x3ff2c65c63639163), U64_C (0x100a041202020802), U64_C (0x39384993aaaa92aa), U64_C (0xafa8e2de7171d971), U64_C (0x0ecf8dc6c8c807c8), U64_C (0xc87d32d119196419), U64_C (0x7270923b49493949), U64_C (0x869aaf5fd9d943d9), U64_C (0xc31df931f2f2eff2), U64_C (0x4b48dba8e3e3abe3), U64_C (0xe22ab6b95b5b715b), U64_C (0x34920dbc88881a88), U64_C (0xa4c8293e9a9a529a), U64_C (0x2dbe4c0b26269826), U64_C (0x8dfa64bf3232c832), U64_C (0xe94a7d59b0b0fab0), U64_C (0x1b6acff2e9e983e9), U64_C (0x78331e770f0f3c0f), U64_C (0xe6a6b733d5d573d5), U64_C (0x74ba1df480803a80), U64_C (0x997c6127bebec2be), U64_C (0x26de87ebcdcd13cd), U64_C (0xbde468893434d034), U64_C (0x7a75903248483d48), U64_C (0xab24e354ffffdbff), U64_C (0xf78ff48d7a7af57a), U64_C (0xf4ea3d6490907a90), U64_C (0xc23ebe9d5f5f615f), U64_C (0x1da0403d20208020), U64_C (0x67d5d00f6868bd68), U64_C (0xd07234ca1a1a681a), U64_C (0x192c41b7aeae82ae), U64_C (0xc95e757db4b4eab4), U64_C (0x9a19a8ce54544d54), U64_C (0xece53b7f93937693), U64_C (0x0daa442f22228822), U64_C (0x07e9c86364648d64), U64_C (0xdb12ff2af1f1e3f1), U64_C (0xbfa2e6cc7373d173), U64_C (0x905a248212124812), U64_C (0x3a5d807a40401d40), U64_C (0x4028104808082008), U64_C (0x56e89b95c3c32bc3), U64_C (0x337bc5dfecec97ec), U64_C (0x9690ab4ddbdb4bdb), U64_C (0x611f5fc0a1a1bea1), U64_C (0x1c8307918d8d0e8d), U64_C (0xf5c97ac83d3df43d), U64_C (0xccf1335b97976697), U64_C (0x0000000000000000), U64_C (0x36d483f9cfcf1bcf), U64_C (0x4587566e2b2bac2b), U64_C (0x97b3ece17676c576), U64_C (0x64b019e682823282), U64_C (0xfea9b128d6d67fd6), U64_C (0xd87736c31b1b6c1b), U64_C (0xc15b7774b5b5eeb5), U64_C (0x112943beafaf86af), U64_C (0x77dfd41d6a6ab56a), U64_C (0xba0da0ea50505d50), U64_C (0x124c8a5745450945), U64_C (0xcb18fb38f3f3ebf3), U64_C (0x9df060ad3030c030), U64_C (0x2b74c3c4efef9bef), U64_C (0xe5c37eda3f3ffc3f), U64_C (0x921caac755554955), U64_C (0x791059dba2a2b2a2), U64_C (0x0365c9e9eaea8fea), U64_C (0x0fecca6a65658965), U64_C (0xb9686903babad2ba), U64_C (0x65935e4a2f2fbc2f), U64_C (0x4ee79d8ec0c027c0), U64_C (0xbe81a160dede5fde), U64_C (0xe06c38fc1c1c701c), U64_C (0xbb2ee746fdfdd3fd), U64_C (0x52649a1f4d4d294d), U64_C (0xe4e0397692927292), U64_C (0x8fbceafa7575c975), U64_C (0x301e0c3606061806), U64_C (0x249809ae8a8a128a), U64_C (0xf940794bb2b2f2b2), U64_C (0x6359d185e6e6bfe6), U64_C (0x70361c7e0e0e380e), U64_C (0xf8633ee71f1f7c1f), U64_C (0x37f7c45562629562), U64_C (0xeea3b53ad4d477d4), U64_C (0x29324d81a8a89aa8), U64_C (0xc4f4315296966296), U64_C (0x9b3aef62f9f9c3f9), U64_C (0x66f697a3c5c533c5), U64_C (0x35b14a1025259425), U64_C (0xf220b2ab59597959), U64_C (0x54ae15d084842a84), U64_C (0xb7a7e4c57272d572), U64_C (0xd5dd72ec3939e439), U64_C (0x5a6198164c4c2d4c), U64_C (0xca3bbc945e5e655e), U64_C (0xe785f09f7878fd78), U64_C (0xddd870e53838e038), U64_C (0x148605988c8c0a8c), U64_C (0xc6b2bf17d1d163d1), U64_C (0x410b57e4a5a5aea5), U64_C (0x434dd9a1e2e2afe2), U64_C (0x2ff8c24e61619961), U64_C (0xf1457b42b3b3f6b3), U64_C (0x15a5423421218421), U64_C (0x94d625089c9c4a9c), U64_C (0xf0663cee1e1e781e), U64_C (0x2252866143431143), U64_C (0x76fc93b1c7c73bc7), U64_C (0xb32be54ffcfcd7fc), U64_C (0x2014082404041004), U64_C (0xb208a2e351515951), U64_C (0xbcc72f2599995e99), U64_C (0x4fc4da226d6da96d), U64_C (0x68391a650d0d340d), U64_C (0x8335e979fafacffa), U64_C (0xb684a369dfdf5bdf), U64_C (0xd79bfca97e7ee57e), U64_C (0x3db4481924249024), U64_C (0xc5d776fe3b3bec3b), U64_C (0x313d4b9aabab96ab), U64_C (0x3ed181f0cece1fce), U64_C (0x8855229911114411), U64_C (0x0c8903838f8f068f), U64_C (0x4a6b9c044e4e254e), U64_C (0xd1517366b7b7e6b7), U64_C (0x0b60cbe0ebeb8beb), U64_C (0xfdcc78c13c3cf03c), U64_C (0x7cbf1ffd81813e81), U64_C (0xd4fe354094946a94), U64_C (0xeb0cf31cf7f7fbf7), U64_C (0xa1676f18b9b9deb9), U64_C (0x985f268b13134c13), U64_C (0x7d9c58512c2cb02c), U64_C (0xd6b8bb05d3d36bd3), U64_C (0x6b5cd38ce7e7bbe7), U64_C (0x57cbdc396e6ea56e), U64_C (0x6ef395aac4c437c4), U64_C (0x180f061b03030c03), U64_C (0x8a13acdc56564556), U64_C (0x1a49885e44440d44), U64_C (0xdf9efea07f7fe17f), U64_C (0x21374f88a9a99ea9), U64_C (0x4d8254672a2aa82a), U64_C (0xb16d6b0abbbbd6bb), U64_C (0x46e29f87c1c123c1), U64_C (0xa202a6f153535153), U64_C (0xae8ba572dcdc57dc), U64_C (0x582716530b0b2c0b), U64_C (0x9cd327019d9d4e9d), U64_C (0x47c1d82b6c6cad6c), U64_C (0x95f562a43131c431), U64_C (0x87b9e8f37474cd74), U64_C (0xe309f115f6f6fff6), U64_C (0x0a438c4c46460546), U64_C (0x092645a5acac8aac), U64_C (0x3c970fb589891e89), U64_C (0xa04428b414145014), U64_C (0x5b42dfbae1e1a3e1), U64_C (0xb04e2ca616165816), U64_C (0xcdd274f73a3ae83a), U64_C (0x6fd0d2066969b969), U64_C (0x482d124109092409), U64_C (0xa7ade0d77070dd70), U64_C (0xd954716fb6b6e2b6), U64_C (0xceb7bd1ed0d067d0), U64_C (0x3b7ec7d6eded93ed), U64_C (0x2edb85e2cccc17cc), U64_C (0x2a57846842421542), U64_C (0xb4c22d2c98985a98), U64_C (0x490e55eda4a4aaa4), U64_C (0x5d8850752828a028), U64_C (0xda31b8865c5c6d5c), U64_C (0x933fed6bf8f8c7f8), U64_C (0x44a411c286862286), }; static const u64 C5[256] = { U64_C (0x18c07830d8181860), U64_C (0x2305af462623238c), U64_C (0xc67ef991b8c6c63f), U64_C (0xe8136fcdfbe8e887), U64_C (0x874ca113cb878726), U64_C (0xb8a9626d11b8b8da), U64_C (0x0108050209010104), U64_C (0x4f426e9e0d4f4f21), U64_C (0x36adee6c9b3636d8), U64_C (0xa6590451ffa6a6a2), U64_C (0xd2debdb90cd2d26f), U64_C (0xf5fb06f70ef5f5f3), U64_C (0x79ef80f2967979f9), U64_C (0x6f5fcede306f6fa1), U64_C (0x91fcef3f6d91917e), U64_C (0x52aa07a4f8525255), U64_C (0x6027fdc04760609d), U64_C (0xbc89766535bcbcca), U64_C (0x9baccd2b379b9b56), U64_C (0x8e048c018a8e8e02), U64_C (0xa371155bd2a3a3b6), U64_C (0x0c603c186c0c0c30), U64_C (0x7bff8af6847b7bf1), U64_C (0x35b5e16a803535d4), U64_C (0x1de8693af51d1d74), U64_C (0xe05347ddb3e0e0a7), U64_C (0xd7f6acb321d7d77b), U64_C (0xc25eed999cc2c22f), U64_C (0x2e6d965c432e2eb8), U64_C (0x4b627a96294b4b31), U64_C (0xfea321e15dfefedf), U64_C (0x578216aed5575741), U64_C (0x15a8412abd151554), U64_C (0x779fb6eee87777c1), U64_C (0x37a5eb6e923737dc), U64_C (0xe57b56d79ee5e5b3), U64_C (0x9f8cd923139f9f46), U64_C (0xf0d317fd23f0f0e7), U64_C (0x4a6a7f94204a4a35), U64_C (0xda9e95a944dada4f), U64_C (0x58fa25b0a258587d), U64_C (0xc906ca8fcfc9c903), U64_C (0x29558d527c2929a4), U64_C (0x0a5022145a0a0a28), U64_C (0xb1e14f7f50b1b1fe), U64_C (0xa0691a5dc9a0a0ba), U64_C (0x6b7fdad6146b6bb1), U64_C (0x855cab17d985852e), U64_C (0xbd8173673cbdbdce), U64_C (0x5dd234ba8f5d5d69), U64_C (0x1080502090101040), U64_C (0xf4f303f507f4f4f7), U64_C (0xcb16c08bddcbcb0b), U64_C (0x3eedc67cd33e3ef8), U64_C (0x0528110a2d050514), U64_C (0x671fe6ce78676781), U64_C (0xe47353d597e4e4b7), U64_C (0x2725bb4e0227279c), U64_C (0x4132588273414119), U64_C (0x8b2c9d0ba78b8b16), U64_C (0xa7510153f6a7a7a6), U64_C (0x7dcf94fab27d7de9), U64_C (0x95dcfb374995956e), U64_C (0xd88e9fad56d8d847), U64_C (0xfb8b30eb70fbfbcb), U64_C (0xee2371c1cdeeee9f), U64_C (0x7cc791f8bb7c7ced), U64_C (0x6617e3cc71666685), U64_C (0xdda68ea77bdddd53), U64_C (0x17b84b2eaf17175c), U64_C (0x4702468e45474701), U64_C (0x9e84dc211a9e9e42), U64_C (0xca1ec589d4caca0f), U64_C (0x2d75995a582d2db4), U64_C (0xbf9179632ebfbfc6), U64_C (0x07381b0e3f07071c), U64_C (0xad012347acadad8e), U64_C (0x5aea2fb4b05a5a75), U64_C (0x836cb51bef838336), U64_C (0x3385ff66b63333cc), U64_C (0x633ff2c65c636391), U64_C (0x02100a0412020208), U64_C (0xaa39384993aaaa92), U64_C (0x71afa8e2de7171d9), U64_C (0xc80ecf8dc6c8c807), U64_C (0x19c87d32d1191964), U64_C (0x497270923b494939), U64_C (0xd9869aaf5fd9d943), U64_C (0xf2c31df931f2f2ef), U64_C (0xe34b48dba8e3e3ab), U64_C (0x5be22ab6b95b5b71), U64_C (0x8834920dbc88881a), U64_C (0x9aa4c8293e9a9a52), U64_C (0x262dbe4c0b262698), U64_C (0x328dfa64bf3232c8), U64_C (0xb0e94a7d59b0b0fa), U64_C (0xe91b6acff2e9e983), U64_C (0x0f78331e770f0f3c), U64_C (0xd5e6a6b733d5d573), U64_C (0x8074ba1df480803a), U64_C (0xbe997c6127bebec2), U64_C (0xcd26de87ebcdcd13), U64_C (0x34bde468893434d0), U64_C (0x487a75903248483d), U64_C (0xffab24e354ffffdb), U64_C (0x7af78ff48d7a7af5), U64_C (0x90f4ea3d6490907a), U64_C (0x5fc23ebe9d5f5f61), U64_C (0x201da0403d202080), U64_C (0x6867d5d00f6868bd), U64_C (0x1ad07234ca1a1a68), U64_C (0xae192c41b7aeae82), U64_C (0xb4c95e757db4b4ea), U64_C (0x549a19a8ce54544d), U64_C (0x93ece53b7f939376), U64_C (0x220daa442f222288), U64_C (0x6407e9c86364648d), U64_C (0xf1db12ff2af1f1e3), U64_C (0x73bfa2e6cc7373d1), U64_C (0x12905a2482121248), U64_C (0x403a5d807a40401d), U64_C (0x0840281048080820), U64_C (0xc356e89b95c3c32b), U64_C (0xec337bc5dfecec97), U64_C (0xdb9690ab4ddbdb4b), U64_C (0xa1611f5fc0a1a1be), U64_C (0x8d1c8307918d8d0e), U64_C (0x3df5c97ac83d3df4), U64_C (0x97ccf1335b979766), U64_C (0x0000000000000000), U64_C (0xcf36d483f9cfcf1b), U64_C (0x2b4587566e2b2bac), U64_C (0x7697b3ece17676c5), U64_C (0x8264b019e6828232), U64_C (0xd6fea9b128d6d67f), U64_C (0x1bd87736c31b1b6c), U64_C (0xb5c15b7774b5b5ee), U64_C (0xaf112943beafaf86), U64_C (0x6a77dfd41d6a6ab5), U64_C (0x50ba0da0ea50505d), U64_C (0x45124c8a57454509), U64_C (0xf3cb18fb38f3f3eb), U64_C (0x309df060ad3030c0), U64_C (0xef2b74c3c4efef9b), U64_C (0x3fe5c37eda3f3ffc), U64_C (0x55921caac7555549), U64_C (0xa2791059dba2a2b2), U64_C (0xea0365c9e9eaea8f), U64_C (0x650fecca6a656589), U64_C (0xbab9686903babad2), U64_C (0x2f65935e4a2f2fbc), U64_C (0xc04ee79d8ec0c027), U64_C (0xdebe81a160dede5f), U64_C (0x1ce06c38fc1c1c70), U64_C (0xfdbb2ee746fdfdd3), U64_C (0x4d52649a1f4d4d29), U64_C (0x92e4e03976929272), U64_C (0x758fbceafa7575c9), U64_C (0x06301e0c36060618), U64_C (0x8a249809ae8a8a12), U64_C (0xb2f940794bb2b2f2), U64_C (0xe66359d185e6e6bf), U64_C (0x0e70361c7e0e0e38), U64_C (0x1ff8633ee71f1f7c), U64_C (0x6237f7c455626295), U64_C (0xd4eea3b53ad4d477), U64_C (0xa829324d81a8a89a), U64_C (0x96c4f43152969662), U64_C (0xf99b3aef62f9f9c3), U64_C (0xc566f697a3c5c533), U64_C (0x2535b14a10252594), U64_C (0x59f220b2ab595979), U64_C (0x8454ae15d084842a), U64_C (0x72b7a7e4c57272d5), U64_C (0x39d5dd72ec3939e4), U64_C (0x4c5a6198164c4c2d), U64_C (0x5eca3bbc945e5e65), U64_C (0x78e785f09f7878fd), U64_C (0x38ddd870e53838e0), U64_C (0x8c148605988c8c0a), U64_C (0xd1c6b2bf17d1d163), U64_C (0xa5410b57e4a5a5ae), U64_C (0xe2434dd9a1e2e2af), U64_C (0x612ff8c24e616199), U64_C (0xb3f1457b42b3b3f6), U64_C (0x2115a54234212184), U64_C (0x9c94d625089c9c4a), U64_C (0x1ef0663cee1e1e78), U64_C (0x4322528661434311), U64_C (0xc776fc93b1c7c73b), U64_C (0xfcb32be54ffcfcd7), U64_C (0x0420140824040410), U64_C (0x51b208a2e3515159), U64_C (0x99bcc72f2599995e), U64_C (0x6d4fc4da226d6da9), U64_C (0x0d68391a650d0d34), U64_C (0xfa8335e979fafacf), U64_C (0xdfb684a369dfdf5b), U64_C (0x7ed79bfca97e7ee5), U64_C (0x243db44819242490), U64_C (0x3bc5d776fe3b3bec), U64_C (0xab313d4b9aabab96), U64_C (0xce3ed181f0cece1f), U64_C (0x1188552299111144), U64_C (0x8f0c8903838f8f06), U64_C (0x4e4a6b9c044e4e25), U64_C (0xb7d1517366b7b7e6), U64_C (0xeb0b60cbe0ebeb8b), U64_C (0x3cfdcc78c13c3cf0), U64_C (0x817cbf1ffd81813e), U64_C (0x94d4fe354094946a), U64_C (0xf7eb0cf31cf7f7fb), U64_C (0xb9a1676f18b9b9de), U64_C (0x13985f268b13134c), U64_C (0x2c7d9c58512c2cb0), U64_C (0xd3d6b8bb05d3d36b), U64_C (0xe76b5cd38ce7e7bb), U64_C (0x6e57cbdc396e6ea5), U64_C (0xc46ef395aac4c437), U64_C (0x03180f061b03030c), U64_C (0x568a13acdc565645), U64_C (0x441a49885e44440d), U64_C (0x7fdf9efea07f7fe1), U64_C (0xa921374f88a9a99e), U64_C (0x2a4d8254672a2aa8), U64_C (0xbbb16d6b0abbbbd6), U64_C (0xc146e29f87c1c123), U64_C (0x53a202a6f1535351), U64_C (0xdcae8ba572dcdc57), U64_C (0x0b582716530b0b2c), U64_C (0x9d9cd327019d9d4e), U64_C (0x6c47c1d82b6c6cad), U64_C (0x3195f562a43131c4), U64_C (0x7487b9e8f37474cd), U64_C (0xf6e309f115f6f6ff), U64_C (0x460a438c4c464605), U64_C (0xac092645a5acac8a), U64_C (0x893c970fb589891e), U64_C (0x14a04428b4141450), U64_C (0xe15b42dfbae1e1a3), U64_C (0x16b04e2ca6161658), U64_C (0x3acdd274f73a3ae8), U64_C (0x696fd0d2066969b9), U64_C (0x09482d1241090924), U64_C (0x70a7ade0d77070dd), U64_C (0xb6d954716fb6b6e2), U64_C (0xd0ceb7bd1ed0d067), U64_C (0xed3b7ec7d6eded93), U64_C (0xcc2edb85e2cccc17), U64_C (0x422a578468424215), U64_C (0x98b4c22d2c98985a), U64_C (0xa4490e55eda4a4aa), U64_C (0x285d8850752828a0), U64_C (0x5cda31b8865c5c6d), U64_C (0xf8933fed6bf8f8c7), U64_C (0x8644a411c2868622), }; static const u64 C6[256] = { U64_C (0x6018c07830d81818), U64_C (0x8c2305af46262323), U64_C (0x3fc67ef991b8c6c6), U64_C (0x87e8136fcdfbe8e8), U64_C (0x26874ca113cb8787), U64_C (0xdab8a9626d11b8b8), U64_C (0x0401080502090101), U64_C (0x214f426e9e0d4f4f), U64_C (0xd836adee6c9b3636), U64_C (0xa2a6590451ffa6a6), U64_C (0x6fd2debdb90cd2d2), U64_C (0xf3f5fb06f70ef5f5), U64_C (0xf979ef80f2967979), U64_C (0xa16f5fcede306f6f), U64_C (0x7e91fcef3f6d9191), U64_C (0x5552aa07a4f85252), U64_C (0x9d6027fdc0476060), U64_C (0xcabc89766535bcbc), U64_C (0x569baccd2b379b9b), U64_C (0x028e048c018a8e8e), U64_C (0xb6a371155bd2a3a3), U64_C (0x300c603c186c0c0c), U64_C (0xf17bff8af6847b7b), U64_C (0xd435b5e16a803535), U64_C (0x741de8693af51d1d), U64_C (0xa7e05347ddb3e0e0), U64_C (0x7bd7f6acb321d7d7), U64_C (0x2fc25eed999cc2c2), U64_C (0xb82e6d965c432e2e), U64_C (0x314b627a96294b4b), U64_C (0xdffea321e15dfefe), U64_C (0x41578216aed55757), U64_C (0x5415a8412abd1515), U64_C (0xc1779fb6eee87777), U64_C (0xdc37a5eb6e923737), U64_C (0xb3e57b56d79ee5e5), U64_C (0x469f8cd923139f9f), U64_C (0xe7f0d317fd23f0f0), U64_C (0x354a6a7f94204a4a), U64_C (0x4fda9e95a944dada), U64_C (0x7d58fa25b0a25858), U64_C (0x03c906ca8fcfc9c9), U64_C (0xa429558d527c2929), U64_C (0x280a5022145a0a0a), U64_C (0xfeb1e14f7f50b1b1), U64_C (0xbaa0691a5dc9a0a0), U64_C (0xb16b7fdad6146b6b), U64_C (0x2e855cab17d98585), U64_C (0xcebd8173673cbdbd), U64_C (0x695dd234ba8f5d5d), U64_C (0x4010805020901010), U64_C (0xf7f4f303f507f4f4), U64_C (0x0bcb16c08bddcbcb), U64_C (0xf83eedc67cd33e3e), U64_C (0x140528110a2d0505), U64_C (0x81671fe6ce786767), U64_C (0xb7e47353d597e4e4), U64_C (0x9c2725bb4e022727), U64_C (0x1941325882734141), U64_C (0x168b2c9d0ba78b8b), U64_C (0xa6a7510153f6a7a7), U64_C (0xe97dcf94fab27d7d), U64_C (0x6e95dcfb37499595), U64_C (0x47d88e9fad56d8d8), U64_C (0xcbfb8b30eb70fbfb), U64_C (0x9fee2371c1cdeeee), U64_C (0xed7cc791f8bb7c7c), U64_C (0x856617e3cc716666), U64_C (0x53dda68ea77bdddd), U64_C (0x5c17b84b2eaf1717), U64_C (0x014702468e454747), U64_C (0x429e84dc211a9e9e), U64_C (0x0fca1ec589d4caca), U64_C (0xb42d75995a582d2d), U64_C (0xc6bf9179632ebfbf), U64_C (0x1c07381b0e3f0707), U64_C (0x8ead012347acadad), U64_C (0x755aea2fb4b05a5a), U64_C (0x36836cb51bef8383), U64_C (0xcc3385ff66b63333), U64_C (0x91633ff2c65c6363), U64_C (0x0802100a04120202), U64_C (0x92aa39384993aaaa), U64_C (0xd971afa8e2de7171), U64_C (0x07c80ecf8dc6c8c8), U64_C (0x6419c87d32d11919), U64_C (0x39497270923b4949), U64_C (0x43d9869aaf5fd9d9), U64_C (0xeff2c31df931f2f2), U64_C (0xabe34b48dba8e3e3), U64_C (0x715be22ab6b95b5b), U64_C (0x1a8834920dbc8888), U64_C (0x529aa4c8293e9a9a), U64_C (0x98262dbe4c0b2626), U64_C (0xc8328dfa64bf3232), U64_C (0xfab0e94a7d59b0b0), U64_C (0x83e91b6acff2e9e9), U64_C (0x3c0f78331e770f0f), U64_C (0x73d5e6a6b733d5d5), U64_C (0x3a8074ba1df48080), U64_C (0xc2be997c6127bebe), U64_C (0x13cd26de87ebcdcd), U64_C (0xd034bde468893434), U64_C (0x3d487a7590324848), U64_C (0xdbffab24e354ffff), U64_C (0xf57af78ff48d7a7a), U64_C (0x7a90f4ea3d649090), U64_C (0x615fc23ebe9d5f5f), U64_C (0x80201da0403d2020), U64_C (0xbd6867d5d00f6868), U64_C (0x681ad07234ca1a1a), U64_C (0x82ae192c41b7aeae), U64_C (0xeab4c95e757db4b4), U64_C (0x4d549a19a8ce5454), U64_C (0x7693ece53b7f9393), U64_C (0x88220daa442f2222), U64_C (0x8d6407e9c8636464), U64_C (0xe3f1db12ff2af1f1), U64_C (0xd173bfa2e6cc7373), U64_C (0x4812905a24821212), U64_C (0x1d403a5d807a4040), U64_C (0x2008402810480808), U64_C (0x2bc356e89b95c3c3), U64_C (0x97ec337bc5dfecec), U64_C (0x4bdb9690ab4ddbdb), U64_C (0xbea1611f5fc0a1a1), U64_C (0x0e8d1c8307918d8d), U64_C (0xf43df5c97ac83d3d), U64_C (0x6697ccf1335b9797), U64_C (0x0000000000000000), U64_C (0x1bcf36d483f9cfcf), U64_C (0xac2b4587566e2b2b), U64_C (0xc57697b3ece17676), U64_C (0x328264b019e68282), U64_C (0x7fd6fea9b128d6d6), U64_C (0x6c1bd87736c31b1b), U64_C (0xeeb5c15b7774b5b5), U64_C (0x86af112943beafaf), U64_C (0xb56a77dfd41d6a6a), U64_C (0x5d50ba0da0ea5050), U64_C (0x0945124c8a574545), U64_C (0xebf3cb18fb38f3f3), U64_C (0xc0309df060ad3030), U64_C (0x9bef2b74c3c4efef), U64_C (0xfc3fe5c37eda3f3f), U64_C (0x4955921caac75555), U64_C (0xb2a2791059dba2a2), U64_C (0x8fea0365c9e9eaea), U64_C (0x89650fecca6a6565), U64_C (0xd2bab9686903baba), U64_C (0xbc2f65935e4a2f2f), U64_C (0x27c04ee79d8ec0c0), U64_C (0x5fdebe81a160dede), U64_C (0x701ce06c38fc1c1c), U64_C (0xd3fdbb2ee746fdfd), U64_C (0x294d52649a1f4d4d), U64_C (0x7292e4e039769292), U64_C (0xc9758fbceafa7575), U64_C (0x1806301e0c360606), U64_C (0x128a249809ae8a8a), U64_C (0xf2b2f940794bb2b2), U64_C (0xbfe66359d185e6e6), U64_C (0x380e70361c7e0e0e), U64_C (0x7c1ff8633ee71f1f), U64_C (0x956237f7c4556262), U64_C (0x77d4eea3b53ad4d4), U64_C (0x9aa829324d81a8a8), U64_C (0x6296c4f431529696), U64_C (0xc3f99b3aef62f9f9), U64_C (0x33c566f697a3c5c5), U64_C (0x942535b14a102525), U64_C (0x7959f220b2ab5959), U64_C (0x2a8454ae15d08484), U64_C (0xd572b7a7e4c57272), U64_C (0xe439d5dd72ec3939), U64_C (0x2d4c5a6198164c4c), U64_C (0x655eca3bbc945e5e), U64_C (0xfd78e785f09f7878), U64_C (0xe038ddd870e53838), U64_C (0x0a8c148605988c8c), U64_C (0x63d1c6b2bf17d1d1), U64_C (0xaea5410b57e4a5a5), U64_C (0xafe2434dd9a1e2e2), U64_C (0x99612ff8c24e6161), U64_C (0xf6b3f1457b42b3b3), U64_C (0x842115a542342121), U64_C (0x4a9c94d625089c9c), U64_C (0x781ef0663cee1e1e), U64_C (0x1143225286614343), U64_C (0x3bc776fc93b1c7c7), U64_C (0xd7fcb32be54ffcfc), U64_C (0x1004201408240404), U64_C (0x5951b208a2e35151), U64_C (0x5e99bcc72f259999), U64_C (0xa96d4fc4da226d6d), U64_C (0x340d68391a650d0d), U64_C (0xcffa8335e979fafa), U64_C (0x5bdfb684a369dfdf), U64_C (0xe57ed79bfca97e7e), U64_C (0x90243db448192424), U64_C (0xec3bc5d776fe3b3b), U64_C (0x96ab313d4b9aabab), U64_C (0x1fce3ed181f0cece), U64_C (0x4411885522991111), U64_C (0x068f0c8903838f8f), U64_C (0x254e4a6b9c044e4e), U64_C (0xe6b7d1517366b7b7), U64_C (0x8beb0b60cbe0ebeb), U64_C (0xf03cfdcc78c13c3c), U64_C (0x3e817cbf1ffd8181), U64_C (0x6a94d4fe35409494), U64_C (0xfbf7eb0cf31cf7f7), U64_C (0xdeb9a1676f18b9b9), U64_C (0x4c13985f268b1313), U64_C (0xb02c7d9c58512c2c), U64_C (0x6bd3d6b8bb05d3d3), U64_C (0xbbe76b5cd38ce7e7), U64_C (0xa56e57cbdc396e6e), U64_C (0x37c46ef395aac4c4), U64_C (0x0c03180f061b0303), U64_C (0x45568a13acdc5656), U64_C (0x0d441a49885e4444), U64_C (0xe17fdf9efea07f7f), U64_C (0x9ea921374f88a9a9), U64_C (0xa82a4d8254672a2a), U64_C (0xd6bbb16d6b0abbbb), U64_C (0x23c146e29f87c1c1), U64_C (0x5153a202a6f15353), U64_C (0x57dcae8ba572dcdc), U64_C (0x2c0b582716530b0b), U64_C (0x4e9d9cd327019d9d), U64_C (0xad6c47c1d82b6c6c), U64_C (0xc43195f562a43131), U64_C (0xcd7487b9e8f37474), U64_C (0xfff6e309f115f6f6), U64_C (0x05460a438c4c4646), U64_C (0x8aac092645a5acac), U64_C (0x1e893c970fb58989), U64_C (0x5014a04428b41414), U64_C (0xa3e15b42dfbae1e1), U64_C (0x5816b04e2ca61616), U64_C (0xe83acdd274f73a3a), U64_C (0xb9696fd0d2066969), U64_C (0x2409482d12410909), U64_C (0xdd70a7ade0d77070), U64_C (0xe2b6d954716fb6b6), U64_C (0x67d0ceb7bd1ed0d0), U64_C (0x93ed3b7ec7d6eded), U64_C (0x17cc2edb85e2cccc), U64_C (0x15422a5784684242), U64_C (0x5a98b4c22d2c9898), U64_C (0xaaa4490e55eda4a4), U64_C (0xa0285d8850752828), U64_C (0x6d5cda31b8865c5c), U64_C (0xc7f8933fed6bf8f8), U64_C (0x228644a411c28686), }; static const u64 C7[256] = { U64_C (0x186018c07830d818), U64_C (0x238c2305af462623), U64_C (0xc63fc67ef991b8c6), U64_C (0xe887e8136fcdfbe8), U64_C (0x8726874ca113cb87), U64_C (0xb8dab8a9626d11b8), U64_C (0x0104010805020901), U64_C (0x4f214f426e9e0d4f), U64_C (0x36d836adee6c9b36), U64_C (0xa6a2a6590451ffa6), U64_C (0xd26fd2debdb90cd2), U64_C (0xf5f3f5fb06f70ef5), U64_C (0x79f979ef80f29679), U64_C (0x6fa16f5fcede306f), U64_C (0x917e91fcef3f6d91), U64_C (0x525552aa07a4f852), U64_C (0x609d6027fdc04760), U64_C (0xbccabc89766535bc), U64_C (0x9b569baccd2b379b), U64_C (0x8e028e048c018a8e), U64_C (0xa3b6a371155bd2a3), U64_C (0x0c300c603c186c0c), U64_C (0x7bf17bff8af6847b), U64_C (0x35d435b5e16a8035), U64_C (0x1d741de8693af51d), U64_C (0xe0a7e05347ddb3e0), U64_C (0xd77bd7f6acb321d7), U64_C (0xc22fc25eed999cc2), U64_C (0x2eb82e6d965c432e), U64_C (0x4b314b627a96294b), U64_C (0xfedffea321e15dfe), U64_C (0x5741578216aed557), U64_C (0x155415a8412abd15), U64_C (0x77c1779fb6eee877), U64_C (0x37dc37a5eb6e9237), U64_C (0xe5b3e57b56d79ee5), U64_C (0x9f469f8cd923139f), U64_C (0xf0e7f0d317fd23f0), U64_C (0x4a354a6a7f94204a), U64_C (0xda4fda9e95a944da), U64_C (0x587d58fa25b0a258), U64_C (0xc903c906ca8fcfc9), U64_C (0x29a429558d527c29), U64_C (0x0a280a5022145a0a), U64_C (0xb1feb1e14f7f50b1), U64_C (0xa0baa0691a5dc9a0), U64_C (0x6bb16b7fdad6146b), U64_C (0x852e855cab17d985), U64_C (0xbdcebd8173673cbd), U64_C (0x5d695dd234ba8f5d), U64_C (0x1040108050209010), U64_C (0xf4f7f4f303f507f4), U64_C (0xcb0bcb16c08bddcb), U64_C (0x3ef83eedc67cd33e), U64_C (0x05140528110a2d05), U64_C (0x6781671fe6ce7867), U64_C (0xe4b7e47353d597e4), U64_C (0x279c2725bb4e0227), U64_C (0x4119413258827341), U64_C (0x8b168b2c9d0ba78b), U64_C (0xa7a6a7510153f6a7), U64_C (0x7de97dcf94fab27d), U64_C (0x956e95dcfb374995), U64_C (0xd847d88e9fad56d8), U64_C (0xfbcbfb8b30eb70fb), U64_C (0xee9fee2371c1cdee), U64_C (0x7ced7cc791f8bb7c), U64_C (0x66856617e3cc7166), U64_C (0xdd53dda68ea77bdd), U64_C (0x175c17b84b2eaf17), U64_C (0x47014702468e4547), U64_C (0x9e429e84dc211a9e), U64_C (0xca0fca1ec589d4ca), U64_C (0x2db42d75995a582d), U64_C (0xbfc6bf9179632ebf), U64_C (0x071c07381b0e3f07), U64_C (0xad8ead012347acad), U64_C (0x5a755aea2fb4b05a), U64_C (0x8336836cb51bef83), U64_C (0x33cc3385ff66b633), U64_C (0x6391633ff2c65c63), U64_C (0x020802100a041202), U64_C (0xaa92aa39384993aa), U64_C (0x71d971afa8e2de71), U64_C (0xc807c80ecf8dc6c8), U64_C (0x196419c87d32d119), U64_C (0x4939497270923b49), U64_C (0xd943d9869aaf5fd9), U64_C (0xf2eff2c31df931f2), U64_C (0xe3abe34b48dba8e3), U64_C (0x5b715be22ab6b95b), U64_C (0x881a8834920dbc88), U64_C (0x9a529aa4c8293e9a), U64_C (0x2698262dbe4c0b26), U64_C (0x32c8328dfa64bf32), U64_C (0xb0fab0e94a7d59b0), U64_C (0xe983e91b6acff2e9), U64_C (0x0f3c0f78331e770f), U64_C (0xd573d5e6a6b733d5), U64_C (0x803a8074ba1df480), U64_C (0xbec2be997c6127be), U64_C (0xcd13cd26de87ebcd), U64_C (0x34d034bde4688934), U64_C (0x483d487a75903248), U64_C (0xffdbffab24e354ff), U64_C (0x7af57af78ff48d7a), U64_C (0x907a90f4ea3d6490), U64_C (0x5f615fc23ebe9d5f), U64_C (0x2080201da0403d20), U64_C (0x68bd6867d5d00f68), U64_C (0x1a681ad07234ca1a), U64_C (0xae82ae192c41b7ae), U64_C (0xb4eab4c95e757db4), U64_C (0x544d549a19a8ce54), U64_C (0x937693ece53b7f93), U64_C (0x2288220daa442f22), U64_C (0x648d6407e9c86364), U64_C (0xf1e3f1db12ff2af1), U64_C (0x73d173bfa2e6cc73), U64_C (0x124812905a248212), U64_C (0x401d403a5d807a40), U64_C (0x0820084028104808), U64_C (0xc32bc356e89b95c3), U64_C (0xec97ec337bc5dfec), U64_C (0xdb4bdb9690ab4ddb), U64_C (0xa1bea1611f5fc0a1), U64_C (0x8d0e8d1c8307918d), U64_C (0x3df43df5c97ac83d), U64_C (0x976697ccf1335b97), U64_C (0x0000000000000000), U64_C (0xcf1bcf36d483f9cf), U64_C (0x2bac2b4587566e2b), U64_C (0x76c57697b3ece176), U64_C (0x82328264b019e682), U64_C (0xd67fd6fea9b128d6), U64_C (0x1b6c1bd87736c31b), U64_C (0xb5eeb5c15b7774b5), U64_C (0xaf86af112943beaf), U64_C (0x6ab56a77dfd41d6a), U64_C (0x505d50ba0da0ea50), U64_C (0x450945124c8a5745), U64_C (0xf3ebf3cb18fb38f3), U64_C (0x30c0309df060ad30), U64_C (0xef9bef2b74c3c4ef), U64_C (0x3ffc3fe5c37eda3f), U64_C (0x554955921caac755), U64_C (0xa2b2a2791059dba2), U64_C (0xea8fea0365c9e9ea), U64_C (0x6589650fecca6a65), U64_C (0xbad2bab9686903ba), U64_C (0x2fbc2f65935e4a2f), U64_C (0xc027c04ee79d8ec0), U64_C (0xde5fdebe81a160de), U64_C (0x1c701ce06c38fc1c), U64_C (0xfdd3fdbb2ee746fd), U64_C (0x4d294d52649a1f4d), U64_C (0x927292e4e0397692), U64_C (0x75c9758fbceafa75), U64_C (0x061806301e0c3606), U64_C (0x8a128a249809ae8a), U64_C (0xb2f2b2f940794bb2), U64_C (0xe6bfe66359d185e6), U64_C (0x0e380e70361c7e0e), U64_C (0x1f7c1ff8633ee71f), U64_C (0x62956237f7c45562), U64_C (0xd477d4eea3b53ad4), U64_C (0xa89aa829324d81a8), U64_C (0x966296c4f4315296), U64_C (0xf9c3f99b3aef62f9), U64_C (0xc533c566f697a3c5), U64_C (0x25942535b14a1025), U64_C (0x597959f220b2ab59), U64_C (0x842a8454ae15d084), U64_C (0x72d572b7a7e4c572), U64_C (0x39e439d5dd72ec39), U64_C (0x4c2d4c5a6198164c), U64_C (0x5e655eca3bbc945e), U64_C (0x78fd78e785f09f78), U64_C (0x38e038ddd870e538), U64_C (0x8c0a8c148605988c), U64_C (0xd163d1c6b2bf17d1), U64_C (0xa5aea5410b57e4a5), U64_C (0xe2afe2434dd9a1e2), U64_C (0x6199612ff8c24e61), U64_C (0xb3f6b3f1457b42b3), U64_C (0x21842115a5423421), U64_C (0x9c4a9c94d625089c), U64_C (0x1e781ef0663cee1e), U64_C (0x4311432252866143), U64_C (0xc73bc776fc93b1c7), U64_C (0xfcd7fcb32be54ffc), U64_C (0x0410042014082404), U64_C (0x515951b208a2e351), U64_C (0x995e99bcc72f2599), U64_C (0x6da96d4fc4da226d), U64_C (0x0d340d68391a650d), U64_C (0xfacffa8335e979fa), U64_C (0xdf5bdfb684a369df), U64_C (0x7ee57ed79bfca97e), U64_C (0x2490243db4481924), U64_C (0x3bec3bc5d776fe3b), U64_C (0xab96ab313d4b9aab), U64_C (0xce1fce3ed181f0ce), U64_C (0x1144118855229911), U64_C (0x8f068f0c8903838f), U64_C (0x4e254e4a6b9c044e), U64_C (0xb7e6b7d1517366b7), U64_C (0xeb8beb0b60cbe0eb), U64_C (0x3cf03cfdcc78c13c), U64_C (0x813e817cbf1ffd81), U64_C (0x946a94d4fe354094), U64_C (0xf7fbf7eb0cf31cf7), U64_C (0xb9deb9a1676f18b9), U64_C (0x134c13985f268b13), U64_C (0x2cb02c7d9c58512c), U64_C (0xd36bd3d6b8bb05d3), U64_C (0xe7bbe76b5cd38ce7), U64_C (0x6ea56e57cbdc396e), U64_C (0xc437c46ef395aac4), U64_C (0x030c03180f061b03), U64_C (0x5645568a13acdc56), U64_C (0x440d441a49885e44), U64_C (0x7fe17fdf9efea07f), U64_C (0xa99ea921374f88a9), U64_C (0x2aa82a4d8254672a), U64_C (0xbbd6bbb16d6b0abb), U64_C (0xc123c146e29f87c1), U64_C (0x535153a202a6f153), U64_C (0xdc57dcae8ba572dc), U64_C (0x0b2c0b582716530b), U64_C (0x9d4e9d9cd327019d), U64_C (0x6cad6c47c1d82b6c), U64_C (0x31c43195f562a431), U64_C (0x74cd7487b9e8f374), U64_C (0xf6fff6e309f115f6), U64_C (0x4605460a438c4c46), U64_C (0xac8aac092645a5ac), U64_C (0x891e893c970fb589), U64_C (0x145014a04428b414), U64_C (0xe1a3e15b42dfbae1), U64_C (0x165816b04e2ca616), U64_C (0x3ae83acdd274f73a), U64_C (0x69b9696fd0d20669), U64_C (0x092409482d124109), U64_C (0x70dd70a7ade0d770), U64_C (0xb6e2b6d954716fb6), U64_C (0xd067d0ceb7bd1ed0), U64_C (0xed93ed3b7ec7d6ed), U64_C (0xcc17cc2edb85e2cc), U64_C (0x4215422a57846842), U64_C (0x985a98b4c22d2c98), U64_C (0xa4aaa4490e55eda4), U64_C (0x28a0285d88507528), U64_C (0x5c6d5cda31b8865c), U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286), }; static void whirlpool_init (void *ctx) { whirlpool_context_t *context = ctx; memset (context, 0, sizeof (*context)); } /* * Transform block. */ static void whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) { whirlpool_block_t data_block; whirlpool_block_t key; whirlpool_block_t state; whirlpool_block_t block; unsigned int r; unsigned int i; buffer_to_block (data, data_block, i); block_copy (key, context->hash_state, i); block_copy (state, context->hash_state, i); block_xor (state, data_block, i); for (r = 0; r < R; r++) { /* Compute round key K^r. */ block[0] = (C0[(key[0] >> 56) & 0xFF] ^ C1[(key[7] >> 48) & 0xFF] ^ C2[(key[6] >> 40) & 0xFF] ^ C3[(key[5] >> 32) & 0xFF] ^ C4[(key[4] >> 24) & 0xFF] ^ C5[(key[3] >> 16) & 0xFF] ^ C6[(key[2] >> 8) & 0xFF] ^ C7[(key[1] >> 0) & 0xFF] ^ rc[r]); block[1] = (C0[(key[1] >> 56) & 0xFF] ^ C1[(key[0] >> 48) & 0xFF] ^ C2[(key[7] >> 40) & 0xFF] ^ C3[(key[6] >> 32) & 0xFF] ^ C4[(key[5] >> 24) & 0xFF] ^ C5[(key[4] >> 16) & 0xFF] ^ C6[(key[3] >> 8) & 0xFF] ^ C7[(key[2] >> 0) & 0xFF]); block[2] = (C0[(key[2] >> 56) & 0xFF] ^ C1[(key[1] >> 48) & 0xFF] ^ C2[(key[0] >> 40) & 0xFF] ^ C3[(key[7] >> 32) & 0xFF] ^ C4[(key[6] >> 24) & 0xFF] ^ C5[(key[5] >> 16) & 0xFF] ^ C6[(key[4] >> 8) & 0xFF] ^ C7[(key[3] >> 0) & 0xFF]); block[3] = (C0[(key[3] >> 56) & 0xFF] ^ C1[(key[2] >> 48) & 0xFF] ^ C2[(key[1] >> 40) & 0xFF] ^ C3[(key[0] >> 32) & 0xFF] ^ C4[(key[7] >> 24) & 0xFF] ^ C5[(key[6] >> 16) & 0xFF] ^ C6[(key[5] >> 8) & 0xFF] ^ C7[(key[4] >> 0) & 0xFF]); block[4] = (C0[(key[4] >> 56) & 0xFF] ^ C1[(key[3] >> 48) & 0xFF] ^ C2[(key[2] >> 40) & 0xFF] ^ C3[(key[1] >> 32) & 0xFF] ^ C4[(key[0] >> 24) & 0xFF] ^ C5[(key[7] >> 16) & 0xFF] ^ C6[(key[6] >> 8) & 0xFF] ^ C7[(key[5] >> 0) & 0xFF]); block[5] = (C0[(key[5] >> 56) & 0xFF] ^ C1[(key[4] >> 48) & 0xFF] ^ C2[(key[3] >> 40) & 0xFF] ^ C3[(key[2] >> 32) & 0xFF] ^ C4[(key[1] >> 24) & 0xFF] ^ C5[(key[0] >> 16) & 0xFF] ^ C6[(key[7] >> 8) & 0xFF] ^ C7[(key[6] >> 0) & 0xFF]); block[6] = (C0[(key[6] >> 56) & 0xFF] ^ C1[(key[5] >> 48) & 0xFF] ^ C2[(key[4] >> 40) & 0xFF] ^ C3[(key[3] >> 32) & 0xFF] ^ C4[(key[2] >> 24) & 0xFF] ^ C5[(key[1] >> 16) & 0xFF] ^ C6[(key[0] >> 8) & 0xFF] ^ C7[(key[7] >> 0) & 0xFF]); block[7] = (C0[(key[7] >> 56) & 0xFF] ^ C1[(key[6] >> 48) & 0xFF] ^ C2[(key[5] >> 40) & 0xFF] ^ C3[(key[4] >> 32) & 0xFF] ^ C4[(key[3] >> 24) & 0xFF] ^ C5[(key[2] >> 16) & 0xFF] ^ C6[(key[1] >> 8) & 0xFF] ^ C7[(key[0] >> 0) & 0xFF]); block_copy (key, block, i); /* Apply r-th round transformation. */ block[0] = (C0[(state[0] >> 56) & 0xFF] ^ C1[(state[7] >> 48) & 0xFF] ^ C2[(state[6] >> 40) & 0xFF] ^ C3[(state[5] >> 32) & 0xFF] ^ C4[(state[4] >> 24) & 0xFF] ^ C5[(state[3] >> 16) & 0xFF] ^ C6[(state[2] >> 8) & 0xFF] ^ C7[(state[1] >> 0) & 0xFF] ^ key[0]); block[1] = (C0[(state[1] >> 56) & 0xFF] ^ C1[(state[0] >> 48) & 0xFF] ^ C2[(state[7] >> 40) & 0xFF] ^ C3[(state[6] >> 32) & 0xFF] ^ C4[(state[5] >> 24) & 0xFF] ^ C5[(state[4] >> 16) & 0xFF] ^ C6[(state[3] >> 8) & 0xFF] ^ C7[(state[2] >> 0) & 0xFF] ^ key[1]); block[2] = (C0[(state[2] >> 56) & 0xFF] ^ C1[(state[1] >> 48) & 0xFF] ^ C2[(state[0] >> 40) & 0xFF] ^ C3[(state[7] >> 32) & 0xFF] ^ C4[(state[6] >> 24) & 0xFF] ^ C5[(state[5] >> 16) & 0xFF] ^ C6[(state[4] >> 8) & 0xFF] ^ C7[(state[3] >> 0) & 0xFF] ^ key[2]); block[3] = (C0[(state[3] >> 56) & 0xFF] ^ C1[(state[2] >> 48) & 0xFF] ^ C2[(state[1] >> 40) & 0xFF] ^ C3[(state[0] >> 32) & 0xFF] ^ C4[(state[7] >> 24) & 0xFF] ^ C5[(state[6] >> 16) & 0xFF] ^ C6[(state[5] >> 8) & 0xFF] ^ C7[(state[4] >> 0) & 0xFF] ^ key[3]); block[4] = (C0[(state[4] >> 56) & 0xFF] ^ C1[(state[3] >> 48) & 0xFF] ^ C2[(state[2] >> 40) & 0xFF] ^ C3[(state[1] >> 32) & 0xFF] ^ C4[(state[0] >> 24) & 0xFF] ^ C5[(state[7] >> 16) & 0xFF] ^ C6[(state[6] >> 8) & 0xFF] ^ C7[(state[5] >> 0) & 0xFF] ^ key[4]); block[5] = (C0[(state[5] >> 56) & 0xFF] ^ C1[(state[4] >> 48) & 0xFF] ^ C2[(state[3] >> 40) & 0xFF] ^ C3[(state[2] >> 32) & 0xFF] ^ C4[(state[1] >> 24) & 0xFF] ^ C5[(state[0] >> 16) & 0xFF] ^ C6[(state[7] >> 8) & 0xFF] ^ C7[(state[6] >> 0) & 0xFF] ^ key[5]); block[6] = (C0[(state[6] >> 56) & 0xFF] ^ C1[(state[5] >> 48) & 0xFF] ^ C2[(state[4] >> 40) & 0xFF] ^ C3[(state[3] >> 32) & 0xFF] ^ C4[(state[2] >> 24) & 0xFF] ^ C5[(state[1] >> 16) & 0xFF] ^ C6[(state[0] >> 8) & 0xFF] ^ C7[(state[7] >> 0) & 0xFF] ^ key[6]); block[7] = (C0[(state[7] >> 56) & 0xFF] ^ C1[(state[6] >> 48) & 0xFF] ^ C2[(state[5] >> 40) & 0xFF] ^ C3[(state[4] >> 32) & 0xFF] ^ C4[(state[3] >> 24) & 0xFF] ^ C5[(state[2] >> 16) & 0xFF] ^ C6[(state[1] >> 8) & 0xFF] ^ C7[(state[0] >> 0) & 0xFF] ^ key[7]); block_copy (state, block, i); } /* Compression. */ block_xor (context->hash_state, data_block, i); block_xor (context->hash_state, state, i); } static void whirlpool_add (whirlpool_context_t *context, const void *buffer_arg, size_t buffer_n) { const unsigned char *buffer = buffer_arg; u64 buffer_size; unsigned int carry; unsigned int i; buffer_size = buffer_n; if (context->count == BLOCK_SIZE) { /* Flush the buffer. */ whirlpool_transform (context, context->buffer); /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ context->count = 0; } if (! buffer) return; /* Nothing to add. */ if (context->count) { while (buffer_n && (context->count < BLOCK_SIZE)) { context->buffer[context->count++] = *buffer++; buffer_n--; } whirlpool_add (context, NULL, 0); } /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ while (buffer_n >= BLOCK_SIZE) { whirlpool_transform (context, buffer); context->count = 0; buffer_n -= BLOCK_SIZE; buffer += BLOCK_SIZE; } while (buffer_n && (context->count < BLOCK_SIZE)) { context->buffer[context->count++] = *buffer++; buffer_n--; } /* Update bit counter. */ carry = 0; buffer_size <<= 3; for (i = 1; i <= 32; i++) { if (! (buffer_size || carry)) break; carry += context->length[32 - i] + (buffer_size & 0xFF); context->length[32 - i] = carry; buffer_size >>= 8; carry >>= 8; } gcry_assert (! (buffer_size || carry)); } static void whirlpool_write (void *ctx, const void *buffer, size_t buffer_n) { whirlpool_context_t *context = ctx; whirlpool_add (context, buffer, buffer_n); } static void whirlpool_final (void *ctx) { whirlpool_context_t *context = ctx; unsigned int i; /* Flush. */ whirlpool_add (context, NULL, 0); /* Pad. */ context->buffer[context->count++] = 0x80; if (context->count > 32) { /* An extra block is necessary. */ while (context->count < 64) context->buffer[context->count++] = 0; whirlpool_add (context, NULL, 0); } while (context->count < 32) context->buffer[context->count++] = 0; /* Add length of message. */ memcpy (context->buffer + context->count, context->length, 32); context->count += 32; whirlpool_add (context, NULL, 0); block_to_buffer (context->buffer, context->hash_state, i); } static byte * whirlpool_read (void *ctx) { whirlpool_context_t *context = ctx; return context->buffer; } gcry_md_spec_t _gcry_digest_spec_whirlpool = { "WHIRLPOOL", NULL, 0, NULL, 64, whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, sizeof (whirlpool_context_t) }; diff --git a/configure.ac b/configure.ac index 91bbf4b1..2c92028b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,1797 +1,1827 @@ # Configure.ac script for Libgcrypt # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, # 2007, 2008, 2009, 2011 Free Software Foundation, Inc. # Copyright (C) 2012, 2013 g10 Code GmbH # # This file is part of Libgcrypt. # # Libgcrypt is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 2.1 of # the License, or (at your option) any later version. # # Libgcrypt is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this program; if not, see . # (Process this file with autoconf to produce a configure script.) AC_REVISION($Revision$) AC_PREREQ(2.60) min_automake_version="1.10" # To build a release you need to create a tag with the version number # (git tag -s libgcrypt-n.m.k) and run "./autogen.sh --force". Please # bump the version number immediately after the release and do another # commit and push so that the git magic is able to work. See below # for the LT versions. m4_define(mym4_version_major, [1]) m4_define(mym4_version_minor, [6]) m4_define(mym4_version_micro, [0]) # Below is m4 magic to extract and compute the revision number, the # decimalized short revision number, a beta version string, and a flag # indicating a development version (mym4_isgit). Note that the m4 # processing is done by autoconf and not during the configure run. m4_define(mym4_version, [mym4_version_major.mym4_version_minor.mym4_version_micro]) m4_define([mym4_revision], m4_esyscmd([git rev-parse --short HEAD | tr -d '\n\r'])) m4_define([mym4_revision_dec], m4_esyscmd_s([echo $((0x$(echo ]mym4_revision[|head -c 4)))])) m4_define([mym4_betastring], m4_esyscmd_s([git describe --match 'libgcrypt-[0-9].*[0-9]' --long|\ awk -F- '$3!=0{print"-beta"$3}'])) m4_define([mym4_isgit],m4_if(mym4_betastring,[],[no],[yes])) m4_define([mym4_full_version],[mym4_version[]mym4_betastring]) AC_INIT([libgcrypt],[mym4_full_version],[http://bugs.gnupg.org]) # LT Version numbers, remember to change them just *before* a release. # (Interfaces removed: CURRENT++, AGE=0, REVISION=0) # (Interfaces added: CURRENT++, AGE++, REVISION=0) # (No interfaces changed: REVISION++) # CAUTION: Due to the ABI change in 1.6 the LT version numbers below have # already been set for the next release. Thus don't update them for # the 1.6.0 release. LIBGCRYPT_LT_CURRENT=20 LIBGCRYPT_LT_AGE=0 LIBGCRYPT_LT_REVISION=0 # If the API is changed in an incompatible way: increment the next counter. LIBGCRYPT_CONFIG_API_VERSION=1 # If you change the required gpg-error version, please remove # unnecessary error code defines in src/gcrypt-int.h. NEED_GPG_ERROR_VERSION=1.11 PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION AC_CONFIG_SRCDIR([src/libgcrypt.vers]) AM_INIT_AUTOMAKE AC_CONFIG_HEADER(config.h) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_LIBOBJ_DIR([compat]) AC_CANONICAL_HOST AM_MAINTAINER_MODE AH_TOP([ #ifndef _GCRYPT_CONFIG_H_INCLUDED #define _GCRYPT_CONFIG_H_INCLUDED /* Enable gpg-error's strerror macro for W32CE. */ #define GPG_ERR_ENABLE_ERRNO_MACROS 1 ]) AH_BOTTOM([ #define _GCRYPT_IN_LIBGCRYPT 1 /* If the configure check for endianness has been disabled, get it from OS macros. This is intended for making fat binary builds on OS X. */ #ifdef DISABLED_ENDIAN_CHECK # if defined(__BIG_ENDIAN__) # define WORDS_BIGENDIAN 1 # elif defined(__LITTLE_ENDIAN__) # undef WORDS_BIGENDIAN # else # error "No endianness found" # endif #endif /*DISABLED_ENDIAN_CHECK*/ /* We basically use the original Camellia source. Make sure the symbols properly prefixed. */ #define CAMELLIA_EXT_SYM_PREFIX _gcry_ #endif /*_GCRYPT_CONFIG_H_INCLUDED*/ ]) AH_VERBATIM([_REENTRANT], [/* To allow the use of Libgcrypt in multithreaded programs we have to use special features from the library. */ #ifndef _REENTRANT # define _REENTRANT 1 #endif ]) AC_SUBST(LIBGCRYPT_LT_CURRENT) AC_SUBST(LIBGCRYPT_LT_AGE) AC_SUBST(LIBGCRYPT_LT_REVISION) AC_SUBST(PACKAGE) AC_SUBST(VERSION) AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) VERSION_NUMBER=m4_esyscmd(printf "0x%02x%02x%02x" mym4_version_major \ mym4_version_minor mym4_version_micro) AC_SUBST(VERSION_NUMBER) ###################### ## Basic checks. ### (we need some results later on (e.g. $GCC) ###################### AC_PROG_MAKE_SET missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) # AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) AC_PROG_CC AC_PROG_CPP AM_PROG_CC_C_O AM_PROG_AS AC_ISC_POSIX AC_PROG_INSTALL AC_PROG_AWK AC_GNU_SOURCE # We need to compile and run a program on the build machine. A # comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in # the AC archive is broken for autoconf 2.57. Given that there is no # newer version of that macro, we assume that it is also broken for # autoconf 2.61 and thus we use a simple but usually sufficient # approach. AC_MSG_CHECKING(for cc for build) if test "$cross_compiling" = "yes"; then CC_FOR_BUILD="${CC_FOR_BUILD-cc}" else CC_FOR_BUILD="${CC_FOR_BUILD-$CC}" fi AC_MSG_RESULT($CC_FOR_BUILD) AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler]) LT_PREREQ([2.2.6]) LT_INIT([win32-dll disable-static]) LT_LANG([Windows Resource]) ########################## ## General definitions. ## ########################## # Used by libgcrypt-config LIBGCRYPT_CONFIG_LIBS="-lgcrypt" LIBGCRYPT_CONFIG_CFLAGS="" LIBGCRYPT_CONFIG_HOST="$host" # Definitions for symmetric ciphers. available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268 seed" available_ciphers="$available_ciphers camellia idea salsa20 gost28147" enabled_ciphers="" # Definitions for public-key ciphers. available_pubkey_ciphers="dsa elgamal rsa ecc" enabled_pubkey_ciphers="" # Definitions for message digests. available_digests="crc gostr3411-94 md4 md5 rmd160 sha1 sha256" available_digests_64="sha512 tiger whirlpool stribog" enabled_digests="" # Definitions for kdfs (optional ones) available_kdfs="s2k pkdf2" available_kdfs_64="scrypt" enabled_kdfs="" # Definitions for random modules. available_random_modules="linux egd unix" auto_random_modules="$available_random_modules" # Supported thread backends. LIBGCRYPT_THREAD_MODULES="" # Other definitions. print_egd_notice=no have_w32_system=no have_w32ce_system=no have_pthread=no # Setup some stuff depending on host. case "${host}" in *-*-mingw32*) ac_cv_have_dev_random=no have_w32_system=yes case "${host}" in *-mingw32ce*) have_w32ce_system=yes available_random_modules="w32ce" ;; *) available_random_modules="w32" ;; esac AC_DEFINE(USE_ONLY_8DOT3,1, [set this to limit filenames to the 8.3 format]) AC_DEFINE(HAVE_DRIVE_LETTERS,1, [defined if we must run on a stupid file system]) AC_DEFINE(HAVE_DOSISH_SYSTEM,1, [defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) with special properties like no file modes]) ;; i?86-emx-os2 | i?86-*-os2*emx) # OS/2 with the EMX environment ac_cv_have_dev_random=no AC_DEFINE(HAVE_DRIVE_LETTERS) AC_DEFINE(HAVE_DOSISH_SYSTEM) ;; i?86-*-msdosdjgpp*) # DOS with the DJGPP environment ac_cv_have_dev_random=no AC_DEFINE(HAVE_DRIVE_LETTERS) AC_DEFINE(HAVE_DOSISH_SYSTEM) ;; *-*-hpux*) if test -z "$GCC" ; then CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" fi ;; *-dec-osf4*) if test -z "$GCC" ; then # Suppress all warnings # to get rid of the unsigned/signed char mismatch warnings. CFLAGS="$CFLAGS -w" fi ;; m68k-atari-mint) ;; *) ;; esac if test "$have_w32_system" = yes; then AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system]) if test "$have_w32ce_system" = yes; then AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE]) fi fi AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes) AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes) # A printable OS Name is sometimes useful. case "${host}" in *-*-mingw32ce*) PRINTABLE_OS_NAME="W32CE" ;; *-*-mingw32*) PRINTABLE_OS_NAME="W32" ;; i?86-emx-os2 | i?86-*-os2*emx ) PRINTABLE_OS_NAME="OS/2" ;; i?86-*-msdosdjgpp*) PRINTABLE_OS_NAME="MSDOS/DJGPP" ;; *-linux*) PRINTABLE_OS_NAME="GNU/Linux" ;; *) PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` ;; esac # # Figure out the name of the random device # case "${host}" in *-openbsd*) NAME_OF_DEV_RANDOM="/dev/srandom" NAME_OF_DEV_URANDOM="/dev/urandom" ;; *) NAME_OF_DEV_RANDOM="/dev/random" NAME_OF_DEV_URANDOM="/dev/urandom" ;; esac AC_ARG_ENABLE(endian-check, AC_HELP_STRING([--disable-endian-check], [disable the endian check and trust the OS provided macros]), endiancheck=$enableval,endiancheck=yes) if test x"$endiancheck" = xyes ; then AC_C_BIGENDIAN else AC_DEFINE(DISABLED_ENDIAN_CHECK,1,[configure did not test for endianess]) fi AC_CHECK_SIZEOF(unsigned short, 2) AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned long, 4) AC_CHECK_SIZEOF(unsigned long long, 0) AC_TYPE_UINTPTR_T if test "$ac_cv_sizeof_unsigned_short" = "0" \ || test "$ac_cv_sizeof_unsigned_int" = "0" \ || test "$ac_cv_sizeof_unsigned_long" = "0"; then AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); fi # Do we have any 64-bit data types? if test "$ac_cv_sizeof_unsigned_int" != "8" \ && test "$ac_cv_sizeof_unsigned_long" != "8" \ && test "$ac_cv_sizeof_unsigned_long_long" != "8" \ && test "$ac_cv_sizeof_uint64_t" != "8"; then AC_MSG_WARN([No 64-bit types. Disabling TIGER/192, SCRYPT, SHA-384, \ SHA-512 and GOST R 34.11-12]) else available_digests="$available_digests $available_digests_64" available_kdfs="$available_kdfs $available_kdfs_64" fi # If not specified otherwise, all available algorithms will be # included. default_ciphers="$available_ciphers" default_pubkey_ciphers="$available_pubkey_ciphers" default_digests="$available_digests" default_kdfs="$available_kdfs" # Substitutions to set generated files in a Emacs buffer to read-only. AC_SUBST(emacs_local_vars_begin, ['Local Variables:']) AC_SUBST(emacs_local_vars_read_only, ['buffer-read-only: t']) AC_SUBST(emacs_local_vars_end, ['End:']) ############################ ## Command line switches. ## ############################ # Implementation of the --enable-ciphers switch. AC_ARG_ENABLE(ciphers, AC_HELP_STRING([--enable-ciphers=ciphers], [select the symmetric ciphers to include]), [enabled_ciphers=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`], [enabled_ciphers=""]) if test "x$enabled_ciphers" = "x" \ -o "$enabled_ciphers" = "yes" \ -o "$enabled_ciphers" = "no"; then enabled_ciphers=$default_ciphers fi AC_MSG_CHECKING([which symmetric ciphers to include]) for cipher in $enabled_ciphers; do LIST_MEMBER($cipher, $available_ciphers) if test "$found" = "0"; then AC_MSG_ERROR([unsupported cipher "$cipher" specified]) fi done AC_MSG_RESULT([$enabled_ciphers]) # Implementation of the --enable-pubkey-ciphers switch. AC_ARG_ENABLE(pubkey-ciphers, AC_HELP_STRING([--enable-pubkey-ciphers=ciphers], [select the public-key ciphers to include]), [enabled_pubkey_ciphers=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`], [enabled_pubkey_ciphers=""]) if test "x$enabled_pubkey_ciphers" = "x" \ -o "$enabled_pubkey_ciphers" = "yes" \ -o "$enabled_pubkey_ciphers" = "no"; then enabled_pubkey_ciphers=$default_pubkey_ciphers fi AC_MSG_CHECKING([which public-key ciphers to include]) for cipher in $enabled_pubkey_ciphers; do LIST_MEMBER($cipher, $available_pubkey_ciphers) if test "$found" = "0"; then AC_MSG_ERROR([unsupported public-key cipher specified]) fi done AC_MSG_RESULT([$enabled_pubkey_ciphers]) # Implementation of the --enable-digests switch. AC_ARG_ENABLE(digests, AC_HELP_STRING([--enable-digests=digests], [select the message digests to include]), [enabled_digests=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`], [enabled_digests=""]) if test "x$enabled_digests" = "x" \ -o "$enabled_digests" = "yes" \ -o "$enabled_digests" = "no"; then enabled_digests=$default_digests fi AC_MSG_CHECKING([which message digests to include]) for digest in $enabled_digests; do LIST_MEMBER($digest, $available_digests) if test "$found" = "0"; then AC_MSG_ERROR([unsupported message digest specified]) fi done AC_MSG_RESULT([$enabled_digests]) # Implementation of the --enable-kdfs switch. AC_ARG_ENABLE(kdfs, AC_HELP_STRING([--enable-kfds=kdfs], [select the KDFs to include]), [enabled_kdfs=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`], [enabled_kdfs=""]) if test "x$enabled_kdfs" = "x" \ -o "$enabled_kdfs" = "yes" \ -o "$enabled_kdfs" = "no"; then enabled_kdfs=$default_kdfs fi AC_MSG_CHECKING([which key derivation functions to include]) for kdf in $enabled_kdfs; do LIST_MEMBER($kdf, $available_kdfs) if test "$found" = "0"; then AC_MSG_ERROR([unsupported key derivation function specified]) fi done AC_MSG_RESULT([$enabled_kdfs]) # Implementation of the --enable-random switch. AC_ARG_ENABLE(random, AC_HELP_STRING([--enable-random=name], [select which random number generator to use]), [random=`echo $enableval | tr '[A-Z]' '[a-z]'`], []) if test "x$random" = "x" -o "$random" = "yes" -o "$random" = "no"; then random=default fi AC_MSG_CHECKING([which random module to use]) if test "$random" != "default" -a "$random" != "auto"; then LIST_MEMBER($random, $available_random_modules) if test "$found" = "0"; then AC_MSG_ERROR([unsupported random module specified]) fi fi AC_MSG_RESULT($random) # Implementation of the --disable-dev-random switch. AC_MSG_CHECKING([whether use of /dev/random is requested]) AC_ARG_ENABLE(dev-random, [ --disable-dev-random disable the use of dev random], try_dev_random=$enableval, try_dev_random=yes) AC_MSG_RESULT($try_dev_random) # Implementation of the --with-egd-socket switch. AC_ARG_WITH(egd-socket, [ --with-egd-socket=NAME Use NAME for the EGD socket)], egd_socket_name="$withval", egd_socket_name="" ) AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name", [Define if you don't want the default EGD socket name. For details see cipher/rndegd.c]) # Implementation of the --enable-random-daemon AC_MSG_CHECKING([whether the experimental random daemon is requested]) AC_ARG_ENABLE([random-daemon], AC_HELP_STRING([--enable-random-daemon], [Build and support the experimental gcryptrnd]), [use_random_daemon=$enableval], [use_random_daemon=no]) AC_MSG_RESULT($use_random_daemon) if test x$use_random_daemon = xyes ; then AC_DEFINE(USE_RANDOM_DAEMON,1, [Define to support the experimental random daemon]) fi AM_CONDITIONAL(USE_RANDOM_DAEMON, test x$use_random_daemon = xyes) # Implementation of --disable-asm. AC_MSG_CHECKING([whether MPI assembler modules are requested]) AC_ARG_ENABLE([asm], AC_HELP_STRING([--disable-asm], [Disable MPI assembler modules]), [try_asm_modules=$enableval], [try_asm_modules=yes]) AC_MSG_RESULT($try_asm_modules) # Implementation of the --enable-m-guard switch. AC_MSG_CHECKING([whether memory guard is requested]) AC_ARG_ENABLE(m-guard, AC_HELP_STRING([--enable-m-guard], [Enable memory guard facility]), [use_m_guard=$enableval], [use_m_guard=no]) AC_MSG_RESULT($use_m_guard) if test "$use_m_guard" = yes ; then AC_DEFINE(M_GUARD,1,[Define to use the (obsolete) malloc guarding feature]) fi # Implementation of the --with-capabilities switch. # Check whether we want to use Linux capabilities AC_MSG_CHECKING([whether use of capabilities is requested]) AC_ARG_WITH(capabilities, AC_HELP_STRING([--with-capabilities], [Use linux capabilities [default=no]]), [use_capabilities="$withval"],[use_capabilities=no]) AC_MSG_RESULT($use_capabilities) # Implementation of the --enable-hmac-binary-check. AC_MSG_CHECKING([whether a HMAC binary check is requested]) AC_ARG_ENABLE(hmac-binary-check, AC_HELP_STRING([--enable-hmac-binary-check], [Enable library integrity check]), [use_hmac_binary_check=$enableval], [use_hmac_binary_check=no]) AC_MSG_RESULT($use_hmac_binary_check) if test "$use_hmac_binary_check" = yes ; then AC_DEFINE(ENABLE_HMAC_BINARY_CHECK,1, [Define to support an HMAC based integrity check]) fi # Implementation of the --disable-padlock-support switch. AC_MSG_CHECKING([whether padlock support is requested]) AC_ARG_ENABLE(padlock-support, AC_HELP_STRING([--disable-padlock-support], [Disable support for the PadLock Engine of VIA processors]), padlocksupport=$enableval,padlocksupport=yes) AC_MSG_RESULT($padlocksupport) if test x"$padlocksupport" = xyes ; then AC_DEFINE(ENABLE_PADLOCK_SUPPORT, 1, [Enable support for the PadLock engine.]) fi # Implementation of the --disable-aesni-support switch. AC_MSG_CHECKING([whether AESNI support is requested]) AC_ARG_ENABLE(aesni-support, AC_HELP_STRING([--disable-aesni-support], [Disable support for the Intel AES-NI instructions]), aesnisupport=$enableval,aesnisupport=yes) AC_MSG_RESULT($aesnisupport) # Implementation of the --disable-drng-support switch. AC_MSG_CHECKING([whether DRNG support is requested]) AC_ARG_ENABLE(drng-support, AC_HELP_STRING([--disable-drng-support], [Disable support for the Intel DRNG (RDRAND instruction)]), drngsupport=$enableval,drngsupport=yes) AC_MSG_RESULT($drngsupport) if test x"$drngsupport" = xyes ; then AC_DEFINE(ENABLE_DRNG_SUPPORT, 1, [Enable support for Intel DRNG (RDRAND instruction).]) fi # Implementation of the --disable-avx-support switch. AC_MSG_CHECKING([whether AVX support is requested]) AC_ARG_ENABLE(avx-support, AC_HELP_STRING([--disable-avx-support], [Disable support for the Intel AVX instructions]), avxsupport=$enableval,avxsupport=yes) AC_MSG_RESULT($avxsupport) # Implementation of the --disable-avx2-support switch. AC_MSG_CHECKING([whether AVX2 support is requested]) AC_ARG_ENABLE(avx2-support, AC_HELP_STRING([--disable-avx2-support], [Disable support for the Intel AVX2 instructions]), avx2support=$enableval,avx2support=yes) AC_MSG_RESULT($avx2support) # Implementation of the --disable-neon-support switch. AC_MSG_CHECKING([whether NEON support is requested]) AC_ARG_ENABLE(neon-support, AC_HELP_STRING([--disable-neon-support], [Disable support for the ARM NEON instructions]), neonsupport=$enableval,neonsupport=yes) AC_MSG_RESULT($neonsupport) # Implementation of the --disable-O-flag-munging switch. AC_MSG_CHECKING([whether a -O flag munging is requested]) AC_ARG_ENABLE([O-flag-munging], AC_HELP_STRING([--disable-O-flag-munging], [Disable modification of the cc -O flag]), [enable_o_flag_munging=$enableval], [enable_o_flag_munging=yes]) AC_MSG_RESULT($enable_o_flag_munging) AM_CONDITIONAL(ENABLE_O_FLAG_MUNGING, test "$enable_o_flag_munging" = "yes") # Implementation of the --disable-amd64-as-feature-detection switch. AC_MSG_CHECKING([whether to enable AMD64 as(1) feature detection]) AC_ARG_ENABLE(amd64-as-feature-detection, AC_HELP_STRING([--disable-amd64-as-feature-detection], [Disable the auto-detection of AMD64 as(1) features]), amd64_as_feature_detection=$enableval, amd64_as_feature_detection=yes) AC_MSG_RESULT($amd64_as_feature_detection) AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", [A human readable text with the name of the OS]) # For some systems we know that we have ld_version scripts. # Use it then as default. have_ld_version_script=no case "${host}" in *-*-linux*) have_ld_version_script=yes ;; *-*-gnu*) have_ld_version_script=yes ;; esac AC_ARG_ENABLE([ld-version-script], AC_HELP_STRING([--enable-ld-version-script], [enable/disable use of linker version script. (default is system dependent)]), [have_ld_version_script=$enableval], [ : ] ) AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM", [defined to the name of the strong random device]) AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM", [defined to the name of the weaker random device]) ############################### #### Checks for libraries. #### ############################### # # gpg-error is required. # AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION") if test "x$GPG_ERROR_LIBS" = "x"; then AC_MSG_ERROR([libgpg-error is needed. See ftp://ftp.gnupg.org/gcrypt/libgpg-error/ .]) fi AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GCRYPT, [The default error source for libgcrypt.]) # # Check whether the GNU Pth library is available. We require this # to build the optional gcryptrnd program. # AC_ARG_WITH(pth-prefix, AC_HELP_STRING([--with-pth-prefix=PFX], [prefix where GNU Pth is installed (optional)]), pth_config_prefix="$withval", pth_config_prefix="") if test x$pth_config_prefix != x ; then PTH_CONFIG="$pth_config_prefix/bin/pth-config" fi if test "$use_random_daemon" = "yes"; then AC_PATH_PROG(PTH_CONFIG, pth-config, no) if test "$PTH_CONFIG" = "no"; then AC_MSG_WARN([[ *** *** To build the Libgcrypt's random number daemon *** we need the support of the GNU Portable Threads Library. *** Download it from ftp://ftp.gnu.org/gnu/pth/ *** On a Debian GNU/Linux system you might want to try *** apt-get install libpth-dev ***]]) else GNUPG_PTH_VERSION_CHECK([1.3.7]) if test $have_pth = yes; then PTH_CFLAGS=`$PTH_CONFIG --cflags` PTH_LIBS=`$PTH_CONFIG --ldflags` PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs --all`" AC_DEFINE(USE_GNU_PTH, 1, [Defined if the GNU Portable Thread Library should be used]) AC_DEFINE(HAVE_PTH, 1, [Defined if the GNU Pth is available]) fi fi fi AC_SUBST(PTH_CFLAGS) AC_SUBST(PTH_LIBS) # # Check whether pthreads is available # AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes) if test "$have_pthread" = yes; then AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.]) fi # # See which thread system we have # FIXME: Thus duplicates the above check. # gl_LOCK # Solaris needs -lsocket and -lnsl. Unisys system includes # gethostbyname in libsocket but needs libnsl for socket. AC_SEARCH_LIBS(setsockopt, [socket], , [AC_SEARCH_LIBS(setsockopt, [socket], , , [-lnsl])]) AC_SEARCH_LIBS(setsockopt, [nsl]) ################################## #### Checks for header files. #### ################################## AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h sys/select.h sys/msg.h) INSERT_SYS_SELECT_H= if test x"$ac_cv_header_sys_select_h" = xyes; then INSERT_SYS_SELECT_H=" include " fi AC_SUBST(INSERT_SYS_SELECT_H) ########################################## #### Checks for typedefs, structures, #### #### and compiler characteristics. #### ########################################## AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_TYPE_SIGNAL AC_DECL_SYS_SIGLIST AC_TYPE_PID_T GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF) GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF) GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF) gl_TYPE_SOCKLEN_T case "${host}" in *-*-mingw32*) # socklen_t may or may not be defined depending on what headers # are included. To be safe we use int as this is the actual type. FALLBACK_SOCKLEN_T="typedef int gcry_socklen_t;" ;; *) if test ".$gl_cv_socklen_t_equiv" = "."; then FALLBACK_SOCKLEN_T="typedef socklen_t gcry_socklen_t;" else FALLBACK_SOCKLEN_T="typedef ${gl_cv_socklen_t_equiv} gcry_socklen_t;" fi esac AC_SUBST(FALLBACK_SOCKLEN_T) +# +# Check for __builtin_bswap32 intrinsic. +# +AC_CACHE_CHECK(for __builtin_bswap32, + [gcry_cv_have_builtin_bswap32], + [gcry_cv_have_builtin_bswap32=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[int foo(int x) { return __builtin_bswap32(x); }]])], + [gcry_cv_have_builtin_bswap32=yes])]) +if test "$gcry_cv_have_builtin_bswap32" = "yes" ; then + AC_DEFINE(HAVE_BUILTIN_BSWAP32,1, + [Defined if compiler has '__builtin_bswap32' intrinsic]) +fi + + +# +# Check for __builtin_bswap64 intrinsic. +# +AC_CACHE_CHECK(for __builtin_bswap64, + [gcry_cv_have_builtin_bswap64], + [gcry_cv_have_builtin_bswap64=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[int foo(int x) { return __builtin_bswap64(x); }]])], + [gcry_cv_have_builtin_bswap64=yes])]) +if test "$gcry_cv_have_builtin_bswap64" = "yes" ; then + AC_DEFINE(HAVE_BUILTIN_BSWAP64,1, + [Defined if compiler has '__builtin_bswap64' intrinsic]) +fi + + # # Check for VLA support (variable length arrays). # AC_CACHE_CHECK(whether the variable length arrays are supported, [gcry_cv_have_vla], [gcry_cv_have_vla=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[void f1(char *, int); char foo(int i) { char b[(i < 0 ? 0 : i) + 1]; f1(b, sizeof b); return b[0];}]])], [gcry_cv_have_vla=yes])]) if test "$gcry_cv_have_vla" = "yes" ; then AC_DEFINE(HAVE_VLA,1, [Defined if variable length arrays are supported]) fi # # Check for ELF visibility support. # AC_CACHE_CHECK(whether the visibility attribute is supported, gcry_cv_visibility_attribute, [gcry_cv_visibility_attribute=no AC_LANG_CONFTEST([AC_LANG_SOURCE( [[int foo __attribute__ ((visibility ("hidden"))) = 1; int bar __attribute__ ((visibility ("protected"))) = 1; ]])]) if ${CC-cc} -Werror -S conftest.c -o conftest.s \ 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then if grep '\.hidden.*foo' conftest.s >/dev/null 2>&1 ; then if grep '\.protected.*bar' conftest.s >/dev/null 2>&1; then gcry_cv_visibility_attribute=yes fi fi fi ]) if test "$gcry_cv_visibility_attribute" = "yes"; then AC_CACHE_CHECK(for broken visibility attribute, gcry_cv_broken_visibility_attribute, [gcry_cv_broken_visibility_attribute=yes AC_LANG_CONFTEST([AC_LANG_SOURCE( [[int foo (int x); int bar (int x) __asm__ ("foo") __attribute__ ((visibility ("hidden"))); int bar (int x) { return x; } ]])]) if ${CC-cc} -Werror -S conftest.c -o conftest.s \ 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then if grep '\.hidden@<:@ _@:>@foo' conftest.s >/dev/null 2>&1; then gcry_cv_broken_visibility_attribute=no fi fi ]) fi if test "$gcry_cv_visibility_attribute" = "yes"; then AC_CACHE_CHECK(for broken alias attribute, gcry_cv_broken_alias_attribute, [gcry_cv_broken_alias_attribute=yes AC_LANG_CONFTEST([AC_LANG_SOURCE( [[extern int foo (int x) __asm ("xyzzy"); int bar (int x) { return x; } extern __typeof (bar) foo __attribute ((weak, alias ("bar"))); extern int dfoo; extern __typeof (dfoo) dfoo __asm ("abccb"); int dfoo = 1; ]])]) if ${CC-cc} -Werror -S conftest.c -o conftest.s \ 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then if grep 'xyzzy' conftest.s >/dev/null 2>&1 && \ grep 'abccb' conftest.s >/dev/null 2>&1; then gcry_cv_broken_alias_attribute=no fi fi ]) fi if test "$gcry_cv_visibility_attribute" = "yes"; then AC_CACHE_CHECK(if gcc supports -fvisibility=hidden, gcry_cv_gcc_has_f_visibility, [gcry_cv_gcc_has_f_visibility=no _gcc_cflags_save=$CFLAGS CFLAGS="-fvisibility=hidden" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])], gcry_cv_gcc_has_f_visibility=yes) CFLAGS=$_gcc_cflags_save; ]) fi if test "$gcry_cv_visibility_attribute" = "yes" \ && test "$gcry_cv_broken_visibility_attribute" != "yes" \ && test "$gcry_cv_broken_alias_attribute" != "yes" \ && test "$gcry_cv_gcc_has_f_visibility" = "yes" then AC_DEFINE(GCRY_USE_VISIBILITY, 1, [Define to use the GNU C visibility attribute.]) CFLAGS="$CFLAGS -fvisibility=hidden" fi # # Check whether the compiler supports the GCC style aligned attribute # AC_CACHE_CHECK([whether the GCC style aligned attribute is supported], [gcry_cv_gcc_attribute_aligned], [gcry_cv_gcc_attribute_aligned=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[struct { int a; } foo __attribute__ ((aligned (16)));]])], [gcry_cv_gcc_attribute_aligned=yes])]) if test "$gcry_cv_gcc_attribute_aligned" = "yes" ; then AC_DEFINE(HAVE_GCC_ATTRIBUTE_ALIGNED,1, [Defined if a GCC style "__attribute__ ((aligned (n))" is supported]) fi # # Check whether the compiler supports 'asm' or '__asm__' keyword for # assembler blocks # AC_CACHE_CHECK([whether 'asm' assembler keyword is supported], [gcry_cv_have_asm], [gcry_cv_have_asm=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[void a(void) { asm("":::"memory"); }]])], [gcry_cv_have_asm=yes])]) AC_CACHE_CHECK([whether '__asm__' assembler keyword is supported], [gcry_cv_have___asm__], [gcry_cv_have___asm__=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[void a(void) { __asm__("":::"memory"); }]])], [gcry_cv_have___asm__=yes])]) if test "$gcry_cv_have_asm" = "no" ; then if test "$gcry_cv_have___asm__" = "yes" ; then AC_DEFINE(asm,__asm__, [Define to supported assembler block keyword, if plain 'asm' was not supported]) fi fi # # Check whether GCC inline assembler supports SSSE3 instructions # This is required for the AES-NI instructions. # AC_CACHE_CHECK([whether GCC inline assembler supports SSSE3 instructions], [gcry_cv_gcc_inline_asm_ssse3], [gcry_cv_gcc_inline_asm_ssse3=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[static unsigned char be_mask[16] __attribute__ ((aligned (16))) = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; void a(void) { __asm__("pshufb %[mask], %%xmm2\n\t"::[mask]"m"(*be_mask):); }]])], [gcry_cv_gcc_inline_asm_ssse3=yes])]) if test "$gcry_cv_gcc_inline_asm_ssse3" = "yes" ; then AC_DEFINE(HAVE_GCC_INLINE_ASM_SSSE3,1, [Defined if inline assembler supports SSSE3 instructions]) fi # # Check whether GCC inline assembler supports AVX instructions # AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions], [gcry_cv_gcc_inline_asm_avx], [gcry_cv_gcc_inline_asm_avx=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[void a(void) { __asm__("vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):); }]])], [gcry_cv_gcc_inline_asm_avx=yes])]) if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX,1, [Defined if inline assembler supports AVX instructions]) fi # # Check whether GCC inline assembler supports AVX2 instructions # AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions], [gcry_cv_gcc_inline_asm_avx2], [gcry_cv_gcc_inline_asm_avx2=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[void a(void) { __asm__("vpbroadcastb %%xmm7,%%ymm1\n\t":::); }]])], [gcry_cv_gcc_inline_asm_avx2=yes])]) if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX2,1, [Defined if inline assembler supports AVX2 instructions]) fi # # Check whether GCC assembler supports features needed for our amd64 # implementations # if test $amd64_as_feature_detection = yes; then AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implementations], [gcry_cv_gcc_amd64_platform_as_ok], [gcry_cv_gcc_amd64_platform_as_ok=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[__asm__( /* Test if '.set' is supported by underlying assembler. */ ".set a0, %rax\n\t" ".set b0, %rdx\n\t" "asmfunc:\n\t" "movq a0, b0;\n\t" /* Fails here if .set ignored by as. */ /* Test if '.type' and '.size' are supported. */ /* These work only on ELF targets. */ /* TODO: add COFF (mingw64, cygwin64) support to assembly * implementations. Mingw64/cygwin64 also require additional * work because they use different calling convention. */ ".size asmfunc,.-asmfunc;\n\t" ".type asmfunc,@function;\n\t" );]])], [gcry_cv_gcc_amd64_platform_as_ok=yes])]) if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then AC_DEFINE(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS,1, [Defined if underlying assembler is compatible with amd64 assembly implementations]) fi fi # # Check whether compiler is configured for ARMv6 or newer architecture # AC_CACHE_CHECK([whether compiler is configured for ARMv6 or newer architecture], [gcry_cv_cc_arm_arch_is_v6], [AC_EGREP_CPP(yes, [#if defined(__arm__) && \ ((defined(__ARM_ARCH) && __ARM_ARCH >= 6) \ || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \ || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ || defined(__ARM_ARCH_7EM__)) yes #endif ], gcry_cv_cc_arm_arch_is_v6=yes, gcry_cv_cc_arm_arch_is_v6=no)]) if test "$gcry_cv_cc_arm_arch_is_v6" = "yes" ; then AC_DEFINE(HAVE_ARM_ARCH_V6,1, [Defined if ARM architecture is v6 or newer]) fi # # Check whether GCC inline assembler supports NEON instructions # AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions], [gcry_cv_gcc_inline_asm_neon], [gcry_cv_gcc_inline_asm_neon=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[__asm__( ".syntax unified\n\t" ".thumb\n\t" ".fpu neon\n\t" "vld1.64 {%q0-%q1}, [%r0]!;\n\t" "vrev64.8 %q0, %q3;\n\t" "vadd.u64 %q0, %q1;\n\t" "vadd.s64 %d3, %d2, %d3;\n\t" ); ]])], [gcry_cv_gcc_inline_asm_neon=yes])]) if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then AC_DEFINE(HAVE_GCC_INLINE_ASM_NEON,1, [Defined if inline assembler supports NEON instructions]) fi # # Check whether GCC assembler supports features needed for our ARM # implementations # AC_CACHE_CHECK([whether GCC assembler is compatible for ARM assembly implementations], [gcry_cv_gcc_arm_platform_as_ok], [gcry_cv_gcc_arm_platform_as_ok=no AC_COMPILE_IFELSE([AC_LANG_SOURCE( [[__asm__( /* Test if assembler supports UAL syntax. */ ".syntax unified\n\t" ".thumb\n\t" /* thumb-2 in UAL, thumb-1 otherwise. */ ".code 16\n\t" /* Following causes error if assembler ignored '.syntax unified'. */ "asmfunc:\n\t" "add.w %r0, %r4, %r8, ror #12;\n\t" /* Test if '.type' and '.size' are supported. */ ".size asmfunc,.-asmfunc;\n\t" ".type asmfunc,%function;\n\t" );]])], [gcry_cv_gcc_arm_platform_as_ok=yes])]) if test "$gcry_cv_gcc_arm_platform_as_ok" = "yes" ; then AC_DEFINE(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS,1, [Defined if underlying assembler is compatible with ARM assembly implementations]) fi ####################################### #### Checks for library functions. #### ####################################### AC_FUNC_VPRINTF # We have replacements for these in src/missing-string.c AC_CHECK_FUNCS(stpcpy strcasecmp) # We have replacements for these in src/g10lib.h AC_CHECK_FUNCS(strtoul memmove stricmp atexit raise) # Other checks AC_CHECK_FUNCS(strerror rand mmap getpagesize sysconf waitpid wait4) AC_CHECK_FUNCS(gettimeofday getrusage gethrtime clock_gettime syslog) AC_CHECK_FUNCS(fcntl ftruncate) GNUPG_CHECK_MLOCK # # Replacement functions. # AC_REPLACE_FUNCS([getpid clock]) # # Check wether it is necessary to link against libdl. # DL_LIBS="" if test "$use_hmac_binary_check" = yes ; then _gcry_save_libs="$LIBS" LIBS="" AC_SEARCH_LIBS(dlopen, c dl,,,) DL_LIBS=$LIBS LIBS="$_gcry_save_libs" LIBGCRYPT_CONFIG_LIBS="${LIBGCRYPT_CONFIG_LIBS} ${DL_LIBS}" fi AC_SUBST(DL_LIBS) # # Check whether we can use Linux capabilities as requested. # if test "$use_capabilities" = "yes" ; then use_capabilities=no AC_CHECK_HEADERS(sys/capability.h) if test "$ac_cv_header_sys_capability_h" = "yes" ; then AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1) if test "$ac_cv_lib_cap_cap_init" = "yes"; then AC_DEFINE(USE_CAPABILITIES,1, [define if capabilities should be used]) LIBS="$LIBS -lcap" use_capabilities=yes fi fi if test "$use_capabilities" = "no" ; then AC_MSG_WARN([[ *** *** The use of capabilities on this system is not possible. *** You need a recent Linux kernel and some patches: *** fcaps-2.2.9-990610.patch (kernel patch for 2.2.9) *** fcap-module-990613.tar.gz (kernel module) *** libcap-1.92.tar.gz (user mode library and utilities) *** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN *** set (filesystems menu). Be warned: This code is *really* ALPHA. ***]]) fi fi # Check whether a random device is available. if test "$try_dev_random" = yes ; then AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, [if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) if test "$ac_cv_have_dev_random" = yes; then AC_DEFINE(HAVE_DEV_RANDOM,1, [defined if the system supports a random device] ) fi else AC_MSG_CHECKING(for random device) ac_cv_have_dev_random=no AC_MSG_RESULT(has been disabled) fi # Figure out the random modules for this configuration. if test "$random" = "default"; then # Select default value. if test "$ac_cv_have_dev_random" = yes; then # Try Linuxish random device. random_modules="linux" else case "${host}" in *-*-mingw32ce*) # WindowsCE random device. random_modules="w32ce" ;; *-*-mingw32*|*-*-cygwin*) # Windows random device. random_modules="w32" ;; *) # Build everything, allow to select at runtime. random_modules="$auto_random_modules" ;; esac fi else if test "$random" = "auto"; then # Build everything, allow to select at runtime. random_modules="$auto_random_modules" else random_modules="$random" fi fi # # Setup assembler stuff. # # Note that config.links also defines mpi_cpu_arch, which is required # later on. # GNUPG_SYS_SYMBOL_UNDERSCORE() AC_ARG_ENABLE(mpi-path, AC_HELP_STRING([--enable-mpi-path=EXTRA_PATH], [prepend EXTRA_PATH to list of CPU specific optimizations]), mpi_extra_path="$enableval",mpi_extra_path="") AC_MSG_CHECKING(for mpi assembler functions) if test -f $srcdir/mpi/config.links ; then . $srcdir/mpi/config.links AC_CONFIG_LINKS("$mpi_ln_list") ac_cv_mpi_sflags="$mpi_sflags" AC_MSG_RESULT(done) else AC_MSG_RESULT(failed) AC_MSG_ERROR([mpi/config.links missing!]) fi MPI_SFLAGS="$ac_cv_mpi_sflags" AC_SUBST(MPI_SFLAGS) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_ADD1, test "$mpi_mod_asm_mpih_add1" = yes) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_SUB1, test "$mpi_mod_asm_mpih_sub1" = yes) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL1, test "$mpi_mod_asm_mpih_mul1" = yes) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL2, test "$mpi_mod_asm_mpih_mul2" = yes) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL3, test "$mpi_mod_asm_mpih_mul3" = yes) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_LSHIFT, test "$mpi_mod_asm_mpih_lshift" = yes) AM_CONDITIONAL(MPI_MOD_ASM_MPIH_RSHIFT, test "$mpi_mod_asm_mpih_rshift" = yes) AM_CONDITIONAL(MPI_MOD_ASM_UDIV, test "$mpi_mod_asm_udiv" = yes) AM_CONDITIONAL(MPI_MOD_ASM_UDIV_QRNND, test "$mpi_mod_asm_udiv_qrnnd" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_ADD1, test "$mpi_mod_c_mpih_add1" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_SUB1, test "$mpi_mod_c_mpih_sub1" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL1, test "$mpi_mod_c_mpih_mul1" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL2, test "$mpi_mod_c_mpih_mul2" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL3, test "$mpi_mod_c_mpih_mul3" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_LSHIFT, test "$mpi_mod_c_mpih_lshift" = yes) AM_CONDITIONAL(MPI_MOD_C_MPIH_RSHIFT, test "$mpi_mod_c_mpih_rshift" = yes) AM_CONDITIONAL(MPI_MOD_C_UDIV, test "$mpi_mod_c_udiv" = yes) AM_CONDITIONAL(MPI_MOD_C_UDIV_QRNND, test "$mpi_mod_c_udiv_qrnnd" = yes) if test mym4_isgit = "yes"; then AC_DEFINE(IS_DEVELOPMENT_VERSION,1, [Defined if this is not a regular release]) fi AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) # This is handy for debugging so the compiler doesn't rearrange # things and eliminate variables. AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable compiler optimization]), [if test $enableval = no ; then CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'` fi]) # CFLAGS mangling when using gcc. if test "$GCC" = yes; then CFLAGS="$CFLAGS -Wall" if test "$USE_MAINTAINER_MODE" = "yes"; then CFLAGS="$CFLAGS -Wcast-align -Wshadow -Wstrict-prototypes" CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security" # If -Wno-missing-field-initializers is supported we can enable a # a bunch of really useful warnings. AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers]) _gcc_cflags_save=$CFLAGS CFLAGS="-Wno-missing-field-initializers" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no) AC_MSG_RESULT($_gcc_wopt) CFLAGS=$_gcc_cflags_save; if test x"$_gcc_wopt" = xyes ; then CFLAGS="$CFLAGS -W -Wextra -Wbad-function-cast" CFLAGS="$CFLAGS -Wwrite-strings" CFLAGS="$CFLAGS -Wdeclaration-after-statement" CFLAGS="$CFLAGS -Wno-missing-field-initializers" CFLAGS="$CFLAGS -Wno-sign-compare" fi AC_MSG_CHECKING([if gcc supports -Wpointer-arith]) _gcc_cflags_save=$CFLAGS CFLAGS="-Wpointer-arith" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no) AC_MSG_RESULT($_gcc_wopt) CFLAGS=$_gcc_cflags_save; if test x"$_gcc_wopt" = xyes ; then CFLAGS="$CFLAGS -Wpointer-arith" fi fi fi # Check whether as(1) supports a noeexecstack feature. This test # includes an override option. CL_AS_NOEXECSTACK AC_SUBST(LIBGCRYPT_CONFIG_API_VERSION) AC_SUBST(LIBGCRYPT_CONFIG_LIBS) AC_SUBST(LIBGCRYPT_CONFIG_CFLAGS) AC_SUBST(LIBGCRYPT_CONFIG_HOST) AC_SUBST(LIBGCRYPT_THREAD_MODULES) AC_CONFIG_COMMANDS([gcrypt-conf],[[ chmod +x src/libgcrypt-config ]],[[ prefix=$prefix exec_prefix=$exec_prefix libdir=$libdir datadir=$datadir DATADIRNAME=$DATADIRNAME ]]) ##################### #### Conclusion. #### ##################### # Check that requested feature can actually be used and define # ENABLE_foo_SUPPORT macros. if test x"$aesnisupport" = xyes ; then if test "$gcry_cv_gcc_inline_asm_ssse3" != "yes" ; then aesnisupport="no (unsupported by compiler)" fi fi if test x"$avxsupport" = xyes ; then if test "$gcry_cv_gcc_inline_asm_avx" != "yes" ; then avxsupport="no (unsupported by compiler)" fi fi if test x"$avx2support" = xyes ; then if test "$gcry_cv_gcc_inline_asm_avx2" != "yes" ; then avx2support="no (unsupported by compiler)" fi fi if test x"$neonsupport" = xyes ; then if test "$gcry_cv_gcc_inline_asm_neon" != "yes" ; then neonsupport="no (unsupported by compiler)" fi fi if test x"$aesnisupport" = xyes ; then AC_DEFINE(ENABLE_AESNI_SUPPORT, 1, [Enable support for Intel AES-NI instructions.]) fi if test x"$avxsupport" = xyes ; then AC_DEFINE(ENABLE_AVX_SUPPORT,1, [Enable support for Intel AVX instructions.]) fi if test x"$avx2support" = xyes ; then AC_DEFINE(ENABLE_AVX2_SUPPORT,1, [Enable support for Intel AVX2 instructions.]) fi if test x"$neonsupport" = xyes ; then AC_DEFINE(ENABLE_NEON_SUPPORT,1, [Enable support for ARM NEON instructions.]) fi # Define conditional sources and config.h symbols depending on the # selected ciphers, pubkey-ciphers, digests, kdfs, and random modules. LIST_MEMBER(arcfour, $enabled_ciphers) if test "$found" = "1"; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour.lo" AC_DEFINE(USE_ARCFOUR, 1, [Defined if this module should be included]) fi LIST_MEMBER(blowfish, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish.lo" AC_DEFINE(USE_BLOWFISH, 1, [Defined if this module should be included]) case "${host}" in x86_64-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-amd64.lo" ;; arm*-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-armv6.lo" ;; esac fi LIST_MEMBER(cast5, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5.lo" AC_DEFINE(USE_CAST5, 1, [Defined if this module should be included]) case "${host}" in x86_64-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-amd64.lo" ;; arm*-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-armv6.lo" ;; esac fi LIST_MEMBER(des, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS des.lo" AC_DEFINE(USE_DES, 1, [Defined if this module should be included]) fi LIST_MEMBER(aes, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael.lo" AC_DEFINE(USE_AES, 1, [Defined if this module should be included]) case "${host}" in x86_64-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-amd64.lo" ;; arm*-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv6.lo" ;; esac fi LIST_MEMBER(twofish, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish.lo" AC_DEFINE(USE_TWOFISH, 1, [Defined if this module should be included]) case "${host}" in x86_64-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-amd64.lo" ;; esac fi LIST_MEMBER(serpent, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent.lo" AC_DEFINE(USE_SERPENT, 1, [Defined if this module should be included]) case "${host}" in x86_64-*-*) # Build with the SSE2 implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-sse2-amd64.lo" ;; esac if test x"$avx2support" = xyes ; then # Build with the AVX2 implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-avx2-amd64.lo" fi fi LIST_MEMBER(rfc2268, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS rfc2268.lo" AC_DEFINE(USE_RFC2268, 1, [Defined if this module should be included]) fi LIST_MEMBER(seed, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS seed.lo" AC_DEFINE(USE_SEED, 1, [Defined if this module should be included]) fi LIST_MEMBER(camellia, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia.lo camellia-glue.lo" AC_DEFINE(USE_CAMELLIA, 1, [Defined if this module should be included]) case "${host}" in arm*-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-armv6.lo" ;; esac if test x"$avxsupport" = xyes ; then if test x"$aesnisupport" = xyes ; then # Build with the AES-NI/AVX implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx-amd64.lo" fi fi if test x"$avx2support" = xyes ; then if test x"$aesnisupport" = xyes ; then # Build with the AES-NI/AVX2 implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx2-amd64.lo" fi fi fi LIST_MEMBER(idea, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS idea.lo" AC_DEFINE(USE_IDEA, 1, [Defined if this module should be included]) fi LIST_MEMBER(salsa20, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20.lo" AC_DEFINE(USE_SALSA20, 1, [Defined if this module should be included]) fi LIST_MEMBER(gost28147, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS gost28147.lo" AC_DEFINE(USE_GOST28147, 1, [Defined if this module should be included]) fi LIST_MEMBER(dsa, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo" AC_DEFINE(USE_DSA, 1, [Defined if this module should be included]) fi LIST_MEMBER(rsa, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS rsa.lo" AC_DEFINE(USE_RSA, 1, [Defined if this module should be included]) fi LIST_MEMBER(elgamal, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS elgamal.lo" AC_DEFINE(USE_ELGAMAL, 1, [Defined if this module should be included]) fi LIST_MEMBER(ecc, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \ ecc.lo ecc-curves.lo ecc-misc.lo" AC_DEFINE(USE_ECC, 1, [Defined if this module should be included]) fi LIST_MEMBER(crc, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo" AC_DEFINE(USE_CRC, 1, [Defined if this module should be included]) fi LIST_MEMBER(gostr3411-94, $enabled_digests) if test "$found" = "1" ; then # GOST R 34.11-94 internally uses GOST 28147-89 LIST_MEMBER(gost28147, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS gostr3411-94.lo" AC_DEFINE(USE_GOST_R_3411_94, 1, [Defined if this module should be included]) fi fi LIST_MEMBER(stribog, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS stribog.lo" AC_DEFINE(USE_GOST_R_3411_12, 1, [Defined if this module should be included]) fi LIST_MEMBER(md4, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS md4.lo" AC_DEFINE(USE_MD4, 1, [Defined if this module should be included]) fi LIST_MEMBER(md5, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS md5.lo" AC_DEFINE(USE_MD5, 1, [Defined if this module should be included]) fi LIST_MEMBER(sha256, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256.lo" AC_DEFINE(USE_SHA256, 1, [Defined if this module should be included]) fi LIST_MEMBER(sha512, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512.lo" AC_DEFINE(USE_SHA512, 1, [Defined if this module should be included]) if test x"$neonsupport" = xyes ; then # Build with the NEON implementation GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-armv7-neon.lo" fi fi LIST_MEMBER(tiger, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS tiger.lo" AC_DEFINE(USE_TIGER, 1, [Defined if this module should be included]) fi LIST_MEMBER(whirlpool, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool.lo" AC_DEFINE(USE_WHIRLPOOL, 1, [Defined if this module should be included]) fi # rmd160 and sha1 should be included always. GCRYPT_DIGESTS="$GCRYPT_DIGESTS rmd160.lo sha1.lo" AC_DEFINE(USE_RMD160, 1, [Defined if this module should be included]) AC_DEFINE(USE_SHA1, 1, [Defined if this module should be included]) LIST_MEMBER(scrypt, $enabled_kdfs) if test "$found" = "1" ; then GCRYPT_KDFS="$GCRYPT_KDFS scrypt.lo" AC_DEFINE(USE_SCRYPT, 1, [Defined if this module should be included]) fi LIST_MEMBER(linux, $random_modules) if test "$found" = "1" ; then GCRYPT_RANDOM="$GCRYPT_RANDOM rndlinux.lo" AC_DEFINE(USE_RNDLINUX, 1, [Defined if the /dev/random RNG should be used.]) fi LIST_MEMBER(unix, $random_modules) if test "$found" = "1" ; then GCRYPT_RANDOM="$GCRYPT_RANDOM rndunix.lo" AC_DEFINE(USE_RNDUNIX, 1, [Defined if the default Unix RNG should be used.]) print_egd_notice=yes fi LIST_MEMBER(egd, $random_modules) if test "$found" = "1" ; then GCRYPT_RANDOM="$GCRYPT_RANDOM rndegd.lo" AC_DEFINE(USE_RNDEGD, 1, [Defined if the EGD based RNG should be used.]) fi LIST_MEMBER(w32, $random_modules) if test "$found" = "1" ; then GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo" AC_DEFINE(USE_RNDW32, 1, [Defined if the Windows specific RNG should be used.]) fi LIST_MEMBER(w32ce, $random_modules) if test "$found" = "1" ; then GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32ce.lo" AC_DEFINE(USE_RNDW32CE, 1, [Defined if the WindowsCE specific RNG should be used.]) fi AC_SUBST([GCRYPT_CIPHERS]) AC_SUBST([GCRYPT_PUBKEY_CIPHERS]) AC_SUBST([GCRYPT_DIGESTS]) AC_SUBST([GCRYPT_KDFS]) AC_SUBST([GCRYPT_RANDOM]) AC_SUBST(LIBGCRYPT_CIPHERS, $enabled_ciphers) AC_SUBST(LIBGCRYPT_PUBKEY_CIPHERS, $enabled_pubkey_ciphers) AC_SUBST(LIBGCRYPT_DIGESTS, $enabled_digests) # For printing the configuration we need a colon separated list of # algorithm names. tmp=`echo "$enabled_ciphers" | tr ' ' : ` AC_DEFINE_UNQUOTED(LIBGCRYPT_CIPHERS, "$tmp", [List of available cipher algorithms]) tmp=`echo "$enabled_pubkey_ciphers" | tr ' ' : ` AC_DEFINE_UNQUOTED(LIBGCRYPT_PUBKEY_CIPHERS, "$tmp", [List of available public key cipher algorithms]) tmp=`echo "$enabled_digests" | tr ' ' : ` AC_DEFINE_UNQUOTED(LIBGCRYPT_DIGESTS, "$tmp", [List of available digest algorithms]) tmp=`echo "$enabled_kdfs" | tr ' ' : ` AC_DEFINE_UNQUOTED(LIBGCRYPT_KDFS, "$tmp", [List of available KDF algorithms]) # # Define conditional sources depending on the used hardware platform. # Note that all possible modules must also be listed in # src/Makefile.am (EXTRA_libgcrypt_la_SOURCES). # GCRYPT_HWF_MODULES= case "$mpi_cpu_arch" in x86) AC_DEFINE(HAVE_CPU_ARCH_X86, 1, [Defined for the x86 platforms]) GCRYPT_HWF_MODULES="hwf-x86.lo" ;; alpha) AC_DEFINE(HAVE_CPU_ARCH_ALPHA, 1, [Defined for Alpha platforms]) ;; sparc) AC_DEFINE(HAVE_CPU_ARCH_SPARC, 1, [Defined for SPARC platforms]) ;; mips) AC_DEFINE(HAVE_CPU_ARCH_MIPS, 1, [Defined for MIPS platforms]) ;; m68k) AC_DEFINE(HAVE_CPU_ARCH_M68K, 1, [Defined for M68k platforms]) ;; ppc) AC_DEFINE(HAVE_CPU_ARCH_PPC, 1, [Defined for PPC platforms]) ;; arm) AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM platforms]) GCRYPT_HWF_MODULES="hwf-arm.lo" ;; esac AC_SUBST([GCRYPT_HWF_MODULES]) # # Provide information about the build. # BUILD_REVISION="mym4_revision" AC_SUBST(BUILD_REVISION) AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION", [GIT commit id revision used to build this package]) changequote(,)dnl BUILD_FILEVERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./;s/\./,/g'` changequote([,])dnl BUILD_FILEVERSION="${BUILD_FILEVERSION}mym4_revision_dec" AC_SUBST(BUILD_FILEVERSION) BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date` AC_SUBST(BUILD_TIMESTAMP) AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP", [The time this package was configured for a build]) # And create the files. AC_CONFIG_FILES([ Makefile m4/Makefile compat/Makefile mpi/Makefile cipher/Makefile random/Makefile doc/Makefile src/Makefile src/gcrypt.h src/libgcrypt-config src/versioninfo.rc tests/Makefile ]) AC_OUTPUT detection_module="${GCRYPT_HWF_MODULES%.lo}" test -n "$detection_module" || detection_module="none" # Give some feedback GCRY_MSG_SHOW([],[]) GCRY_MSG_SHOW([Libgcrypt],[v${VERSION} has been configured as follows:]) GCRY_MSG_SHOW([],[]) GCRY_MSG_SHOW([Platform: ],[$PRINTABLE_OS_NAME ($host)]) GCRY_MSG_SHOW([Hardware detection module:],[$detection_module]) GCRY_MSG_WRAP([Enabled cipher algorithms:],[$enabled_ciphers]) GCRY_MSG_WRAP([Enabled digest algorithms:],[$enabled_digests]) GCRY_MSG_WRAP([Enabled kdf algorithms: ],[$enabled_kdfs]) GCRY_MSG_WRAP([Enabled pubkey algorithms:],[$enabled_pubkey_ciphers]) GCRY_MSG_SHOW([Random number generator: ],[$random]) GCRY_MSG_SHOW([Using linux capabilities: ],[$use_capabilities]) GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport]) GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport]) GCRY_MSG_SHOW([Try using DRNG (RDRAND): ],[$drngsupport]) GCRY_MSG_SHOW([Try using Intel AVX: ],[$avxsupport]) GCRY_MSG_SHOW([Try using Intel AVX2: ],[$avx2support]) GCRY_MSG_SHOW([Try using ARM NEON: ],[$neonsupport]) GCRY_MSG_SHOW([],[]) if test "$print_egd_notice" = "yes"; then cat <