From ca371a48b24a617b7439705f294dc1910c7c5a8a Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Tue, 30 Nov 2004 17:43:59 +0000 Subject: [PATCH] Incorporated LibTomCrypt code into rsaenh to get rid of OpenSSL dependencies. --- dlls/rsaenh/Makefile.in | 8 +- dlls/rsaenh/des.c | 1496 +++++++++++ dlls/rsaenh/implglue.c | 442 ++++ dlls/rsaenh/{implossl.h => implglue.h} | 54 +- dlls/rsaenh/implossl.c | 683 ----- dlls/rsaenh/md2.c | 151 ++ dlls/rsaenh/mpi.c | 4422 ++++++++++++++++++++++++++++++++ dlls/rsaenh/rc2.c | 203 ++ dlls/rsaenh/rc4.c | 108 + dlls/rsaenh/rsa.c | 246 ++ dlls/rsaenh/rsaenh.c | 15 +- dlls/rsaenh/tomcrypt.h | 618 +++++ 12 files changed, 7714 insertions(+), 732 deletions(-) create mode 100644 dlls/rsaenh/des.c create mode 100644 dlls/rsaenh/implglue.c rename dlls/rsaenh/{implossl.h => implglue.h} (80%) delete mode 100644 dlls/rsaenh/implossl.c create mode 100644 dlls/rsaenh/md2.c create mode 100644 dlls/rsaenh/mpi.c create mode 100644 dlls/rsaenh/rc2.c create mode 100644 dlls/rsaenh/rc4.c create mode 100644 dlls/rsaenh/rsa.c create mode 100644 dlls/rsaenh/tomcrypt.h diff --git a/dlls/rsaenh/Makefile.in b/dlls/rsaenh/Makefile.in index cea30329d5f..f0ab25af7a0 100644 --- a/dlls/rsaenh/Makefile.in +++ b/dlls/rsaenh/Makefile.in @@ -7,8 +7,14 @@ MODULE = rsaenh.dll IMPORTS = advapi32 kernel32 C_SRCS = \ + des.c \ handle.c \ - implossl.c \ + implglue.c \ + md2.c \ + mpi.c \ + rc2.c \ + rc4.c \ + rsa.c \ rsaenh.c SUBDIRS = tests diff --git a/dlls/rsaenh/des.c b/dlls/rsaenh/des.c new file mode 100644 index 00000000000..4898401b8a1 --- /dev/null +++ b/dlls/rsaenh/des.c @@ -0,0 +1,1496 @@ +/* + * dlls/rsaenh/des.c + * DES functions + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * and Dobes Vandermeer. + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#include "tomcrypt.h" + +#define EN0 0 +#define DE1 1 + +static const ulong32 bytebit[8] = +{ + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + +static const ulong32 bigbyte[24] = +{ + 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, + 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, + 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, + 0x800UL, 0x400UL, 0x200UL, 0x100UL, + 0x80UL, 0x40UL, 0x20UL, 0x10UL, + 0x8UL, 0x4UL, 0x2UL, 0x1L +}; + +/* Use the key schedule specific in the standard (ANSI X3.92-1981) */ + +static const unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 +}; + +static const unsigned char totrot[16] = { + 1, 2, 4, 6, + 8, 10, 12, 14, + 15, 17, 19, 21, + 23, 25, 27, 28 +}; + +static const unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 +}; + + +static const ulong32 SP1[64] = +{ + 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, + 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, + 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, + 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, + 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, + 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, + 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, + 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, + 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, + 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, + 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, + 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, + 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, + 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL +}; + +static const ulong32 SP2[64] = +{ + 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, + 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, + 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, + 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, + 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, + 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, + 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, + 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, + 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, + 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, + 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, + 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, + 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, + 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, + 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, + 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL +}; + +static const ulong32 SP3[64] = +{ + 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, + 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, + 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, + 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, + 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, + 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, + 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, + 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, + 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, + 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, + 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, + 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, + 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, + 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, + 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, + 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL +}; + +static const ulong32 SP4[64] = +{ + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, + 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, + 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, + 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, + 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, + 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, + 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, + 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, + 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL +}; + +static const ulong32 SP5[64] = +{ + 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, + 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, + 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, + 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, + 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, + 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, + 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, + 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, + 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, + 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, + 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, + 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, + 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, + 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, + 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, + 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL +}; + +static const ulong32 SP6[64] = +{ + 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, + 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, + 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, + 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, + 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, + 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, + 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, + 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, + 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, + 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, + 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, + 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, + 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, + 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL +}; + +static const ulong32 SP7[64] = +{ + 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, + 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, + 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, + 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, + 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, + 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, + 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, + 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, + 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, + 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, + 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, + 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, + 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, + 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, + 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, + 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL +}; + +static const ulong32 SP8[64] = +{ + 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, + 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, + 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, + 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, + 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, + 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, + 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, + 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, + 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, + 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, + 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, + 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, + 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, + 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, + 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, + 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL +}; + +static const ulong64 des_ip[8][256] = { + +{ CONST64(0x00000000,0x00000000), CONST64(0x00000010,0x00000000), CONST64(0x00000000,0x00000010), CONST64(0x00000010,0x00000010), + CONST64(0x00001000,0x00000000), CONST64(0x00001010,0x00000000), CONST64(0x00001000,0x00000010), CONST64(0x00001010,0x00000010), + CONST64(0x00000000,0x00001000), CONST64(0x00000010,0x00001000), CONST64(0x00000000,0x00001010), CONST64(0x00000010,0x00001010), + CONST64(0x00001000,0x00001000), CONST64(0x00001010,0x00001000), CONST64(0x00001000,0x00001010), CONST64(0x00001010,0x00001010), + CONST64(0x00100000,0x00000000), CONST64(0x00100010,0x00000000), CONST64(0x00100000,0x00000010), CONST64(0x00100010,0x00000010), + CONST64(0x00101000,0x00000000), CONST64(0x00101010,0x00000000), CONST64(0x00101000,0x00000010), CONST64(0x00101010,0x00000010), + CONST64(0x00100000,0x00001000), CONST64(0x00100010,0x00001000), CONST64(0x00100000,0x00001010), CONST64(0x00100010,0x00001010), + CONST64(0x00101000,0x00001000), CONST64(0x00101010,0x00001000), CONST64(0x00101000,0x00001010), CONST64(0x00101010,0x00001010), + CONST64(0x00000000,0x00100000), CONST64(0x00000010,0x00100000), CONST64(0x00000000,0x00100010), CONST64(0x00000010,0x00100010), + CONST64(0x00001000,0x00100000), CONST64(0x00001010,0x00100000), CONST64(0x00001000,0x00100010), CONST64(0x00001010,0x00100010), + CONST64(0x00000000,0x00101000), CONST64(0x00000010,0x00101000), CONST64(0x00000000,0x00101010), CONST64(0x00000010,0x00101010), + CONST64(0x00001000,0x00101000), CONST64(0x00001010,0x00101000), CONST64(0x00001000,0x00101010), CONST64(0x00001010,0x00101010), + CONST64(0x00100000,0x00100000), CONST64(0x00100010,0x00100000), CONST64(0x00100000,0x00100010), CONST64(0x00100010,0x00100010), + CONST64(0x00101000,0x00100000), CONST64(0x00101010,0x00100000), CONST64(0x00101000,0x00100010), CONST64(0x00101010,0x00100010), + CONST64(0x00100000,0x00101000), CONST64(0x00100010,0x00101000), CONST64(0x00100000,0x00101010), CONST64(0x00100010,0x00101010), + CONST64(0x00101000,0x00101000), CONST64(0x00101010,0x00101000), CONST64(0x00101000,0x00101010), CONST64(0x00101010,0x00101010), + CONST64(0x10000000,0x00000000), CONST64(0x10000010,0x00000000), CONST64(0x10000000,0x00000010), CONST64(0x10000010,0x00000010), + CONST64(0x10001000,0x00000000), CONST64(0x10001010,0x00000000), CONST64(0x10001000,0x00000010), CONST64(0x10001010,0x00000010), + CONST64(0x10000000,0x00001000), CONST64(0x10000010,0x00001000), CONST64(0x10000000,0x00001010), CONST64(0x10000010,0x00001010), + CONST64(0x10001000,0x00001000), CONST64(0x10001010,0x00001000), CONST64(0x10001000,0x00001010), CONST64(0x10001010,0x00001010), + CONST64(0x10100000,0x00000000), CONST64(0x10100010,0x00000000), CONST64(0x10100000,0x00000010), CONST64(0x10100010,0x00000010), + CONST64(0x10101000,0x00000000), CONST64(0x10101010,0x00000000), CONST64(0x10101000,0x00000010), CONST64(0x10101010,0x00000010), + CONST64(0x10100000,0x00001000), CONST64(0x10100010,0x00001000), CONST64(0x10100000,0x00001010), CONST64(0x10100010,0x00001010), + CONST64(0x10101000,0x00001000), CONST64(0x10101010,0x00001000), CONST64(0x10101000,0x00001010), CONST64(0x10101010,0x00001010), + CONST64(0x10000000,0x00100000), CONST64(0x10000010,0x00100000), CONST64(0x10000000,0x00100010), CONST64(0x10000010,0x00100010), + CONST64(0x10001000,0x00100000), CONST64(0x10001010,0x00100000), CONST64(0x10001000,0x00100010), CONST64(0x10001010,0x00100010), + CONST64(0x10000000,0x00101000), CONST64(0x10000010,0x00101000), CONST64(0x10000000,0x00101010), CONST64(0x10000010,0x00101010), + CONST64(0x10001000,0x00101000), CONST64(0x10001010,0x00101000), CONST64(0x10001000,0x00101010), CONST64(0x10001010,0x00101010), + CONST64(0x10100000,0x00100000), CONST64(0x10100010,0x00100000), CONST64(0x10100000,0x00100010), CONST64(0x10100010,0x00100010), + CONST64(0x10101000,0x00100000), CONST64(0x10101010,0x00100000), CONST64(0x10101000,0x00100010), CONST64(0x10101010,0x00100010), + CONST64(0x10100000,0x00101000), CONST64(0x10100010,0x00101000), CONST64(0x10100000,0x00101010), CONST64(0x10100010,0x00101010), + CONST64(0x10101000,0x00101000), CONST64(0x10101010,0x00101000), CONST64(0x10101000,0x00101010), CONST64(0x10101010,0x00101010), + CONST64(0x00000000,0x10000000), CONST64(0x00000010,0x10000000), CONST64(0x00000000,0x10000010), CONST64(0x00000010,0x10000010), + CONST64(0x00001000,0x10000000), CONST64(0x00001010,0x10000000), CONST64(0x00001000,0x10000010), CONST64(0x00001010,0x10000010), + CONST64(0x00000000,0x10001000), CONST64(0x00000010,0x10001000), CONST64(0x00000000,0x10001010), CONST64(0x00000010,0x10001010), + CONST64(0x00001000,0x10001000), CONST64(0x00001010,0x10001000), CONST64(0x00001000,0x10001010), CONST64(0x00001010,0x10001010), + CONST64(0x00100000,0x10000000), CONST64(0x00100010,0x10000000), CONST64(0x00100000,0x10000010), CONST64(0x00100010,0x10000010), + CONST64(0x00101000,0x10000000), CONST64(0x00101010,0x10000000), CONST64(0x00101000,0x10000010), CONST64(0x00101010,0x10000010), + CONST64(0x00100000,0x10001000), CONST64(0x00100010,0x10001000), CONST64(0x00100000,0x10001010), CONST64(0x00100010,0x10001010), + CONST64(0x00101000,0x10001000), CONST64(0x00101010,0x10001000), CONST64(0x00101000,0x10001010), CONST64(0x00101010,0x10001010), + CONST64(0x00000000,0x10100000), CONST64(0x00000010,0x10100000), CONST64(0x00000000,0x10100010), CONST64(0x00000010,0x10100010), + CONST64(0x00001000,0x10100000), CONST64(0x00001010,0x10100000), CONST64(0x00001000,0x10100010), CONST64(0x00001010,0x10100010), + CONST64(0x00000000,0x10101000), CONST64(0x00000010,0x10101000), CONST64(0x00000000,0x10101010), CONST64(0x00000010,0x10101010), + CONST64(0x00001000,0x10101000), CONST64(0x00001010,0x10101000), CONST64(0x00001000,0x10101010), CONST64(0x00001010,0x10101010), + CONST64(0x00100000,0x10100000), CONST64(0x00100010,0x10100000), CONST64(0x00100000,0x10100010), CONST64(0x00100010,0x10100010), + CONST64(0x00101000,0x10100000), CONST64(0x00101010,0x10100000), CONST64(0x00101000,0x10100010), CONST64(0x00101010,0x10100010), + CONST64(0x00100000,0x10101000), CONST64(0x00100010,0x10101000), CONST64(0x00100000,0x10101010), CONST64(0x00100010,0x10101010), + CONST64(0x00101000,0x10101000), CONST64(0x00101010,0x10101000), CONST64(0x00101000,0x10101010), CONST64(0x00101010,0x10101010), + CONST64(0x10000000,0x10000000), CONST64(0x10000010,0x10000000), CONST64(0x10000000,0x10000010), CONST64(0x10000010,0x10000010), + CONST64(0x10001000,0x10000000), CONST64(0x10001010,0x10000000), CONST64(0x10001000,0x10000010), CONST64(0x10001010,0x10000010), + CONST64(0x10000000,0x10001000), CONST64(0x10000010,0x10001000), CONST64(0x10000000,0x10001010), CONST64(0x10000010,0x10001010), + CONST64(0x10001000,0x10001000), CONST64(0x10001010,0x10001000), CONST64(0x10001000,0x10001010), CONST64(0x10001010,0x10001010), + CONST64(0x10100000,0x10000000), CONST64(0x10100010,0x10000000), CONST64(0x10100000,0x10000010), CONST64(0x10100010,0x10000010), + CONST64(0x10101000,0x10000000), CONST64(0x10101010,0x10000000), CONST64(0x10101000,0x10000010), CONST64(0x10101010,0x10000010), + CONST64(0x10100000,0x10001000), CONST64(0x10100010,0x10001000), CONST64(0x10100000,0x10001010), CONST64(0x10100010,0x10001010), + CONST64(0x10101000,0x10001000), CONST64(0x10101010,0x10001000), CONST64(0x10101000,0x10001010), CONST64(0x10101010,0x10001010), + CONST64(0x10000000,0x10100000), CONST64(0x10000010,0x10100000), CONST64(0x10000000,0x10100010), CONST64(0x10000010,0x10100010), + CONST64(0x10001000,0x10100000), CONST64(0x10001010,0x10100000), CONST64(0x10001000,0x10100010), CONST64(0x10001010,0x10100010), + CONST64(0x10000000,0x10101000), CONST64(0x10000010,0x10101000), CONST64(0x10000000,0x10101010), CONST64(0x10000010,0x10101010), + CONST64(0x10001000,0x10101000), CONST64(0x10001010,0x10101000), CONST64(0x10001000,0x10101010), CONST64(0x10001010,0x10101010), + CONST64(0x10100000,0x10100000), CONST64(0x10100010,0x10100000), CONST64(0x10100000,0x10100010), CONST64(0x10100010,0x10100010), + CONST64(0x10101000,0x10100000), CONST64(0x10101010,0x10100000), CONST64(0x10101000,0x10100010), CONST64(0x10101010,0x10100010), + CONST64(0x10100000,0x10101000), CONST64(0x10100010,0x10101000), CONST64(0x10100000,0x10101010), CONST64(0x10100010,0x10101010), + CONST64(0x10101000,0x10101000), CONST64(0x10101010,0x10101000), CONST64(0x10101000,0x10101010), CONST64(0x10101010,0x10101010) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000008,0x00000000), CONST64(0x00000000,0x00000008), CONST64(0x00000008,0x00000008), + CONST64(0x00000800,0x00000000), CONST64(0x00000808,0x00000000), CONST64(0x00000800,0x00000008), CONST64(0x00000808,0x00000008), + CONST64(0x00000000,0x00000800), CONST64(0x00000008,0x00000800), CONST64(0x00000000,0x00000808), CONST64(0x00000008,0x00000808), + CONST64(0x00000800,0x00000800), CONST64(0x00000808,0x00000800), CONST64(0x00000800,0x00000808), CONST64(0x00000808,0x00000808), + CONST64(0x00080000,0x00000000), CONST64(0x00080008,0x00000000), CONST64(0x00080000,0x00000008), CONST64(0x00080008,0x00000008), + CONST64(0x00080800,0x00000000), CONST64(0x00080808,0x00000000), CONST64(0x00080800,0x00000008), CONST64(0x00080808,0x00000008), + CONST64(0x00080000,0x00000800), CONST64(0x00080008,0x00000800), CONST64(0x00080000,0x00000808), CONST64(0x00080008,0x00000808), + CONST64(0x00080800,0x00000800), CONST64(0x00080808,0x00000800), CONST64(0x00080800,0x00000808), CONST64(0x00080808,0x00000808), + CONST64(0x00000000,0x00080000), CONST64(0x00000008,0x00080000), CONST64(0x00000000,0x00080008), CONST64(0x00000008,0x00080008), + CONST64(0x00000800,0x00080000), CONST64(0x00000808,0x00080000), CONST64(0x00000800,0x00080008), CONST64(0x00000808,0x00080008), + CONST64(0x00000000,0x00080800), CONST64(0x00000008,0x00080800), CONST64(0x00000000,0x00080808), CONST64(0x00000008,0x00080808), + CONST64(0x00000800,0x00080800), CONST64(0x00000808,0x00080800), CONST64(0x00000800,0x00080808), CONST64(0x00000808,0x00080808), + CONST64(0x00080000,0x00080000), CONST64(0x00080008,0x00080000), CONST64(0x00080000,0x00080008), CONST64(0x00080008,0x00080008), + CONST64(0x00080800,0x00080000), CONST64(0x00080808,0x00080000), CONST64(0x00080800,0x00080008), CONST64(0x00080808,0x00080008), + CONST64(0x00080000,0x00080800), CONST64(0x00080008,0x00080800), CONST64(0x00080000,0x00080808), CONST64(0x00080008,0x00080808), + CONST64(0x00080800,0x00080800), CONST64(0x00080808,0x00080800), CONST64(0x00080800,0x00080808), CONST64(0x00080808,0x00080808), + CONST64(0x08000000,0x00000000), CONST64(0x08000008,0x00000000), CONST64(0x08000000,0x00000008), CONST64(0x08000008,0x00000008), + CONST64(0x08000800,0x00000000), CONST64(0x08000808,0x00000000), CONST64(0x08000800,0x00000008), CONST64(0x08000808,0x00000008), + CONST64(0x08000000,0x00000800), CONST64(0x08000008,0x00000800), CONST64(0x08000000,0x00000808), CONST64(0x08000008,0x00000808), + CONST64(0x08000800,0x00000800), CONST64(0x08000808,0x00000800), CONST64(0x08000800,0x00000808), CONST64(0x08000808,0x00000808), + CONST64(0x08080000,0x00000000), CONST64(0x08080008,0x00000000), CONST64(0x08080000,0x00000008), CONST64(0x08080008,0x00000008), + CONST64(0x08080800,0x00000000), CONST64(0x08080808,0x00000000), CONST64(0x08080800,0x00000008), CONST64(0x08080808,0x00000008), + CONST64(0x08080000,0x00000800), CONST64(0x08080008,0x00000800), CONST64(0x08080000,0x00000808), CONST64(0x08080008,0x00000808), + CONST64(0x08080800,0x00000800), CONST64(0x08080808,0x00000800), CONST64(0x08080800,0x00000808), CONST64(0x08080808,0x00000808), + CONST64(0x08000000,0x00080000), CONST64(0x08000008,0x00080000), CONST64(0x08000000,0x00080008), CONST64(0x08000008,0x00080008), + CONST64(0x08000800,0x00080000), CONST64(0x08000808,0x00080000), CONST64(0x08000800,0x00080008), CONST64(0x08000808,0x00080008), + CONST64(0x08000000,0x00080800), CONST64(0x08000008,0x00080800), CONST64(0x08000000,0x00080808), CONST64(0x08000008,0x00080808), + CONST64(0x08000800,0x00080800), CONST64(0x08000808,0x00080800), CONST64(0x08000800,0x00080808), CONST64(0x08000808,0x00080808), + CONST64(0x08080000,0x00080000), CONST64(0x08080008,0x00080000), CONST64(0x08080000,0x00080008), CONST64(0x08080008,0x00080008), + CONST64(0x08080800,0x00080000), CONST64(0x08080808,0x00080000), CONST64(0x08080800,0x00080008), CONST64(0x08080808,0x00080008), + CONST64(0x08080000,0x00080800), CONST64(0x08080008,0x00080800), CONST64(0x08080000,0x00080808), CONST64(0x08080008,0x00080808), + CONST64(0x08080800,0x00080800), CONST64(0x08080808,0x00080800), CONST64(0x08080800,0x00080808), CONST64(0x08080808,0x00080808), + CONST64(0x00000000,0x08000000), CONST64(0x00000008,0x08000000), CONST64(0x00000000,0x08000008), CONST64(0x00000008,0x08000008), + CONST64(0x00000800,0x08000000), CONST64(0x00000808,0x08000000), CONST64(0x00000800,0x08000008), CONST64(0x00000808,0x08000008), + CONST64(0x00000000,0x08000800), CONST64(0x00000008,0x08000800), CONST64(0x00000000,0x08000808), CONST64(0x00000008,0x08000808), + CONST64(0x00000800,0x08000800), CONST64(0x00000808,0x08000800), CONST64(0x00000800,0x08000808), CONST64(0x00000808,0x08000808), + CONST64(0x00080000,0x08000000), CONST64(0x00080008,0x08000000), CONST64(0x00080000,0x08000008), CONST64(0x00080008,0x08000008), + CONST64(0x00080800,0x08000000), CONST64(0x00080808,0x08000000), CONST64(0x00080800,0x08000008), CONST64(0x00080808,0x08000008), + CONST64(0x00080000,0x08000800), CONST64(0x00080008,0x08000800), CONST64(0x00080000,0x08000808), CONST64(0x00080008,0x08000808), + CONST64(0x00080800,0x08000800), CONST64(0x00080808,0x08000800), CONST64(0x00080800,0x08000808), CONST64(0x00080808,0x08000808), + CONST64(0x00000000,0x08080000), CONST64(0x00000008,0x08080000), CONST64(0x00000000,0x08080008), CONST64(0x00000008,0x08080008), + CONST64(0x00000800,0x08080000), CONST64(0x00000808,0x08080000), CONST64(0x00000800,0x08080008), CONST64(0x00000808,0x08080008), + CONST64(0x00000000,0x08080800), CONST64(0x00000008,0x08080800), CONST64(0x00000000,0x08080808), CONST64(0x00000008,0x08080808), + CONST64(0x00000800,0x08080800), CONST64(0x00000808,0x08080800), CONST64(0x00000800,0x08080808), CONST64(0x00000808,0x08080808), + CONST64(0x00080000,0x08080000), CONST64(0x00080008,0x08080000), CONST64(0x00080000,0x08080008), CONST64(0x00080008,0x08080008), + CONST64(0x00080800,0x08080000), CONST64(0x00080808,0x08080000), CONST64(0x00080800,0x08080008), CONST64(0x00080808,0x08080008), + CONST64(0x00080000,0x08080800), CONST64(0x00080008,0x08080800), CONST64(0x00080000,0x08080808), CONST64(0x00080008,0x08080808), + CONST64(0x00080800,0x08080800), CONST64(0x00080808,0x08080800), CONST64(0x00080800,0x08080808), CONST64(0x00080808,0x08080808), + CONST64(0x08000000,0x08000000), CONST64(0x08000008,0x08000000), CONST64(0x08000000,0x08000008), CONST64(0x08000008,0x08000008), + CONST64(0x08000800,0x08000000), CONST64(0x08000808,0x08000000), CONST64(0x08000800,0x08000008), CONST64(0x08000808,0x08000008), + CONST64(0x08000000,0x08000800), CONST64(0x08000008,0x08000800), CONST64(0x08000000,0x08000808), CONST64(0x08000008,0x08000808), + CONST64(0x08000800,0x08000800), CONST64(0x08000808,0x08000800), CONST64(0x08000800,0x08000808), CONST64(0x08000808,0x08000808), + CONST64(0x08080000,0x08000000), CONST64(0x08080008,0x08000000), CONST64(0x08080000,0x08000008), CONST64(0x08080008,0x08000008), + CONST64(0x08080800,0x08000000), CONST64(0x08080808,0x08000000), CONST64(0x08080800,0x08000008), CONST64(0x08080808,0x08000008), + CONST64(0x08080000,0x08000800), CONST64(0x08080008,0x08000800), CONST64(0x08080000,0x08000808), CONST64(0x08080008,0x08000808), + CONST64(0x08080800,0x08000800), CONST64(0x08080808,0x08000800), CONST64(0x08080800,0x08000808), CONST64(0x08080808,0x08000808), + CONST64(0x08000000,0x08080000), CONST64(0x08000008,0x08080000), CONST64(0x08000000,0x08080008), CONST64(0x08000008,0x08080008), + CONST64(0x08000800,0x08080000), CONST64(0x08000808,0x08080000), CONST64(0x08000800,0x08080008), CONST64(0x08000808,0x08080008), + CONST64(0x08000000,0x08080800), CONST64(0x08000008,0x08080800), CONST64(0x08000000,0x08080808), CONST64(0x08000008,0x08080808), + CONST64(0x08000800,0x08080800), CONST64(0x08000808,0x08080800), CONST64(0x08000800,0x08080808), CONST64(0x08000808,0x08080808), + CONST64(0x08080000,0x08080000), CONST64(0x08080008,0x08080000), CONST64(0x08080000,0x08080008), CONST64(0x08080008,0x08080008), + CONST64(0x08080800,0x08080000), CONST64(0x08080808,0x08080000), CONST64(0x08080800,0x08080008), CONST64(0x08080808,0x08080008), + CONST64(0x08080000,0x08080800), CONST64(0x08080008,0x08080800), CONST64(0x08080000,0x08080808), CONST64(0x08080008,0x08080808), + CONST64(0x08080800,0x08080800), CONST64(0x08080808,0x08080800), CONST64(0x08080800,0x08080808), CONST64(0x08080808,0x08080808) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000004,0x00000000), CONST64(0x00000000,0x00000004), CONST64(0x00000004,0x00000004), + CONST64(0x00000400,0x00000000), CONST64(0x00000404,0x00000000), CONST64(0x00000400,0x00000004), CONST64(0x00000404,0x00000004), + CONST64(0x00000000,0x00000400), CONST64(0x00000004,0x00000400), CONST64(0x00000000,0x00000404), CONST64(0x00000004,0x00000404), + CONST64(0x00000400,0x00000400), CONST64(0x00000404,0x00000400), CONST64(0x00000400,0x00000404), CONST64(0x00000404,0x00000404), + CONST64(0x00040000,0x00000000), CONST64(0x00040004,0x00000000), CONST64(0x00040000,0x00000004), CONST64(0x00040004,0x00000004), + CONST64(0x00040400,0x00000000), CONST64(0x00040404,0x00000000), CONST64(0x00040400,0x00000004), CONST64(0x00040404,0x00000004), + CONST64(0x00040000,0x00000400), CONST64(0x00040004,0x00000400), CONST64(0x00040000,0x00000404), CONST64(0x00040004,0x00000404), + CONST64(0x00040400,0x00000400), CONST64(0x00040404,0x00000400), CONST64(0x00040400,0x00000404), CONST64(0x00040404,0x00000404), + CONST64(0x00000000,0x00040000), CONST64(0x00000004,0x00040000), CONST64(0x00000000,0x00040004), CONST64(0x00000004,0x00040004), + CONST64(0x00000400,0x00040000), CONST64(0x00000404,0x00040000), CONST64(0x00000400,0x00040004), CONST64(0x00000404,0x00040004), + CONST64(0x00000000,0x00040400), CONST64(0x00000004,0x00040400), CONST64(0x00000000,0x00040404), CONST64(0x00000004,0x00040404), + CONST64(0x00000400,0x00040400), CONST64(0x00000404,0x00040400), CONST64(0x00000400,0x00040404), CONST64(0x00000404,0x00040404), + CONST64(0x00040000,0x00040000), CONST64(0x00040004,0x00040000), CONST64(0x00040000,0x00040004), CONST64(0x00040004,0x00040004), + CONST64(0x00040400,0x00040000), CONST64(0x00040404,0x00040000), CONST64(0x00040400,0x00040004), CONST64(0x00040404,0x00040004), + CONST64(0x00040000,0x00040400), CONST64(0x00040004,0x00040400), CONST64(0x00040000,0x00040404), CONST64(0x00040004,0x00040404), + CONST64(0x00040400,0x00040400), CONST64(0x00040404,0x00040400), CONST64(0x00040400,0x00040404), CONST64(0x00040404,0x00040404), + CONST64(0x04000000,0x00000000), CONST64(0x04000004,0x00000000), CONST64(0x04000000,0x00000004), CONST64(0x04000004,0x00000004), + CONST64(0x04000400,0x00000000), CONST64(0x04000404,0x00000000), CONST64(0x04000400,0x00000004), CONST64(0x04000404,0x00000004), + CONST64(0x04000000,0x00000400), CONST64(0x04000004,0x00000400), CONST64(0x04000000,0x00000404), CONST64(0x04000004,0x00000404), + CONST64(0x04000400,0x00000400), CONST64(0x04000404,0x00000400), CONST64(0x04000400,0x00000404), CONST64(0x04000404,0x00000404), + CONST64(0x04040000,0x00000000), CONST64(0x04040004,0x00000000), CONST64(0x04040000,0x00000004), CONST64(0x04040004,0x00000004), + CONST64(0x04040400,0x00000000), CONST64(0x04040404,0x00000000), CONST64(0x04040400,0x00000004), CONST64(0x04040404,0x00000004), + CONST64(0x04040000,0x00000400), CONST64(0x04040004,0x00000400), CONST64(0x04040000,0x00000404), CONST64(0x04040004,0x00000404), + CONST64(0x04040400,0x00000400), CONST64(0x04040404,0x00000400), CONST64(0x04040400,0x00000404), CONST64(0x04040404,0x00000404), + CONST64(0x04000000,0x00040000), CONST64(0x04000004,0x00040000), CONST64(0x04000000,0x00040004), CONST64(0x04000004,0x00040004), + CONST64(0x04000400,0x00040000), CONST64(0x04000404,0x00040000), CONST64(0x04000400,0x00040004), CONST64(0x04000404,0x00040004), + CONST64(0x04000000,0x00040400), CONST64(0x04000004,0x00040400), CONST64(0x04000000,0x00040404), CONST64(0x04000004,0x00040404), + CONST64(0x04000400,0x00040400), CONST64(0x04000404,0x00040400), CONST64(0x04000400,0x00040404), CONST64(0x04000404,0x00040404), + CONST64(0x04040000,0x00040000), CONST64(0x04040004,0x00040000), CONST64(0x04040000,0x00040004), CONST64(0x04040004,0x00040004), + CONST64(0x04040400,0x00040000), CONST64(0x04040404,0x00040000), CONST64(0x04040400,0x00040004), CONST64(0x04040404,0x00040004), + CONST64(0x04040000,0x00040400), CONST64(0x04040004,0x00040400), CONST64(0x04040000,0x00040404), CONST64(0x04040004,0x00040404), + CONST64(0x04040400,0x00040400), CONST64(0x04040404,0x00040400), CONST64(0x04040400,0x00040404), CONST64(0x04040404,0x00040404), + CONST64(0x00000000,0x04000000), CONST64(0x00000004,0x04000000), CONST64(0x00000000,0x04000004), CONST64(0x00000004,0x04000004), + CONST64(0x00000400,0x04000000), CONST64(0x00000404,0x04000000), CONST64(0x00000400,0x04000004), CONST64(0x00000404,0x04000004), + CONST64(0x00000000,0x04000400), CONST64(0x00000004,0x04000400), CONST64(0x00000000,0x04000404), CONST64(0x00000004,0x04000404), + CONST64(0x00000400,0x04000400), CONST64(0x00000404,0x04000400), CONST64(0x00000400,0x04000404), CONST64(0x00000404,0x04000404), + CONST64(0x00040000,0x04000000), CONST64(0x00040004,0x04000000), CONST64(0x00040000,0x04000004), CONST64(0x00040004,0x04000004), + CONST64(0x00040400,0x04000000), CONST64(0x00040404,0x04000000), CONST64(0x00040400,0x04000004), CONST64(0x00040404,0x04000004), + CONST64(0x00040000,0x04000400), CONST64(0x00040004,0x04000400), CONST64(0x00040000,0x04000404), CONST64(0x00040004,0x04000404), + CONST64(0x00040400,0x04000400), CONST64(0x00040404,0x04000400), CONST64(0x00040400,0x04000404), CONST64(0x00040404,0x04000404), + CONST64(0x00000000,0x04040000), CONST64(0x00000004,0x04040000), CONST64(0x00000000,0x04040004), CONST64(0x00000004,0x04040004), + CONST64(0x00000400,0x04040000), CONST64(0x00000404,0x04040000), CONST64(0x00000400,0x04040004), CONST64(0x00000404,0x04040004), + CONST64(0x00000000,0x04040400), CONST64(0x00000004,0x04040400), CONST64(0x00000000,0x04040404), CONST64(0x00000004,0x04040404), + CONST64(0x00000400,0x04040400), CONST64(0x00000404,0x04040400), CONST64(0x00000400,0x04040404), CONST64(0x00000404,0x04040404), + CONST64(0x00040000,0x04040000), CONST64(0x00040004,0x04040000), CONST64(0x00040000,0x04040004), CONST64(0x00040004,0x04040004), + CONST64(0x00040400,0x04040000), CONST64(0x00040404,0x04040000), CONST64(0x00040400,0x04040004), CONST64(0x00040404,0x04040004), + CONST64(0x00040000,0x04040400), CONST64(0x00040004,0x04040400), CONST64(0x00040000,0x04040404), CONST64(0x00040004,0x04040404), + CONST64(0x00040400,0x04040400), CONST64(0x00040404,0x04040400), CONST64(0x00040400,0x04040404), CONST64(0x00040404,0x04040404), + CONST64(0x04000000,0x04000000), CONST64(0x04000004,0x04000000), CONST64(0x04000000,0x04000004), CONST64(0x04000004,0x04000004), + CONST64(0x04000400,0x04000000), CONST64(0x04000404,0x04000000), CONST64(0x04000400,0x04000004), CONST64(0x04000404,0x04000004), + CONST64(0x04000000,0x04000400), CONST64(0x04000004,0x04000400), CONST64(0x04000000,0x04000404), CONST64(0x04000004,0x04000404), + CONST64(0x04000400,0x04000400), CONST64(0x04000404,0x04000400), CONST64(0x04000400,0x04000404), CONST64(0x04000404,0x04000404), + CONST64(0x04040000,0x04000000), CONST64(0x04040004,0x04000000), CONST64(0x04040000,0x04000004), CONST64(0x04040004,0x04000004), + CONST64(0x04040400,0x04000000), CONST64(0x04040404,0x04000000), CONST64(0x04040400,0x04000004), CONST64(0x04040404,0x04000004), + CONST64(0x04040000,0x04000400), CONST64(0x04040004,0x04000400), CONST64(0x04040000,0x04000404), CONST64(0x04040004,0x04000404), + CONST64(0x04040400,0x04000400), CONST64(0x04040404,0x04000400), CONST64(0x04040400,0x04000404), CONST64(0x04040404,0x04000404), + CONST64(0x04000000,0x04040000), CONST64(0x04000004,0x04040000), CONST64(0x04000000,0x04040004), CONST64(0x04000004,0x04040004), + CONST64(0x04000400,0x04040000), CONST64(0x04000404,0x04040000), CONST64(0x04000400,0x04040004), CONST64(0x04000404,0x04040004), + CONST64(0x04000000,0x04040400), CONST64(0x04000004,0x04040400), CONST64(0x04000000,0x04040404), CONST64(0x04000004,0x04040404), + CONST64(0x04000400,0x04040400), CONST64(0x04000404,0x04040400), CONST64(0x04000400,0x04040404), CONST64(0x04000404,0x04040404), + CONST64(0x04040000,0x04040000), CONST64(0x04040004,0x04040000), CONST64(0x04040000,0x04040004), CONST64(0x04040004,0x04040004), + CONST64(0x04040400,0x04040000), CONST64(0x04040404,0x04040000), CONST64(0x04040400,0x04040004), CONST64(0x04040404,0x04040004), + CONST64(0x04040000,0x04040400), CONST64(0x04040004,0x04040400), CONST64(0x04040000,0x04040404), CONST64(0x04040004,0x04040404), + CONST64(0x04040400,0x04040400), CONST64(0x04040404,0x04040400), CONST64(0x04040400,0x04040404), CONST64(0x04040404,0x04040404) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000002,0x00000000), CONST64(0x00000000,0x00000002), CONST64(0x00000002,0x00000002), + CONST64(0x00000200,0x00000000), CONST64(0x00000202,0x00000000), CONST64(0x00000200,0x00000002), CONST64(0x00000202,0x00000002), + CONST64(0x00000000,0x00000200), CONST64(0x00000002,0x00000200), CONST64(0x00000000,0x00000202), CONST64(0x00000002,0x00000202), + CONST64(0x00000200,0x00000200), CONST64(0x00000202,0x00000200), CONST64(0x00000200,0x00000202), CONST64(0x00000202,0x00000202), + CONST64(0x00020000,0x00000000), CONST64(0x00020002,0x00000000), CONST64(0x00020000,0x00000002), CONST64(0x00020002,0x00000002), + CONST64(0x00020200,0x00000000), CONST64(0x00020202,0x00000000), CONST64(0x00020200,0x00000002), CONST64(0x00020202,0x00000002), + CONST64(0x00020000,0x00000200), CONST64(0x00020002,0x00000200), CONST64(0x00020000,0x00000202), CONST64(0x00020002,0x00000202), + CONST64(0x00020200,0x00000200), CONST64(0x00020202,0x00000200), CONST64(0x00020200,0x00000202), CONST64(0x00020202,0x00000202), + CONST64(0x00000000,0x00020000), CONST64(0x00000002,0x00020000), CONST64(0x00000000,0x00020002), CONST64(0x00000002,0x00020002), + CONST64(0x00000200,0x00020000), CONST64(0x00000202,0x00020000), CONST64(0x00000200,0x00020002), CONST64(0x00000202,0x00020002), + CONST64(0x00000000,0x00020200), CONST64(0x00000002,0x00020200), CONST64(0x00000000,0x00020202), CONST64(0x00000002,0x00020202), + CONST64(0x00000200,0x00020200), CONST64(0x00000202,0x00020200), CONST64(0x00000200,0x00020202), CONST64(0x00000202,0x00020202), + CONST64(0x00020000,0x00020000), CONST64(0x00020002,0x00020000), CONST64(0x00020000,0x00020002), CONST64(0x00020002,0x00020002), + CONST64(0x00020200,0x00020000), CONST64(0x00020202,0x00020000), CONST64(0x00020200,0x00020002), CONST64(0x00020202,0x00020002), + CONST64(0x00020000,0x00020200), CONST64(0x00020002,0x00020200), CONST64(0x00020000,0x00020202), CONST64(0x00020002,0x00020202), + CONST64(0x00020200,0x00020200), CONST64(0x00020202,0x00020200), CONST64(0x00020200,0x00020202), CONST64(0x00020202,0x00020202), + CONST64(0x02000000,0x00000000), CONST64(0x02000002,0x00000000), CONST64(0x02000000,0x00000002), CONST64(0x02000002,0x00000002), + CONST64(0x02000200,0x00000000), CONST64(0x02000202,0x00000000), CONST64(0x02000200,0x00000002), CONST64(0x02000202,0x00000002), + CONST64(0x02000000,0x00000200), CONST64(0x02000002,0x00000200), CONST64(0x02000000,0x00000202), CONST64(0x02000002,0x00000202), + CONST64(0x02000200,0x00000200), CONST64(0x02000202,0x00000200), CONST64(0x02000200,0x00000202), CONST64(0x02000202,0x00000202), + CONST64(0x02020000,0x00000000), CONST64(0x02020002,0x00000000), CONST64(0x02020000,0x00000002), CONST64(0x02020002,0x00000002), + CONST64(0x02020200,0x00000000), CONST64(0x02020202,0x00000000), CONST64(0x02020200,0x00000002), CONST64(0x02020202,0x00000002), + CONST64(0x02020000,0x00000200), CONST64(0x02020002,0x00000200), CONST64(0x02020000,0x00000202), CONST64(0x02020002,0x00000202), + CONST64(0x02020200,0x00000200), CONST64(0x02020202,0x00000200), CONST64(0x02020200,0x00000202), CONST64(0x02020202,0x00000202), + CONST64(0x02000000,0x00020000), CONST64(0x02000002,0x00020000), CONST64(0x02000000,0x00020002), CONST64(0x02000002,0x00020002), + CONST64(0x02000200,0x00020000), CONST64(0x02000202,0x00020000), CONST64(0x02000200,0x00020002), CONST64(0x02000202,0x00020002), + CONST64(0x02000000,0x00020200), CONST64(0x02000002,0x00020200), CONST64(0x02000000,0x00020202), CONST64(0x02000002,0x00020202), + CONST64(0x02000200,0x00020200), CONST64(0x02000202,0x00020200), CONST64(0x02000200,0x00020202), CONST64(0x02000202,0x00020202), + CONST64(0x02020000,0x00020000), CONST64(0x02020002,0x00020000), CONST64(0x02020000,0x00020002), CONST64(0x02020002,0x00020002), + CONST64(0x02020200,0x00020000), CONST64(0x02020202,0x00020000), CONST64(0x02020200,0x00020002), CONST64(0x02020202,0x00020002), + CONST64(0x02020000,0x00020200), CONST64(0x02020002,0x00020200), CONST64(0x02020000,0x00020202), CONST64(0x02020002,0x00020202), + CONST64(0x02020200,0x00020200), CONST64(0x02020202,0x00020200), CONST64(0x02020200,0x00020202), CONST64(0x02020202,0x00020202), + CONST64(0x00000000,0x02000000), CONST64(0x00000002,0x02000000), CONST64(0x00000000,0x02000002), CONST64(0x00000002,0x02000002), + CONST64(0x00000200,0x02000000), CONST64(0x00000202,0x02000000), CONST64(0x00000200,0x02000002), CONST64(0x00000202,0x02000002), + CONST64(0x00000000,0x02000200), CONST64(0x00000002,0x02000200), CONST64(0x00000000,0x02000202), CONST64(0x00000002,0x02000202), + CONST64(0x00000200,0x02000200), CONST64(0x00000202,0x02000200), CONST64(0x00000200,0x02000202), CONST64(0x00000202,0x02000202), + CONST64(0x00020000,0x02000000), CONST64(0x00020002,0x02000000), CONST64(0x00020000,0x02000002), CONST64(0x00020002,0x02000002), + CONST64(0x00020200,0x02000000), CONST64(0x00020202,0x02000000), CONST64(0x00020200,0x02000002), CONST64(0x00020202,0x02000002), + CONST64(0x00020000,0x02000200), CONST64(0x00020002,0x02000200), CONST64(0x00020000,0x02000202), CONST64(0x00020002,0x02000202), + CONST64(0x00020200,0x02000200), CONST64(0x00020202,0x02000200), CONST64(0x00020200,0x02000202), CONST64(0x00020202,0x02000202), + CONST64(0x00000000,0x02020000), CONST64(0x00000002,0x02020000), CONST64(0x00000000,0x02020002), CONST64(0x00000002,0x02020002), + CONST64(0x00000200,0x02020000), CONST64(0x00000202,0x02020000), CONST64(0x00000200,0x02020002), CONST64(0x00000202,0x02020002), + CONST64(0x00000000,0x02020200), CONST64(0x00000002,0x02020200), CONST64(0x00000000,0x02020202), CONST64(0x00000002,0x02020202), + CONST64(0x00000200,0x02020200), CONST64(0x00000202,0x02020200), CONST64(0x00000200,0x02020202), CONST64(0x00000202,0x02020202), + CONST64(0x00020000,0x02020000), CONST64(0x00020002,0x02020000), CONST64(0x00020000,0x02020002), CONST64(0x00020002,0x02020002), + CONST64(0x00020200,0x02020000), CONST64(0x00020202,0x02020000), CONST64(0x00020200,0x02020002), CONST64(0x00020202,0x02020002), + CONST64(0x00020000,0x02020200), CONST64(0x00020002,0x02020200), CONST64(0x00020000,0x02020202), CONST64(0x00020002,0x02020202), + CONST64(0x00020200,0x02020200), CONST64(0x00020202,0x02020200), CONST64(0x00020200,0x02020202), CONST64(0x00020202,0x02020202), + CONST64(0x02000000,0x02000000), CONST64(0x02000002,0x02000000), CONST64(0x02000000,0x02000002), CONST64(0x02000002,0x02000002), + CONST64(0x02000200,0x02000000), CONST64(0x02000202,0x02000000), CONST64(0x02000200,0x02000002), CONST64(0x02000202,0x02000002), + CONST64(0x02000000,0x02000200), CONST64(0x02000002,0x02000200), CONST64(0x02000000,0x02000202), CONST64(0x02000002,0x02000202), + CONST64(0x02000200,0x02000200), CONST64(0x02000202,0x02000200), CONST64(0x02000200,0x02000202), CONST64(0x02000202,0x02000202), + CONST64(0x02020000,0x02000000), CONST64(0x02020002,0x02000000), CONST64(0x02020000,0x02000002), CONST64(0x02020002,0x02000002), + CONST64(0x02020200,0x02000000), CONST64(0x02020202,0x02000000), CONST64(0x02020200,0x02000002), CONST64(0x02020202,0x02000002), + CONST64(0x02020000,0x02000200), CONST64(0x02020002,0x02000200), CONST64(0x02020000,0x02000202), CONST64(0x02020002,0x02000202), + CONST64(0x02020200,0x02000200), CONST64(0x02020202,0x02000200), CONST64(0x02020200,0x02000202), CONST64(0x02020202,0x02000202), + CONST64(0x02000000,0x02020000), CONST64(0x02000002,0x02020000), CONST64(0x02000000,0x02020002), CONST64(0x02000002,0x02020002), + CONST64(0x02000200,0x02020000), CONST64(0x02000202,0x02020000), CONST64(0x02000200,0x02020002), CONST64(0x02000202,0x02020002), + CONST64(0x02000000,0x02020200), CONST64(0x02000002,0x02020200), CONST64(0x02000000,0x02020202), CONST64(0x02000002,0x02020202), + CONST64(0x02000200,0x02020200), CONST64(0x02000202,0x02020200), CONST64(0x02000200,0x02020202), CONST64(0x02000202,0x02020202), + CONST64(0x02020000,0x02020000), CONST64(0x02020002,0x02020000), CONST64(0x02020000,0x02020002), CONST64(0x02020002,0x02020002), + CONST64(0x02020200,0x02020000), CONST64(0x02020202,0x02020000), CONST64(0x02020200,0x02020002), CONST64(0x02020202,0x02020002), + CONST64(0x02020000,0x02020200), CONST64(0x02020002,0x02020200), CONST64(0x02020000,0x02020202), CONST64(0x02020002,0x02020202), + CONST64(0x02020200,0x02020200), CONST64(0x02020202,0x02020200), CONST64(0x02020200,0x02020202), CONST64(0x02020202,0x02020202) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000100,0x00000000), CONST64(0x00000000,0x00000100), CONST64(0x00000100,0x00000100), + CONST64(0x00010000,0x00000000), CONST64(0x00010100,0x00000000), CONST64(0x00010000,0x00000100), CONST64(0x00010100,0x00000100), + CONST64(0x00000000,0x00010000), CONST64(0x00000100,0x00010000), CONST64(0x00000000,0x00010100), CONST64(0x00000100,0x00010100), + CONST64(0x00010000,0x00010000), CONST64(0x00010100,0x00010000), CONST64(0x00010000,0x00010100), CONST64(0x00010100,0x00010100), + CONST64(0x01000000,0x00000000), CONST64(0x01000100,0x00000000), CONST64(0x01000000,0x00000100), CONST64(0x01000100,0x00000100), + CONST64(0x01010000,0x00000000), CONST64(0x01010100,0x00000000), CONST64(0x01010000,0x00000100), CONST64(0x01010100,0x00000100), + CONST64(0x01000000,0x00010000), CONST64(0x01000100,0x00010000), CONST64(0x01000000,0x00010100), CONST64(0x01000100,0x00010100), + CONST64(0x01010000,0x00010000), CONST64(0x01010100,0x00010000), CONST64(0x01010000,0x00010100), CONST64(0x01010100,0x00010100), + CONST64(0x00000000,0x01000000), CONST64(0x00000100,0x01000000), CONST64(0x00000000,0x01000100), CONST64(0x00000100,0x01000100), + CONST64(0x00010000,0x01000000), CONST64(0x00010100,0x01000000), CONST64(0x00010000,0x01000100), CONST64(0x00010100,0x01000100), + CONST64(0x00000000,0x01010000), CONST64(0x00000100,0x01010000), CONST64(0x00000000,0x01010100), CONST64(0x00000100,0x01010100), + CONST64(0x00010000,0x01010000), CONST64(0x00010100,0x01010000), CONST64(0x00010000,0x01010100), CONST64(0x00010100,0x01010100), + CONST64(0x01000000,0x01000000), CONST64(0x01000100,0x01000000), CONST64(0x01000000,0x01000100), CONST64(0x01000100,0x01000100), + CONST64(0x01010000,0x01000000), CONST64(0x01010100,0x01000000), CONST64(0x01010000,0x01000100), CONST64(0x01010100,0x01000100), + CONST64(0x01000000,0x01010000), CONST64(0x01000100,0x01010000), CONST64(0x01000000,0x01010100), CONST64(0x01000100,0x01010100), + CONST64(0x01010000,0x01010000), CONST64(0x01010100,0x01010000), CONST64(0x01010000,0x01010100), CONST64(0x01010100,0x01010100), + CONST64(0x00000001,0x00000000), CONST64(0x00000101,0x00000000), CONST64(0x00000001,0x00000100), CONST64(0x00000101,0x00000100), + CONST64(0x00010001,0x00000000), CONST64(0x00010101,0x00000000), CONST64(0x00010001,0x00000100), CONST64(0x00010101,0x00000100), + CONST64(0x00000001,0x00010000), CONST64(0x00000101,0x00010000), CONST64(0x00000001,0x00010100), CONST64(0x00000101,0x00010100), + CONST64(0x00010001,0x00010000), CONST64(0x00010101,0x00010000), CONST64(0x00010001,0x00010100), CONST64(0x00010101,0x00010100), + CONST64(0x01000001,0x00000000), CONST64(0x01000101,0x00000000), CONST64(0x01000001,0x00000100), CONST64(0x01000101,0x00000100), + CONST64(0x01010001,0x00000000), CONST64(0x01010101,0x00000000), CONST64(0x01010001,0x00000100), CONST64(0x01010101,0x00000100), + CONST64(0x01000001,0x00010000), CONST64(0x01000101,0x00010000), CONST64(0x01000001,0x00010100), CONST64(0x01000101,0x00010100), + CONST64(0x01010001,0x00010000), CONST64(0x01010101,0x00010000), CONST64(0x01010001,0x00010100), CONST64(0x01010101,0x00010100), + CONST64(0x00000001,0x01000000), CONST64(0x00000101,0x01000000), CONST64(0x00000001,0x01000100), CONST64(0x00000101,0x01000100), + CONST64(0x00010001,0x01000000), CONST64(0x00010101,0x01000000), CONST64(0x00010001,0x01000100), CONST64(0x00010101,0x01000100), + CONST64(0x00000001,0x01010000), CONST64(0x00000101,0x01010000), CONST64(0x00000001,0x01010100), CONST64(0x00000101,0x01010100), + CONST64(0x00010001,0x01010000), CONST64(0x00010101,0x01010000), CONST64(0x00010001,0x01010100), CONST64(0x00010101,0x01010100), + CONST64(0x01000001,0x01000000), CONST64(0x01000101,0x01000000), CONST64(0x01000001,0x01000100), CONST64(0x01000101,0x01000100), + CONST64(0x01010001,0x01000000), CONST64(0x01010101,0x01000000), CONST64(0x01010001,0x01000100), CONST64(0x01010101,0x01000100), + CONST64(0x01000001,0x01010000), CONST64(0x01000101,0x01010000), CONST64(0x01000001,0x01010100), CONST64(0x01000101,0x01010100), + CONST64(0x01010001,0x01010000), CONST64(0x01010101,0x01010000), CONST64(0x01010001,0x01010100), CONST64(0x01010101,0x01010100), + CONST64(0x00000000,0x00000001), CONST64(0x00000100,0x00000001), CONST64(0x00000000,0x00000101), CONST64(0x00000100,0x00000101), + CONST64(0x00010000,0x00000001), CONST64(0x00010100,0x00000001), CONST64(0x00010000,0x00000101), CONST64(0x00010100,0x00000101), + CONST64(0x00000000,0x00010001), CONST64(0x00000100,0x00010001), CONST64(0x00000000,0x00010101), CONST64(0x00000100,0x00010101), + CONST64(0x00010000,0x00010001), CONST64(0x00010100,0x00010001), CONST64(0x00010000,0x00010101), CONST64(0x00010100,0x00010101), + CONST64(0x01000000,0x00000001), CONST64(0x01000100,0x00000001), CONST64(0x01000000,0x00000101), CONST64(0x01000100,0x00000101), + CONST64(0x01010000,0x00000001), CONST64(0x01010100,0x00000001), CONST64(0x01010000,0x00000101), CONST64(0x01010100,0x00000101), + CONST64(0x01000000,0x00010001), CONST64(0x01000100,0x00010001), CONST64(0x01000000,0x00010101), CONST64(0x01000100,0x00010101), + CONST64(0x01010000,0x00010001), CONST64(0x01010100,0x00010001), CONST64(0x01010000,0x00010101), CONST64(0x01010100,0x00010101), + CONST64(0x00000000,0x01000001), CONST64(0x00000100,0x01000001), CONST64(0x00000000,0x01000101), CONST64(0x00000100,0x01000101), + CONST64(0x00010000,0x01000001), CONST64(0x00010100,0x01000001), CONST64(0x00010000,0x01000101), CONST64(0x00010100,0x01000101), + CONST64(0x00000000,0x01010001), CONST64(0x00000100,0x01010001), CONST64(0x00000000,0x01010101), CONST64(0x00000100,0x01010101), + CONST64(0x00010000,0x01010001), CONST64(0x00010100,0x01010001), CONST64(0x00010000,0x01010101), CONST64(0x00010100,0x01010101), + CONST64(0x01000000,0x01000001), CONST64(0x01000100,0x01000001), CONST64(0x01000000,0x01000101), CONST64(0x01000100,0x01000101), + CONST64(0x01010000,0x01000001), CONST64(0x01010100,0x01000001), CONST64(0x01010000,0x01000101), CONST64(0x01010100,0x01000101), + CONST64(0x01000000,0x01010001), CONST64(0x01000100,0x01010001), CONST64(0x01000000,0x01010101), CONST64(0x01000100,0x01010101), + CONST64(0x01010000,0x01010001), CONST64(0x01010100,0x01010001), CONST64(0x01010000,0x01010101), CONST64(0x01010100,0x01010101), + CONST64(0x00000001,0x00000001), CONST64(0x00000101,0x00000001), CONST64(0x00000001,0x00000101), CONST64(0x00000101,0x00000101), + CONST64(0x00010001,0x00000001), CONST64(0x00010101,0x00000001), CONST64(0x00010001,0x00000101), CONST64(0x00010101,0x00000101), + CONST64(0x00000001,0x00010001), CONST64(0x00000101,0x00010001), CONST64(0x00000001,0x00010101), CONST64(0x00000101,0x00010101), + CONST64(0x00010001,0x00010001), CONST64(0x00010101,0x00010001), CONST64(0x00010001,0x00010101), CONST64(0x00010101,0x00010101), + CONST64(0x01000001,0x00000001), CONST64(0x01000101,0x00000001), CONST64(0x01000001,0x00000101), CONST64(0x01000101,0x00000101), + CONST64(0x01010001,0x00000001), CONST64(0x01010101,0x00000001), CONST64(0x01010001,0x00000101), CONST64(0x01010101,0x00000101), + CONST64(0x01000001,0x00010001), CONST64(0x01000101,0x00010001), CONST64(0x01000001,0x00010101), CONST64(0x01000101,0x00010101), + CONST64(0x01010001,0x00010001), CONST64(0x01010101,0x00010001), CONST64(0x01010001,0x00010101), CONST64(0x01010101,0x00010101), + CONST64(0x00000001,0x01000001), CONST64(0x00000101,0x01000001), CONST64(0x00000001,0x01000101), CONST64(0x00000101,0x01000101), + CONST64(0x00010001,0x01000001), CONST64(0x00010101,0x01000001), CONST64(0x00010001,0x01000101), CONST64(0x00010101,0x01000101), + CONST64(0x00000001,0x01010001), CONST64(0x00000101,0x01010001), CONST64(0x00000001,0x01010101), CONST64(0x00000101,0x01010101), + CONST64(0x00010001,0x01010001), CONST64(0x00010101,0x01010001), CONST64(0x00010001,0x01010101), CONST64(0x00010101,0x01010101), + CONST64(0x01000001,0x01000001), CONST64(0x01000101,0x01000001), CONST64(0x01000001,0x01000101), CONST64(0x01000101,0x01000101), + CONST64(0x01010001,0x01000001), CONST64(0x01010101,0x01000001), CONST64(0x01010001,0x01000101), CONST64(0x01010101,0x01000101), + CONST64(0x01000001,0x01010001), CONST64(0x01000101,0x01010001), CONST64(0x01000001,0x01010101), CONST64(0x01000101,0x01010101), + CONST64(0x01010001,0x01010001), CONST64(0x01010101,0x01010001), CONST64(0x01010001,0x01010101), CONST64(0x01010101,0x01010101) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000080,0x00000000), CONST64(0x00000000,0x00000080), CONST64(0x00000080,0x00000080), + CONST64(0x00008000,0x00000000), CONST64(0x00008080,0x00000000), CONST64(0x00008000,0x00000080), CONST64(0x00008080,0x00000080), + CONST64(0x00000000,0x00008000), CONST64(0x00000080,0x00008000), CONST64(0x00000000,0x00008080), CONST64(0x00000080,0x00008080), + CONST64(0x00008000,0x00008000), CONST64(0x00008080,0x00008000), CONST64(0x00008000,0x00008080), CONST64(0x00008080,0x00008080), + CONST64(0x00800000,0x00000000), CONST64(0x00800080,0x00000000), CONST64(0x00800000,0x00000080), CONST64(0x00800080,0x00000080), + CONST64(0x00808000,0x00000000), CONST64(0x00808080,0x00000000), CONST64(0x00808000,0x00000080), CONST64(0x00808080,0x00000080), + CONST64(0x00800000,0x00008000), CONST64(0x00800080,0x00008000), CONST64(0x00800000,0x00008080), CONST64(0x00800080,0x00008080), + CONST64(0x00808000,0x00008000), CONST64(0x00808080,0x00008000), CONST64(0x00808000,0x00008080), CONST64(0x00808080,0x00008080), + CONST64(0x00000000,0x00800000), CONST64(0x00000080,0x00800000), CONST64(0x00000000,0x00800080), CONST64(0x00000080,0x00800080), + CONST64(0x00008000,0x00800000), CONST64(0x00008080,0x00800000), CONST64(0x00008000,0x00800080), CONST64(0x00008080,0x00800080), + CONST64(0x00000000,0x00808000), CONST64(0x00000080,0x00808000), CONST64(0x00000000,0x00808080), CONST64(0x00000080,0x00808080), + CONST64(0x00008000,0x00808000), CONST64(0x00008080,0x00808000), CONST64(0x00008000,0x00808080), CONST64(0x00008080,0x00808080), + CONST64(0x00800000,0x00800000), CONST64(0x00800080,0x00800000), CONST64(0x00800000,0x00800080), CONST64(0x00800080,0x00800080), + CONST64(0x00808000,0x00800000), CONST64(0x00808080,0x00800000), CONST64(0x00808000,0x00800080), CONST64(0x00808080,0x00800080), + CONST64(0x00800000,0x00808000), CONST64(0x00800080,0x00808000), CONST64(0x00800000,0x00808080), CONST64(0x00800080,0x00808080), + CONST64(0x00808000,0x00808000), CONST64(0x00808080,0x00808000), CONST64(0x00808000,0x00808080), CONST64(0x00808080,0x00808080), + CONST64(0x80000000,0x00000000), CONST64(0x80000080,0x00000000), CONST64(0x80000000,0x00000080), CONST64(0x80000080,0x00000080), + CONST64(0x80008000,0x00000000), CONST64(0x80008080,0x00000000), CONST64(0x80008000,0x00000080), CONST64(0x80008080,0x00000080), + CONST64(0x80000000,0x00008000), CONST64(0x80000080,0x00008000), CONST64(0x80000000,0x00008080), CONST64(0x80000080,0x00008080), + CONST64(0x80008000,0x00008000), CONST64(0x80008080,0x00008000), CONST64(0x80008000,0x00008080), CONST64(0x80008080,0x00008080), + CONST64(0x80800000,0x00000000), CONST64(0x80800080,0x00000000), CONST64(0x80800000,0x00000080), CONST64(0x80800080,0x00000080), + CONST64(0x80808000,0x00000000), CONST64(0x80808080,0x00000000), CONST64(0x80808000,0x00000080), CONST64(0x80808080,0x00000080), + CONST64(0x80800000,0x00008000), CONST64(0x80800080,0x00008000), CONST64(0x80800000,0x00008080), CONST64(0x80800080,0x00008080), + CONST64(0x80808000,0x00008000), CONST64(0x80808080,0x00008000), CONST64(0x80808000,0x00008080), CONST64(0x80808080,0x00008080), + CONST64(0x80000000,0x00800000), CONST64(0x80000080,0x00800000), CONST64(0x80000000,0x00800080), CONST64(0x80000080,0x00800080), + CONST64(0x80008000,0x00800000), CONST64(0x80008080,0x00800000), CONST64(0x80008000,0x00800080), CONST64(0x80008080,0x00800080), + CONST64(0x80000000,0x00808000), CONST64(0x80000080,0x00808000), CONST64(0x80000000,0x00808080), CONST64(0x80000080,0x00808080), + CONST64(0x80008000,0x00808000), CONST64(0x80008080,0x00808000), CONST64(0x80008000,0x00808080), CONST64(0x80008080,0x00808080), + CONST64(0x80800000,0x00800000), CONST64(0x80800080,0x00800000), CONST64(0x80800000,0x00800080), CONST64(0x80800080,0x00800080), + CONST64(0x80808000,0x00800000), CONST64(0x80808080,0x00800000), CONST64(0x80808000,0x00800080), CONST64(0x80808080,0x00800080), + CONST64(0x80800000,0x00808000), CONST64(0x80800080,0x00808000), CONST64(0x80800000,0x00808080), CONST64(0x80800080,0x00808080), + CONST64(0x80808000,0x00808000), CONST64(0x80808080,0x00808000), CONST64(0x80808000,0x00808080), CONST64(0x80808080,0x00808080), + CONST64(0x00000000,0x80000000), CONST64(0x00000080,0x80000000), CONST64(0x00000000,0x80000080), CONST64(0x00000080,0x80000080), + CONST64(0x00008000,0x80000000), CONST64(0x00008080,0x80000000), CONST64(0x00008000,0x80000080), CONST64(0x00008080,0x80000080), + CONST64(0x00000000,0x80008000), CONST64(0x00000080,0x80008000), CONST64(0x00000000,0x80008080), CONST64(0x00000080,0x80008080), + CONST64(0x00008000,0x80008000), CONST64(0x00008080,0x80008000), CONST64(0x00008000,0x80008080), CONST64(0x00008080,0x80008080), + CONST64(0x00800000,0x80000000), CONST64(0x00800080,0x80000000), CONST64(0x00800000,0x80000080), CONST64(0x00800080,0x80000080), + CONST64(0x00808000,0x80000000), CONST64(0x00808080,0x80000000), CONST64(0x00808000,0x80000080), CONST64(0x00808080,0x80000080), + CONST64(0x00800000,0x80008000), CONST64(0x00800080,0x80008000), CONST64(0x00800000,0x80008080), CONST64(0x00800080,0x80008080), + CONST64(0x00808000,0x80008000), CONST64(0x00808080,0x80008000), CONST64(0x00808000,0x80008080), CONST64(0x00808080,0x80008080), + CONST64(0x00000000,0x80800000), CONST64(0x00000080,0x80800000), CONST64(0x00000000,0x80800080), CONST64(0x00000080,0x80800080), + CONST64(0x00008000,0x80800000), CONST64(0x00008080,0x80800000), CONST64(0x00008000,0x80800080), CONST64(0x00008080,0x80800080), + CONST64(0x00000000,0x80808000), CONST64(0x00000080,0x80808000), CONST64(0x00000000,0x80808080), CONST64(0x00000080,0x80808080), + CONST64(0x00008000,0x80808000), CONST64(0x00008080,0x80808000), CONST64(0x00008000,0x80808080), CONST64(0x00008080,0x80808080), + CONST64(0x00800000,0x80800000), CONST64(0x00800080,0x80800000), CONST64(0x00800000,0x80800080), CONST64(0x00800080,0x80800080), + CONST64(0x00808000,0x80800000), CONST64(0x00808080,0x80800000), CONST64(0x00808000,0x80800080), CONST64(0x00808080,0x80800080), + CONST64(0x00800000,0x80808000), CONST64(0x00800080,0x80808000), CONST64(0x00800000,0x80808080), CONST64(0x00800080,0x80808080), + CONST64(0x00808000,0x80808000), CONST64(0x00808080,0x80808000), CONST64(0x00808000,0x80808080), CONST64(0x00808080,0x80808080), + CONST64(0x80000000,0x80000000), CONST64(0x80000080,0x80000000), CONST64(0x80000000,0x80000080), CONST64(0x80000080,0x80000080), + CONST64(0x80008000,0x80000000), CONST64(0x80008080,0x80000000), CONST64(0x80008000,0x80000080), CONST64(0x80008080,0x80000080), + CONST64(0x80000000,0x80008000), CONST64(0x80000080,0x80008000), CONST64(0x80000000,0x80008080), CONST64(0x80000080,0x80008080), + CONST64(0x80008000,0x80008000), CONST64(0x80008080,0x80008000), CONST64(0x80008000,0x80008080), CONST64(0x80008080,0x80008080), + CONST64(0x80800000,0x80000000), CONST64(0x80800080,0x80000000), CONST64(0x80800000,0x80000080), CONST64(0x80800080,0x80000080), + CONST64(0x80808000,0x80000000), CONST64(0x80808080,0x80000000), CONST64(0x80808000,0x80000080), CONST64(0x80808080,0x80000080), + CONST64(0x80800000,0x80008000), CONST64(0x80800080,0x80008000), CONST64(0x80800000,0x80008080), CONST64(0x80800080,0x80008080), + CONST64(0x80808000,0x80008000), CONST64(0x80808080,0x80008000), CONST64(0x80808000,0x80008080), CONST64(0x80808080,0x80008080), + CONST64(0x80000000,0x80800000), CONST64(0x80000080,0x80800000), CONST64(0x80000000,0x80800080), CONST64(0x80000080,0x80800080), + CONST64(0x80008000,0x80800000), CONST64(0x80008080,0x80800000), CONST64(0x80008000,0x80800080), CONST64(0x80008080,0x80800080), + CONST64(0x80000000,0x80808000), CONST64(0x80000080,0x80808000), CONST64(0x80000000,0x80808080), CONST64(0x80000080,0x80808080), + CONST64(0x80008000,0x80808000), CONST64(0x80008080,0x80808000), CONST64(0x80008000,0x80808080), CONST64(0x80008080,0x80808080), + CONST64(0x80800000,0x80800000), CONST64(0x80800080,0x80800000), CONST64(0x80800000,0x80800080), CONST64(0x80800080,0x80800080), + CONST64(0x80808000,0x80800000), CONST64(0x80808080,0x80800000), CONST64(0x80808000,0x80800080), CONST64(0x80808080,0x80800080), + CONST64(0x80800000,0x80808000), CONST64(0x80800080,0x80808000), CONST64(0x80800000,0x80808080), CONST64(0x80800080,0x80808080), + CONST64(0x80808000,0x80808000), CONST64(0x80808080,0x80808000), CONST64(0x80808000,0x80808080), CONST64(0x80808080,0x80808080) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000040,0x00000000), CONST64(0x00000000,0x00000040), CONST64(0x00000040,0x00000040), + CONST64(0x00004000,0x00000000), CONST64(0x00004040,0x00000000), CONST64(0x00004000,0x00000040), CONST64(0x00004040,0x00000040), + CONST64(0x00000000,0x00004000), CONST64(0x00000040,0x00004000), CONST64(0x00000000,0x00004040), CONST64(0x00000040,0x00004040), + CONST64(0x00004000,0x00004000), CONST64(0x00004040,0x00004000), CONST64(0x00004000,0x00004040), CONST64(0x00004040,0x00004040), + CONST64(0x00400000,0x00000000), CONST64(0x00400040,0x00000000), CONST64(0x00400000,0x00000040), CONST64(0x00400040,0x00000040), + CONST64(0x00404000,0x00000000), CONST64(0x00404040,0x00000000), CONST64(0x00404000,0x00000040), CONST64(0x00404040,0x00000040), + CONST64(0x00400000,0x00004000), CONST64(0x00400040,0x00004000), CONST64(0x00400000,0x00004040), CONST64(0x00400040,0x00004040), + CONST64(0x00404000,0x00004000), CONST64(0x00404040,0x00004000), CONST64(0x00404000,0x00004040), CONST64(0x00404040,0x00004040), + CONST64(0x00000000,0x00400000), CONST64(0x00000040,0x00400000), CONST64(0x00000000,0x00400040), CONST64(0x00000040,0x00400040), + CONST64(0x00004000,0x00400000), CONST64(0x00004040,0x00400000), CONST64(0x00004000,0x00400040), CONST64(0x00004040,0x00400040), + CONST64(0x00000000,0x00404000), CONST64(0x00000040,0x00404000), CONST64(0x00000000,0x00404040), CONST64(0x00000040,0x00404040), + CONST64(0x00004000,0x00404000), CONST64(0x00004040,0x00404000), CONST64(0x00004000,0x00404040), CONST64(0x00004040,0x00404040), + CONST64(0x00400000,0x00400000), CONST64(0x00400040,0x00400000), CONST64(0x00400000,0x00400040), CONST64(0x00400040,0x00400040), + CONST64(0x00404000,0x00400000), CONST64(0x00404040,0x00400000), CONST64(0x00404000,0x00400040), CONST64(0x00404040,0x00400040), + CONST64(0x00400000,0x00404000), CONST64(0x00400040,0x00404000), CONST64(0x00400000,0x00404040), CONST64(0x00400040,0x00404040), + CONST64(0x00404000,0x00404000), CONST64(0x00404040,0x00404000), CONST64(0x00404000,0x00404040), CONST64(0x00404040,0x00404040), + CONST64(0x40000000,0x00000000), CONST64(0x40000040,0x00000000), CONST64(0x40000000,0x00000040), CONST64(0x40000040,0x00000040), + CONST64(0x40004000,0x00000000), CONST64(0x40004040,0x00000000), CONST64(0x40004000,0x00000040), CONST64(0x40004040,0x00000040), + CONST64(0x40000000,0x00004000), CONST64(0x40000040,0x00004000), CONST64(0x40000000,0x00004040), CONST64(0x40000040,0x00004040), + CONST64(0x40004000,0x00004000), CONST64(0x40004040,0x00004000), CONST64(0x40004000,0x00004040), CONST64(0x40004040,0x00004040), + CONST64(0x40400000,0x00000000), CONST64(0x40400040,0x00000000), CONST64(0x40400000,0x00000040), CONST64(0x40400040,0x00000040), + CONST64(0x40404000,0x00000000), CONST64(0x40404040,0x00000000), CONST64(0x40404000,0x00000040), CONST64(0x40404040,0x00000040), + CONST64(0x40400000,0x00004000), CONST64(0x40400040,0x00004000), CONST64(0x40400000,0x00004040), CONST64(0x40400040,0x00004040), + CONST64(0x40404000,0x00004000), CONST64(0x40404040,0x00004000), CONST64(0x40404000,0x00004040), CONST64(0x40404040,0x00004040), + CONST64(0x40000000,0x00400000), CONST64(0x40000040,0x00400000), CONST64(0x40000000,0x00400040), CONST64(0x40000040,0x00400040), + CONST64(0x40004000,0x00400000), CONST64(0x40004040,0x00400000), CONST64(0x40004000,0x00400040), CONST64(0x40004040,0x00400040), + CONST64(0x40000000,0x00404000), CONST64(0x40000040,0x00404000), CONST64(0x40000000,0x00404040), CONST64(0x40000040,0x00404040), + CONST64(0x40004000,0x00404000), CONST64(0x40004040,0x00404000), CONST64(0x40004000,0x00404040), CONST64(0x40004040,0x00404040), + CONST64(0x40400000,0x00400000), CONST64(0x40400040,0x00400000), CONST64(0x40400000,0x00400040), CONST64(0x40400040,0x00400040), + CONST64(0x40404000,0x00400000), CONST64(0x40404040,0x00400000), CONST64(0x40404000,0x00400040), CONST64(0x40404040,0x00400040), + CONST64(0x40400000,0x00404000), CONST64(0x40400040,0x00404000), CONST64(0x40400000,0x00404040), CONST64(0x40400040,0x00404040), + CONST64(0x40404000,0x00404000), CONST64(0x40404040,0x00404000), CONST64(0x40404000,0x00404040), CONST64(0x40404040,0x00404040), + CONST64(0x00000000,0x40000000), CONST64(0x00000040,0x40000000), CONST64(0x00000000,0x40000040), CONST64(0x00000040,0x40000040), + CONST64(0x00004000,0x40000000), CONST64(0x00004040,0x40000000), CONST64(0x00004000,0x40000040), CONST64(0x00004040,0x40000040), + CONST64(0x00000000,0x40004000), CONST64(0x00000040,0x40004000), CONST64(0x00000000,0x40004040), CONST64(0x00000040,0x40004040), + CONST64(0x00004000,0x40004000), CONST64(0x00004040,0x40004000), CONST64(0x00004000,0x40004040), CONST64(0x00004040,0x40004040), + CONST64(0x00400000,0x40000000), CONST64(0x00400040,0x40000000), CONST64(0x00400000,0x40000040), CONST64(0x00400040,0x40000040), + CONST64(0x00404000,0x40000000), CONST64(0x00404040,0x40000000), CONST64(0x00404000,0x40000040), CONST64(0x00404040,0x40000040), + CONST64(0x00400000,0x40004000), CONST64(0x00400040,0x40004000), CONST64(0x00400000,0x40004040), CONST64(0x00400040,0x40004040), + CONST64(0x00404000,0x40004000), CONST64(0x00404040,0x40004000), CONST64(0x00404000,0x40004040), CONST64(0x00404040,0x40004040), + CONST64(0x00000000,0x40400000), CONST64(0x00000040,0x40400000), CONST64(0x00000000,0x40400040), CONST64(0x00000040,0x40400040), + CONST64(0x00004000,0x40400000), CONST64(0x00004040,0x40400000), CONST64(0x00004000,0x40400040), CONST64(0x00004040,0x40400040), + CONST64(0x00000000,0x40404000), CONST64(0x00000040,0x40404000), CONST64(0x00000000,0x40404040), CONST64(0x00000040,0x40404040), + CONST64(0x00004000,0x40404000), CONST64(0x00004040,0x40404000), CONST64(0x00004000,0x40404040), CONST64(0x00004040,0x40404040), + CONST64(0x00400000,0x40400000), CONST64(0x00400040,0x40400000), CONST64(0x00400000,0x40400040), CONST64(0x00400040,0x40400040), + CONST64(0x00404000,0x40400000), CONST64(0x00404040,0x40400000), CONST64(0x00404000,0x40400040), CONST64(0x00404040,0x40400040), + CONST64(0x00400000,0x40404000), CONST64(0x00400040,0x40404000), CONST64(0x00400000,0x40404040), CONST64(0x00400040,0x40404040), + CONST64(0x00404000,0x40404000), CONST64(0x00404040,0x40404000), CONST64(0x00404000,0x40404040), CONST64(0x00404040,0x40404040), + CONST64(0x40000000,0x40000000), CONST64(0x40000040,0x40000000), CONST64(0x40000000,0x40000040), CONST64(0x40000040,0x40000040), + CONST64(0x40004000,0x40000000), CONST64(0x40004040,0x40000000), CONST64(0x40004000,0x40000040), CONST64(0x40004040,0x40000040), + CONST64(0x40000000,0x40004000), CONST64(0x40000040,0x40004000), CONST64(0x40000000,0x40004040), CONST64(0x40000040,0x40004040), + CONST64(0x40004000,0x40004000), CONST64(0x40004040,0x40004000), CONST64(0x40004000,0x40004040), CONST64(0x40004040,0x40004040), + CONST64(0x40400000,0x40000000), CONST64(0x40400040,0x40000000), CONST64(0x40400000,0x40000040), CONST64(0x40400040,0x40000040), + CONST64(0x40404000,0x40000000), CONST64(0x40404040,0x40000000), CONST64(0x40404000,0x40000040), CONST64(0x40404040,0x40000040), + CONST64(0x40400000,0x40004000), CONST64(0x40400040,0x40004000), CONST64(0x40400000,0x40004040), CONST64(0x40400040,0x40004040), + CONST64(0x40404000,0x40004000), CONST64(0x40404040,0x40004000), CONST64(0x40404000,0x40004040), CONST64(0x40404040,0x40004040), + CONST64(0x40000000,0x40400000), CONST64(0x40000040,0x40400000), CONST64(0x40000000,0x40400040), CONST64(0x40000040,0x40400040), + CONST64(0x40004000,0x40400000), CONST64(0x40004040,0x40400000), CONST64(0x40004000,0x40400040), CONST64(0x40004040,0x40400040), + CONST64(0x40000000,0x40404000), CONST64(0x40000040,0x40404000), CONST64(0x40000000,0x40404040), CONST64(0x40000040,0x40404040), + CONST64(0x40004000,0x40404000), CONST64(0x40004040,0x40404000), CONST64(0x40004000,0x40404040), CONST64(0x40004040,0x40404040), + CONST64(0x40400000,0x40400000), CONST64(0x40400040,0x40400000), CONST64(0x40400000,0x40400040), CONST64(0x40400040,0x40400040), + CONST64(0x40404000,0x40400000), CONST64(0x40404040,0x40400000), CONST64(0x40404000,0x40400040), CONST64(0x40404040,0x40400040), + CONST64(0x40400000,0x40404000), CONST64(0x40400040,0x40404000), CONST64(0x40400000,0x40404040), CONST64(0x40400040,0x40404040), + CONST64(0x40404000,0x40404000), CONST64(0x40404040,0x40404000), CONST64(0x40404000,0x40404040), CONST64(0x40404040,0x40404040) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000020,0x00000000), CONST64(0x00000000,0x00000020), CONST64(0x00000020,0x00000020), + CONST64(0x00002000,0x00000000), CONST64(0x00002020,0x00000000), CONST64(0x00002000,0x00000020), CONST64(0x00002020,0x00000020), + CONST64(0x00000000,0x00002000), CONST64(0x00000020,0x00002000), CONST64(0x00000000,0x00002020), CONST64(0x00000020,0x00002020), + CONST64(0x00002000,0x00002000), CONST64(0x00002020,0x00002000), CONST64(0x00002000,0x00002020), CONST64(0x00002020,0x00002020), + CONST64(0x00200000,0x00000000), CONST64(0x00200020,0x00000000), CONST64(0x00200000,0x00000020), CONST64(0x00200020,0x00000020), + CONST64(0x00202000,0x00000000), CONST64(0x00202020,0x00000000), CONST64(0x00202000,0x00000020), CONST64(0x00202020,0x00000020), + CONST64(0x00200000,0x00002000), CONST64(0x00200020,0x00002000), CONST64(0x00200000,0x00002020), CONST64(0x00200020,0x00002020), + CONST64(0x00202000,0x00002000), CONST64(0x00202020,0x00002000), CONST64(0x00202000,0x00002020), CONST64(0x00202020,0x00002020), + CONST64(0x00000000,0x00200000), CONST64(0x00000020,0x00200000), CONST64(0x00000000,0x00200020), CONST64(0x00000020,0x00200020), + CONST64(0x00002000,0x00200000), CONST64(0x00002020,0x00200000), CONST64(0x00002000,0x00200020), CONST64(0x00002020,0x00200020), + CONST64(0x00000000,0x00202000), CONST64(0x00000020,0x00202000), CONST64(0x00000000,0x00202020), CONST64(0x00000020,0x00202020), + CONST64(0x00002000,0x00202000), CONST64(0x00002020,0x00202000), CONST64(0x00002000,0x00202020), CONST64(0x00002020,0x00202020), + CONST64(0x00200000,0x00200000), CONST64(0x00200020,0x00200000), CONST64(0x00200000,0x00200020), CONST64(0x00200020,0x00200020), + CONST64(0x00202000,0x00200000), CONST64(0x00202020,0x00200000), CONST64(0x00202000,0x00200020), CONST64(0x00202020,0x00200020), + CONST64(0x00200000,0x00202000), CONST64(0x00200020,0x00202000), CONST64(0x00200000,0x00202020), CONST64(0x00200020,0x00202020), + CONST64(0x00202000,0x00202000), CONST64(0x00202020,0x00202000), CONST64(0x00202000,0x00202020), CONST64(0x00202020,0x00202020), + CONST64(0x20000000,0x00000000), CONST64(0x20000020,0x00000000), CONST64(0x20000000,0x00000020), CONST64(0x20000020,0x00000020), + CONST64(0x20002000,0x00000000), CONST64(0x20002020,0x00000000), CONST64(0x20002000,0x00000020), CONST64(0x20002020,0x00000020), + CONST64(0x20000000,0x00002000), CONST64(0x20000020,0x00002000), CONST64(0x20000000,0x00002020), CONST64(0x20000020,0x00002020), + CONST64(0x20002000,0x00002000), CONST64(0x20002020,0x00002000), CONST64(0x20002000,0x00002020), CONST64(0x20002020,0x00002020), + CONST64(0x20200000,0x00000000), CONST64(0x20200020,0x00000000), CONST64(0x20200000,0x00000020), CONST64(0x20200020,0x00000020), + CONST64(0x20202000,0x00000000), CONST64(0x20202020,0x00000000), CONST64(0x20202000,0x00000020), CONST64(0x20202020,0x00000020), + CONST64(0x20200000,0x00002000), CONST64(0x20200020,0x00002000), CONST64(0x20200000,0x00002020), CONST64(0x20200020,0x00002020), + CONST64(0x20202000,0x00002000), CONST64(0x20202020,0x00002000), CONST64(0x20202000,0x00002020), CONST64(0x20202020,0x00002020), + CONST64(0x20000000,0x00200000), CONST64(0x20000020,0x00200000), CONST64(0x20000000,0x00200020), CONST64(0x20000020,0x00200020), + CONST64(0x20002000,0x00200000), CONST64(0x20002020,0x00200000), CONST64(0x20002000,0x00200020), CONST64(0x20002020,0x00200020), + CONST64(0x20000000,0x00202000), CONST64(0x20000020,0x00202000), CONST64(0x20000000,0x00202020), CONST64(0x20000020,0x00202020), + CONST64(0x20002000,0x00202000), CONST64(0x20002020,0x00202000), CONST64(0x20002000,0x00202020), CONST64(0x20002020,0x00202020), + CONST64(0x20200000,0x00200000), CONST64(0x20200020,0x00200000), CONST64(0x20200000,0x00200020), CONST64(0x20200020,0x00200020), + CONST64(0x20202000,0x00200000), CONST64(0x20202020,0x00200000), CONST64(0x20202000,0x00200020), CONST64(0x20202020,0x00200020), + CONST64(0x20200000,0x00202000), CONST64(0x20200020,0x00202000), CONST64(0x20200000,0x00202020), CONST64(0x20200020,0x00202020), + CONST64(0x20202000,0x00202000), CONST64(0x20202020,0x00202000), CONST64(0x20202000,0x00202020), CONST64(0x20202020,0x00202020), + CONST64(0x00000000,0x20000000), CONST64(0x00000020,0x20000000), CONST64(0x00000000,0x20000020), CONST64(0x00000020,0x20000020), + CONST64(0x00002000,0x20000000), CONST64(0x00002020,0x20000000), CONST64(0x00002000,0x20000020), CONST64(0x00002020,0x20000020), + CONST64(0x00000000,0x20002000), CONST64(0x00000020,0x20002000), CONST64(0x00000000,0x20002020), CONST64(0x00000020,0x20002020), + CONST64(0x00002000,0x20002000), CONST64(0x00002020,0x20002000), CONST64(0x00002000,0x20002020), CONST64(0x00002020,0x20002020), + CONST64(0x00200000,0x20000000), CONST64(0x00200020,0x20000000), CONST64(0x00200000,0x20000020), CONST64(0x00200020,0x20000020), + CONST64(0x00202000,0x20000000), CONST64(0x00202020,0x20000000), CONST64(0x00202000,0x20000020), CONST64(0x00202020,0x20000020), + CONST64(0x00200000,0x20002000), CONST64(0x00200020,0x20002000), CONST64(0x00200000,0x20002020), CONST64(0x00200020,0x20002020), + CONST64(0x00202000,0x20002000), CONST64(0x00202020,0x20002000), CONST64(0x00202000,0x20002020), CONST64(0x00202020,0x20002020), + CONST64(0x00000000,0x20200000), CONST64(0x00000020,0x20200000), CONST64(0x00000000,0x20200020), CONST64(0x00000020,0x20200020), + CONST64(0x00002000,0x20200000), CONST64(0x00002020,0x20200000), CONST64(0x00002000,0x20200020), CONST64(0x00002020,0x20200020), + CONST64(0x00000000,0x20202000), CONST64(0x00000020,0x20202000), CONST64(0x00000000,0x20202020), CONST64(0x00000020,0x20202020), + CONST64(0x00002000,0x20202000), CONST64(0x00002020,0x20202000), CONST64(0x00002000,0x20202020), CONST64(0x00002020,0x20202020), + CONST64(0x00200000,0x20200000), CONST64(0x00200020,0x20200000), CONST64(0x00200000,0x20200020), CONST64(0x00200020,0x20200020), + CONST64(0x00202000,0x20200000), CONST64(0x00202020,0x20200000), CONST64(0x00202000,0x20200020), CONST64(0x00202020,0x20200020), + CONST64(0x00200000,0x20202000), CONST64(0x00200020,0x20202000), CONST64(0x00200000,0x20202020), CONST64(0x00200020,0x20202020), + CONST64(0x00202000,0x20202000), CONST64(0x00202020,0x20202000), CONST64(0x00202000,0x20202020), CONST64(0x00202020,0x20202020), + CONST64(0x20000000,0x20000000), CONST64(0x20000020,0x20000000), CONST64(0x20000000,0x20000020), CONST64(0x20000020,0x20000020), + CONST64(0x20002000,0x20000000), CONST64(0x20002020,0x20000000), CONST64(0x20002000,0x20000020), CONST64(0x20002020,0x20000020), + CONST64(0x20000000,0x20002000), CONST64(0x20000020,0x20002000), CONST64(0x20000000,0x20002020), CONST64(0x20000020,0x20002020), + CONST64(0x20002000,0x20002000), CONST64(0x20002020,0x20002000), CONST64(0x20002000,0x20002020), CONST64(0x20002020,0x20002020), + CONST64(0x20200000,0x20000000), CONST64(0x20200020,0x20000000), CONST64(0x20200000,0x20000020), CONST64(0x20200020,0x20000020), + CONST64(0x20202000,0x20000000), CONST64(0x20202020,0x20000000), CONST64(0x20202000,0x20000020), CONST64(0x20202020,0x20000020), + CONST64(0x20200000,0x20002000), CONST64(0x20200020,0x20002000), CONST64(0x20200000,0x20002020), CONST64(0x20200020,0x20002020), + CONST64(0x20202000,0x20002000), CONST64(0x20202020,0x20002000), CONST64(0x20202000,0x20002020), CONST64(0x20202020,0x20002020), + CONST64(0x20000000,0x20200000), CONST64(0x20000020,0x20200000), CONST64(0x20000000,0x20200020), CONST64(0x20000020,0x20200020), + CONST64(0x20002000,0x20200000), CONST64(0x20002020,0x20200000), CONST64(0x20002000,0x20200020), CONST64(0x20002020,0x20200020), + CONST64(0x20000000,0x20202000), CONST64(0x20000020,0x20202000), CONST64(0x20000000,0x20202020), CONST64(0x20000020,0x20202020), + CONST64(0x20002000,0x20202000), CONST64(0x20002020,0x20202000), CONST64(0x20002000,0x20202020), CONST64(0x20002020,0x20202020), + CONST64(0x20200000,0x20200000), CONST64(0x20200020,0x20200000), CONST64(0x20200000,0x20200020), CONST64(0x20200020,0x20200020), + CONST64(0x20202000,0x20200000), CONST64(0x20202020,0x20200000), CONST64(0x20202000,0x20200020), CONST64(0x20202020,0x20200020), + CONST64(0x20200000,0x20202000), CONST64(0x20200020,0x20202000), CONST64(0x20200000,0x20202020), CONST64(0x20200020,0x20202020), + CONST64(0x20202000,0x20202000), CONST64(0x20202020,0x20202000), CONST64(0x20202000,0x20202020), CONST64(0x20202020,0x20202020) + }}; + +static const ulong64 des_fp[8][256] = { + +{ CONST64(0x00000000,0x00000000), CONST64(0x00000080,0x00000000), CONST64(0x00000000,0x02000000), CONST64(0x00000080,0x02000000), + CONST64(0x00000000,0x00020000), CONST64(0x00000080,0x00020000), CONST64(0x00000000,0x02020000), CONST64(0x00000080,0x02020000), + CONST64(0x00000000,0x00000200), CONST64(0x00000080,0x00000200), CONST64(0x00000000,0x02000200), CONST64(0x00000080,0x02000200), + CONST64(0x00000000,0x00020200), CONST64(0x00000080,0x00020200), CONST64(0x00000000,0x02020200), CONST64(0x00000080,0x02020200), + CONST64(0x00000000,0x00000002), CONST64(0x00000080,0x00000002), CONST64(0x00000000,0x02000002), CONST64(0x00000080,0x02000002), + CONST64(0x00000000,0x00020002), CONST64(0x00000080,0x00020002), CONST64(0x00000000,0x02020002), CONST64(0x00000080,0x02020002), + CONST64(0x00000000,0x00000202), CONST64(0x00000080,0x00000202), CONST64(0x00000000,0x02000202), CONST64(0x00000080,0x02000202), + CONST64(0x00000000,0x00020202), CONST64(0x00000080,0x00020202), CONST64(0x00000000,0x02020202), CONST64(0x00000080,0x02020202), + CONST64(0x02000000,0x00000000), CONST64(0x02000080,0x00000000), CONST64(0x02000000,0x02000000), CONST64(0x02000080,0x02000000), + CONST64(0x02000000,0x00020000), CONST64(0x02000080,0x00020000), CONST64(0x02000000,0x02020000), CONST64(0x02000080,0x02020000), + CONST64(0x02000000,0x00000200), CONST64(0x02000080,0x00000200), CONST64(0x02000000,0x02000200), CONST64(0x02000080,0x02000200), + CONST64(0x02000000,0x00020200), CONST64(0x02000080,0x00020200), CONST64(0x02000000,0x02020200), CONST64(0x02000080,0x02020200), + CONST64(0x02000000,0x00000002), CONST64(0x02000080,0x00000002), CONST64(0x02000000,0x02000002), CONST64(0x02000080,0x02000002), + CONST64(0x02000000,0x00020002), CONST64(0x02000080,0x00020002), CONST64(0x02000000,0x02020002), CONST64(0x02000080,0x02020002), + CONST64(0x02000000,0x00000202), CONST64(0x02000080,0x00000202), CONST64(0x02000000,0x02000202), CONST64(0x02000080,0x02000202), + CONST64(0x02000000,0x00020202), CONST64(0x02000080,0x00020202), CONST64(0x02000000,0x02020202), CONST64(0x02000080,0x02020202), + CONST64(0x00020000,0x00000000), CONST64(0x00020080,0x00000000), CONST64(0x00020000,0x02000000), CONST64(0x00020080,0x02000000), + CONST64(0x00020000,0x00020000), CONST64(0x00020080,0x00020000), CONST64(0x00020000,0x02020000), CONST64(0x00020080,0x02020000), + CONST64(0x00020000,0x00000200), CONST64(0x00020080,0x00000200), CONST64(0x00020000,0x02000200), CONST64(0x00020080,0x02000200), + CONST64(0x00020000,0x00020200), CONST64(0x00020080,0x00020200), CONST64(0x00020000,0x02020200), CONST64(0x00020080,0x02020200), + CONST64(0x00020000,0x00000002), CONST64(0x00020080,0x00000002), CONST64(0x00020000,0x02000002), CONST64(0x00020080,0x02000002), + CONST64(0x00020000,0x00020002), CONST64(0x00020080,0x00020002), CONST64(0x00020000,0x02020002), CONST64(0x00020080,0x02020002), + CONST64(0x00020000,0x00000202), CONST64(0x00020080,0x00000202), CONST64(0x00020000,0x02000202), CONST64(0x00020080,0x02000202), + CONST64(0x00020000,0x00020202), CONST64(0x00020080,0x00020202), CONST64(0x00020000,0x02020202), CONST64(0x00020080,0x02020202), + CONST64(0x02020000,0x00000000), CONST64(0x02020080,0x00000000), CONST64(0x02020000,0x02000000), CONST64(0x02020080,0x02000000), + CONST64(0x02020000,0x00020000), CONST64(0x02020080,0x00020000), CONST64(0x02020000,0x02020000), CONST64(0x02020080,0x02020000), + CONST64(0x02020000,0x00000200), CONST64(0x02020080,0x00000200), CONST64(0x02020000,0x02000200), CONST64(0x02020080,0x02000200), + CONST64(0x02020000,0x00020200), CONST64(0x02020080,0x00020200), CONST64(0x02020000,0x02020200), CONST64(0x02020080,0x02020200), + CONST64(0x02020000,0x00000002), CONST64(0x02020080,0x00000002), CONST64(0x02020000,0x02000002), CONST64(0x02020080,0x02000002), + CONST64(0x02020000,0x00020002), CONST64(0x02020080,0x00020002), CONST64(0x02020000,0x02020002), CONST64(0x02020080,0x02020002), + CONST64(0x02020000,0x00000202), CONST64(0x02020080,0x00000202), CONST64(0x02020000,0x02000202), CONST64(0x02020080,0x02000202), + CONST64(0x02020000,0x00020202), CONST64(0x02020080,0x00020202), CONST64(0x02020000,0x02020202), CONST64(0x02020080,0x02020202), + CONST64(0x00000200,0x00000000), CONST64(0x00000280,0x00000000), CONST64(0x00000200,0x02000000), CONST64(0x00000280,0x02000000), + CONST64(0x00000200,0x00020000), CONST64(0x00000280,0x00020000), CONST64(0x00000200,0x02020000), CONST64(0x00000280,0x02020000), + CONST64(0x00000200,0x00000200), CONST64(0x00000280,0x00000200), CONST64(0x00000200,0x02000200), CONST64(0x00000280,0x02000200), + CONST64(0x00000200,0x00020200), CONST64(0x00000280,0x00020200), CONST64(0x00000200,0x02020200), CONST64(0x00000280,0x02020200), + CONST64(0x00000200,0x00000002), CONST64(0x00000280,0x00000002), CONST64(0x00000200,0x02000002), CONST64(0x00000280,0x02000002), + CONST64(0x00000200,0x00020002), CONST64(0x00000280,0x00020002), CONST64(0x00000200,0x02020002), CONST64(0x00000280,0x02020002), + CONST64(0x00000200,0x00000202), CONST64(0x00000280,0x00000202), CONST64(0x00000200,0x02000202), CONST64(0x00000280,0x02000202), + CONST64(0x00000200,0x00020202), CONST64(0x00000280,0x00020202), CONST64(0x00000200,0x02020202), CONST64(0x00000280,0x02020202), + CONST64(0x02000200,0x00000000), CONST64(0x02000280,0x00000000), CONST64(0x02000200,0x02000000), CONST64(0x02000280,0x02000000), + CONST64(0x02000200,0x00020000), CONST64(0x02000280,0x00020000), CONST64(0x02000200,0x02020000), CONST64(0x02000280,0x02020000), + CONST64(0x02000200,0x00000200), CONST64(0x02000280,0x00000200), CONST64(0x02000200,0x02000200), CONST64(0x02000280,0x02000200), + CONST64(0x02000200,0x00020200), CONST64(0x02000280,0x00020200), CONST64(0x02000200,0x02020200), CONST64(0x02000280,0x02020200), + CONST64(0x02000200,0x00000002), CONST64(0x02000280,0x00000002), CONST64(0x02000200,0x02000002), CONST64(0x02000280,0x02000002), + CONST64(0x02000200,0x00020002), CONST64(0x02000280,0x00020002), CONST64(0x02000200,0x02020002), CONST64(0x02000280,0x02020002), + CONST64(0x02000200,0x00000202), CONST64(0x02000280,0x00000202), CONST64(0x02000200,0x02000202), CONST64(0x02000280,0x02000202), + CONST64(0x02000200,0x00020202), CONST64(0x02000280,0x00020202), CONST64(0x02000200,0x02020202), CONST64(0x02000280,0x02020202), + CONST64(0x00020200,0x00000000), CONST64(0x00020280,0x00000000), CONST64(0x00020200,0x02000000), CONST64(0x00020280,0x02000000), + CONST64(0x00020200,0x00020000), CONST64(0x00020280,0x00020000), CONST64(0x00020200,0x02020000), CONST64(0x00020280,0x02020000), + CONST64(0x00020200,0x00000200), CONST64(0x00020280,0x00000200), CONST64(0x00020200,0x02000200), CONST64(0x00020280,0x02000200), + CONST64(0x00020200,0x00020200), CONST64(0x00020280,0x00020200), CONST64(0x00020200,0x02020200), CONST64(0x00020280,0x02020200), + CONST64(0x00020200,0x00000002), CONST64(0x00020280,0x00000002), CONST64(0x00020200,0x02000002), CONST64(0x00020280,0x02000002), + CONST64(0x00020200,0x00020002), CONST64(0x00020280,0x00020002), CONST64(0x00020200,0x02020002), CONST64(0x00020280,0x02020002), + CONST64(0x00020200,0x00000202), CONST64(0x00020280,0x00000202), CONST64(0x00020200,0x02000202), CONST64(0x00020280,0x02000202), + CONST64(0x00020200,0x00020202), CONST64(0x00020280,0x00020202), CONST64(0x00020200,0x02020202), CONST64(0x00020280,0x02020202), + CONST64(0x02020200,0x00000000), CONST64(0x02020280,0x00000000), CONST64(0x02020200,0x02000000), CONST64(0x02020280,0x02000000), + CONST64(0x02020200,0x00020000), CONST64(0x02020280,0x00020000), CONST64(0x02020200,0x02020000), CONST64(0x02020280,0x02020000), + CONST64(0x02020200,0x00000200), CONST64(0x02020280,0x00000200), CONST64(0x02020200,0x02000200), CONST64(0x02020280,0x02000200), + CONST64(0x02020200,0x00020200), CONST64(0x02020280,0x00020200), CONST64(0x02020200,0x02020200), CONST64(0x02020280,0x02020200), + CONST64(0x02020200,0x00000002), CONST64(0x02020280,0x00000002), CONST64(0x02020200,0x02000002), CONST64(0x02020280,0x02000002), + CONST64(0x02020200,0x00020002), CONST64(0x02020280,0x00020002), CONST64(0x02020200,0x02020002), CONST64(0x02020280,0x02020002), + CONST64(0x02020200,0x00000202), CONST64(0x02020280,0x00000202), CONST64(0x02020200,0x02000202), CONST64(0x02020280,0x02000202), + CONST64(0x02020200,0x00020202), CONST64(0x02020280,0x00020202), CONST64(0x02020200,0x02020202), CONST64(0x02020280,0x02020202) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000002,0x00000000), CONST64(0x00000000,0x08000000), CONST64(0x00000002,0x08000000), + CONST64(0x00000000,0x00080000), CONST64(0x00000002,0x00080000), CONST64(0x00000000,0x08080000), CONST64(0x00000002,0x08080000), + CONST64(0x00000000,0x00000800), CONST64(0x00000002,0x00000800), CONST64(0x00000000,0x08000800), CONST64(0x00000002,0x08000800), + CONST64(0x00000000,0x00080800), CONST64(0x00000002,0x00080800), CONST64(0x00000000,0x08080800), CONST64(0x00000002,0x08080800), + CONST64(0x00000000,0x00000008), CONST64(0x00000002,0x00000008), CONST64(0x00000000,0x08000008), CONST64(0x00000002,0x08000008), + CONST64(0x00000000,0x00080008), CONST64(0x00000002,0x00080008), CONST64(0x00000000,0x08080008), CONST64(0x00000002,0x08080008), + CONST64(0x00000000,0x00000808), CONST64(0x00000002,0x00000808), CONST64(0x00000000,0x08000808), CONST64(0x00000002,0x08000808), + CONST64(0x00000000,0x00080808), CONST64(0x00000002,0x00080808), CONST64(0x00000000,0x08080808), CONST64(0x00000002,0x08080808), + CONST64(0x08000000,0x00000000), CONST64(0x08000002,0x00000000), CONST64(0x08000000,0x08000000), CONST64(0x08000002,0x08000000), + CONST64(0x08000000,0x00080000), CONST64(0x08000002,0x00080000), CONST64(0x08000000,0x08080000), CONST64(0x08000002,0x08080000), + CONST64(0x08000000,0x00000800), CONST64(0x08000002,0x00000800), CONST64(0x08000000,0x08000800), CONST64(0x08000002,0x08000800), + CONST64(0x08000000,0x00080800), CONST64(0x08000002,0x00080800), CONST64(0x08000000,0x08080800), CONST64(0x08000002,0x08080800), + CONST64(0x08000000,0x00000008), CONST64(0x08000002,0x00000008), CONST64(0x08000000,0x08000008), CONST64(0x08000002,0x08000008), + CONST64(0x08000000,0x00080008), CONST64(0x08000002,0x00080008), CONST64(0x08000000,0x08080008), CONST64(0x08000002,0x08080008), + CONST64(0x08000000,0x00000808), CONST64(0x08000002,0x00000808), CONST64(0x08000000,0x08000808), CONST64(0x08000002,0x08000808), + CONST64(0x08000000,0x00080808), CONST64(0x08000002,0x00080808), CONST64(0x08000000,0x08080808), CONST64(0x08000002,0x08080808), + CONST64(0x00080000,0x00000000), CONST64(0x00080002,0x00000000), CONST64(0x00080000,0x08000000), CONST64(0x00080002,0x08000000), + CONST64(0x00080000,0x00080000), CONST64(0x00080002,0x00080000), CONST64(0x00080000,0x08080000), CONST64(0x00080002,0x08080000), + CONST64(0x00080000,0x00000800), CONST64(0x00080002,0x00000800), CONST64(0x00080000,0x08000800), CONST64(0x00080002,0x08000800), + CONST64(0x00080000,0x00080800), CONST64(0x00080002,0x00080800), CONST64(0x00080000,0x08080800), CONST64(0x00080002,0x08080800), + CONST64(0x00080000,0x00000008), CONST64(0x00080002,0x00000008), CONST64(0x00080000,0x08000008), CONST64(0x00080002,0x08000008), + CONST64(0x00080000,0x00080008), CONST64(0x00080002,0x00080008), CONST64(0x00080000,0x08080008), CONST64(0x00080002,0x08080008), + CONST64(0x00080000,0x00000808), CONST64(0x00080002,0x00000808), CONST64(0x00080000,0x08000808), CONST64(0x00080002,0x08000808), + CONST64(0x00080000,0x00080808), CONST64(0x00080002,0x00080808), CONST64(0x00080000,0x08080808), CONST64(0x00080002,0x08080808), + CONST64(0x08080000,0x00000000), CONST64(0x08080002,0x00000000), CONST64(0x08080000,0x08000000), CONST64(0x08080002,0x08000000), + CONST64(0x08080000,0x00080000), CONST64(0x08080002,0x00080000), CONST64(0x08080000,0x08080000), CONST64(0x08080002,0x08080000), + CONST64(0x08080000,0x00000800), CONST64(0x08080002,0x00000800), CONST64(0x08080000,0x08000800), CONST64(0x08080002,0x08000800), + CONST64(0x08080000,0x00080800), CONST64(0x08080002,0x00080800), CONST64(0x08080000,0x08080800), CONST64(0x08080002,0x08080800), + CONST64(0x08080000,0x00000008), CONST64(0x08080002,0x00000008), CONST64(0x08080000,0x08000008), CONST64(0x08080002,0x08000008), + CONST64(0x08080000,0x00080008), CONST64(0x08080002,0x00080008), CONST64(0x08080000,0x08080008), CONST64(0x08080002,0x08080008), + CONST64(0x08080000,0x00000808), CONST64(0x08080002,0x00000808), CONST64(0x08080000,0x08000808), CONST64(0x08080002,0x08000808), + CONST64(0x08080000,0x00080808), CONST64(0x08080002,0x00080808), CONST64(0x08080000,0x08080808), CONST64(0x08080002,0x08080808), + CONST64(0x00000800,0x00000000), CONST64(0x00000802,0x00000000), CONST64(0x00000800,0x08000000), CONST64(0x00000802,0x08000000), + CONST64(0x00000800,0x00080000), CONST64(0x00000802,0x00080000), CONST64(0x00000800,0x08080000), CONST64(0x00000802,0x08080000), + CONST64(0x00000800,0x00000800), CONST64(0x00000802,0x00000800), CONST64(0x00000800,0x08000800), CONST64(0x00000802,0x08000800), + CONST64(0x00000800,0x00080800), CONST64(0x00000802,0x00080800), CONST64(0x00000800,0x08080800), CONST64(0x00000802,0x08080800), + CONST64(0x00000800,0x00000008), CONST64(0x00000802,0x00000008), CONST64(0x00000800,0x08000008), CONST64(0x00000802,0x08000008), + CONST64(0x00000800,0x00080008), CONST64(0x00000802,0x00080008), CONST64(0x00000800,0x08080008), CONST64(0x00000802,0x08080008), + CONST64(0x00000800,0x00000808), CONST64(0x00000802,0x00000808), CONST64(0x00000800,0x08000808), CONST64(0x00000802,0x08000808), + CONST64(0x00000800,0x00080808), CONST64(0x00000802,0x00080808), CONST64(0x00000800,0x08080808), CONST64(0x00000802,0x08080808), + CONST64(0x08000800,0x00000000), CONST64(0x08000802,0x00000000), CONST64(0x08000800,0x08000000), CONST64(0x08000802,0x08000000), + CONST64(0x08000800,0x00080000), CONST64(0x08000802,0x00080000), CONST64(0x08000800,0x08080000), CONST64(0x08000802,0x08080000), + CONST64(0x08000800,0x00000800), CONST64(0x08000802,0x00000800), CONST64(0x08000800,0x08000800), CONST64(0x08000802,0x08000800), + CONST64(0x08000800,0x00080800), CONST64(0x08000802,0x00080800), CONST64(0x08000800,0x08080800), CONST64(0x08000802,0x08080800), + CONST64(0x08000800,0x00000008), CONST64(0x08000802,0x00000008), CONST64(0x08000800,0x08000008), CONST64(0x08000802,0x08000008), + CONST64(0x08000800,0x00080008), CONST64(0x08000802,0x00080008), CONST64(0x08000800,0x08080008), CONST64(0x08000802,0x08080008), + CONST64(0x08000800,0x00000808), CONST64(0x08000802,0x00000808), CONST64(0x08000800,0x08000808), CONST64(0x08000802,0x08000808), + CONST64(0x08000800,0x00080808), CONST64(0x08000802,0x00080808), CONST64(0x08000800,0x08080808), CONST64(0x08000802,0x08080808), + CONST64(0x00080800,0x00000000), CONST64(0x00080802,0x00000000), CONST64(0x00080800,0x08000000), CONST64(0x00080802,0x08000000), + CONST64(0x00080800,0x00080000), CONST64(0x00080802,0x00080000), CONST64(0x00080800,0x08080000), CONST64(0x00080802,0x08080000), + CONST64(0x00080800,0x00000800), CONST64(0x00080802,0x00000800), CONST64(0x00080800,0x08000800), CONST64(0x00080802,0x08000800), + CONST64(0x00080800,0x00080800), CONST64(0x00080802,0x00080800), CONST64(0x00080800,0x08080800), CONST64(0x00080802,0x08080800), + CONST64(0x00080800,0x00000008), CONST64(0x00080802,0x00000008), CONST64(0x00080800,0x08000008), CONST64(0x00080802,0x08000008), + CONST64(0x00080800,0x00080008), CONST64(0x00080802,0x00080008), CONST64(0x00080800,0x08080008), CONST64(0x00080802,0x08080008), + CONST64(0x00080800,0x00000808), CONST64(0x00080802,0x00000808), CONST64(0x00080800,0x08000808), CONST64(0x00080802,0x08000808), + CONST64(0x00080800,0x00080808), CONST64(0x00080802,0x00080808), CONST64(0x00080800,0x08080808), CONST64(0x00080802,0x08080808), + CONST64(0x08080800,0x00000000), CONST64(0x08080802,0x00000000), CONST64(0x08080800,0x08000000), CONST64(0x08080802,0x08000000), + CONST64(0x08080800,0x00080000), CONST64(0x08080802,0x00080000), CONST64(0x08080800,0x08080000), CONST64(0x08080802,0x08080000), + CONST64(0x08080800,0x00000800), CONST64(0x08080802,0x00000800), CONST64(0x08080800,0x08000800), CONST64(0x08080802,0x08000800), + CONST64(0x08080800,0x00080800), CONST64(0x08080802,0x00080800), CONST64(0x08080800,0x08080800), CONST64(0x08080802,0x08080800), + CONST64(0x08080800,0x00000008), CONST64(0x08080802,0x00000008), CONST64(0x08080800,0x08000008), CONST64(0x08080802,0x08000008), + CONST64(0x08080800,0x00080008), CONST64(0x08080802,0x00080008), CONST64(0x08080800,0x08080008), CONST64(0x08080802,0x08080008), + CONST64(0x08080800,0x00000808), CONST64(0x08080802,0x00000808), CONST64(0x08080800,0x08000808), CONST64(0x08080802,0x08000808), + CONST64(0x08080800,0x00080808), CONST64(0x08080802,0x00080808), CONST64(0x08080800,0x08080808), CONST64(0x08080802,0x08080808) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000008,0x00000000), CONST64(0x00000000,0x20000000), CONST64(0x00000008,0x20000000), + CONST64(0x00000000,0x00200000), CONST64(0x00000008,0x00200000), CONST64(0x00000000,0x20200000), CONST64(0x00000008,0x20200000), + CONST64(0x00000000,0x00002000), CONST64(0x00000008,0x00002000), CONST64(0x00000000,0x20002000), CONST64(0x00000008,0x20002000), + CONST64(0x00000000,0x00202000), CONST64(0x00000008,0x00202000), CONST64(0x00000000,0x20202000), CONST64(0x00000008,0x20202000), + CONST64(0x00000000,0x00000020), CONST64(0x00000008,0x00000020), CONST64(0x00000000,0x20000020), CONST64(0x00000008,0x20000020), + CONST64(0x00000000,0x00200020), CONST64(0x00000008,0x00200020), CONST64(0x00000000,0x20200020), CONST64(0x00000008,0x20200020), + CONST64(0x00000000,0x00002020), CONST64(0x00000008,0x00002020), CONST64(0x00000000,0x20002020), CONST64(0x00000008,0x20002020), + CONST64(0x00000000,0x00202020), CONST64(0x00000008,0x00202020), CONST64(0x00000000,0x20202020), CONST64(0x00000008,0x20202020), + CONST64(0x20000000,0x00000000), CONST64(0x20000008,0x00000000), CONST64(0x20000000,0x20000000), CONST64(0x20000008,0x20000000), + CONST64(0x20000000,0x00200000), CONST64(0x20000008,0x00200000), CONST64(0x20000000,0x20200000), CONST64(0x20000008,0x20200000), + CONST64(0x20000000,0x00002000), CONST64(0x20000008,0x00002000), CONST64(0x20000000,0x20002000), CONST64(0x20000008,0x20002000), + CONST64(0x20000000,0x00202000), CONST64(0x20000008,0x00202000), CONST64(0x20000000,0x20202000), CONST64(0x20000008,0x20202000), + CONST64(0x20000000,0x00000020), CONST64(0x20000008,0x00000020), CONST64(0x20000000,0x20000020), CONST64(0x20000008,0x20000020), + CONST64(0x20000000,0x00200020), CONST64(0x20000008,0x00200020), CONST64(0x20000000,0x20200020), CONST64(0x20000008,0x20200020), + CONST64(0x20000000,0x00002020), CONST64(0x20000008,0x00002020), CONST64(0x20000000,0x20002020), CONST64(0x20000008,0x20002020), + CONST64(0x20000000,0x00202020), CONST64(0x20000008,0x00202020), CONST64(0x20000000,0x20202020), CONST64(0x20000008,0x20202020), + CONST64(0x00200000,0x00000000), CONST64(0x00200008,0x00000000), CONST64(0x00200000,0x20000000), CONST64(0x00200008,0x20000000), + CONST64(0x00200000,0x00200000), CONST64(0x00200008,0x00200000), CONST64(0x00200000,0x20200000), CONST64(0x00200008,0x20200000), + CONST64(0x00200000,0x00002000), CONST64(0x00200008,0x00002000), CONST64(0x00200000,0x20002000), CONST64(0x00200008,0x20002000), + CONST64(0x00200000,0x00202000), CONST64(0x00200008,0x00202000), CONST64(0x00200000,0x20202000), CONST64(0x00200008,0x20202000), + CONST64(0x00200000,0x00000020), CONST64(0x00200008,0x00000020), CONST64(0x00200000,0x20000020), CONST64(0x00200008,0x20000020), + CONST64(0x00200000,0x00200020), CONST64(0x00200008,0x00200020), CONST64(0x00200000,0x20200020), CONST64(0x00200008,0x20200020), + CONST64(0x00200000,0x00002020), CONST64(0x00200008,0x00002020), CONST64(0x00200000,0x20002020), CONST64(0x00200008,0x20002020), + CONST64(0x00200000,0x00202020), CONST64(0x00200008,0x00202020), CONST64(0x00200000,0x20202020), CONST64(0x00200008,0x20202020), + CONST64(0x20200000,0x00000000), CONST64(0x20200008,0x00000000), CONST64(0x20200000,0x20000000), CONST64(0x20200008,0x20000000), + CONST64(0x20200000,0x00200000), CONST64(0x20200008,0x00200000), CONST64(0x20200000,0x20200000), CONST64(0x20200008,0x20200000), + CONST64(0x20200000,0x00002000), CONST64(0x20200008,0x00002000), CONST64(0x20200000,0x20002000), CONST64(0x20200008,0x20002000), + CONST64(0x20200000,0x00202000), CONST64(0x20200008,0x00202000), CONST64(0x20200000,0x20202000), CONST64(0x20200008,0x20202000), + CONST64(0x20200000,0x00000020), CONST64(0x20200008,0x00000020), CONST64(0x20200000,0x20000020), CONST64(0x20200008,0x20000020), + CONST64(0x20200000,0x00200020), CONST64(0x20200008,0x00200020), CONST64(0x20200000,0x20200020), CONST64(0x20200008,0x20200020), + CONST64(0x20200000,0x00002020), CONST64(0x20200008,0x00002020), CONST64(0x20200000,0x20002020), CONST64(0x20200008,0x20002020), + CONST64(0x20200000,0x00202020), CONST64(0x20200008,0x00202020), CONST64(0x20200000,0x20202020), CONST64(0x20200008,0x20202020), + CONST64(0x00002000,0x00000000), CONST64(0x00002008,0x00000000), CONST64(0x00002000,0x20000000), CONST64(0x00002008,0x20000000), + CONST64(0x00002000,0x00200000), CONST64(0x00002008,0x00200000), CONST64(0x00002000,0x20200000), CONST64(0x00002008,0x20200000), + CONST64(0x00002000,0x00002000), CONST64(0x00002008,0x00002000), CONST64(0x00002000,0x20002000), CONST64(0x00002008,0x20002000), + CONST64(0x00002000,0x00202000), CONST64(0x00002008,0x00202000), CONST64(0x00002000,0x20202000), CONST64(0x00002008,0x20202000), + CONST64(0x00002000,0x00000020), CONST64(0x00002008,0x00000020), CONST64(0x00002000,0x20000020), CONST64(0x00002008,0x20000020), + CONST64(0x00002000,0x00200020), CONST64(0x00002008,0x00200020), CONST64(0x00002000,0x20200020), CONST64(0x00002008,0x20200020), + CONST64(0x00002000,0x00002020), CONST64(0x00002008,0x00002020), CONST64(0x00002000,0x20002020), CONST64(0x00002008,0x20002020), + CONST64(0x00002000,0x00202020), CONST64(0x00002008,0x00202020), CONST64(0x00002000,0x20202020), CONST64(0x00002008,0x20202020), + CONST64(0x20002000,0x00000000), CONST64(0x20002008,0x00000000), CONST64(0x20002000,0x20000000), CONST64(0x20002008,0x20000000), + CONST64(0x20002000,0x00200000), CONST64(0x20002008,0x00200000), CONST64(0x20002000,0x20200000), CONST64(0x20002008,0x20200000), + CONST64(0x20002000,0x00002000), CONST64(0x20002008,0x00002000), CONST64(0x20002000,0x20002000), CONST64(0x20002008,0x20002000), + CONST64(0x20002000,0x00202000), CONST64(0x20002008,0x00202000), CONST64(0x20002000,0x20202000), CONST64(0x20002008,0x20202000), + CONST64(0x20002000,0x00000020), CONST64(0x20002008,0x00000020), CONST64(0x20002000,0x20000020), CONST64(0x20002008,0x20000020), + CONST64(0x20002000,0x00200020), CONST64(0x20002008,0x00200020), CONST64(0x20002000,0x20200020), CONST64(0x20002008,0x20200020), + CONST64(0x20002000,0x00002020), CONST64(0x20002008,0x00002020), CONST64(0x20002000,0x20002020), CONST64(0x20002008,0x20002020), + CONST64(0x20002000,0x00202020), CONST64(0x20002008,0x00202020), CONST64(0x20002000,0x20202020), CONST64(0x20002008,0x20202020), + CONST64(0x00202000,0x00000000), CONST64(0x00202008,0x00000000), CONST64(0x00202000,0x20000000), CONST64(0x00202008,0x20000000), + CONST64(0x00202000,0x00200000), CONST64(0x00202008,0x00200000), CONST64(0x00202000,0x20200000), CONST64(0x00202008,0x20200000), + CONST64(0x00202000,0x00002000), CONST64(0x00202008,0x00002000), CONST64(0x00202000,0x20002000), CONST64(0x00202008,0x20002000), + CONST64(0x00202000,0x00202000), CONST64(0x00202008,0x00202000), CONST64(0x00202000,0x20202000), CONST64(0x00202008,0x20202000), + CONST64(0x00202000,0x00000020), CONST64(0x00202008,0x00000020), CONST64(0x00202000,0x20000020), CONST64(0x00202008,0x20000020), + CONST64(0x00202000,0x00200020), CONST64(0x00202008,0x00200020), CONST64(0x00202000,0x20200020), CONST64(0x00202008,0x20200020), + CONST64(0x00202000,0x00002020), CONST64(0x00202008,0x00002020), CONST64(0x00202000,0x20002020), CONST64(0x00202008,0x20002020), + CONST64(0x00202000,0x00202020), CONST64(0x00202008,0x00202020), CONST64(0x00202000,0x20202020), CONST64(0x00202008,0x20202020), + CONST64(0x20202000,0x00000000), CONST64(0x20202008,0x00000000), CONST64(0x20202000,0x20000000), CONST64(0x20202008,0x20000000), + CONST64(0x20202000,0x00200000), CONST64(0x20202008,0x00200000), CONST64(0x20202000,0x20200000), CONST64(0x20202008,0x20200000), + CONST64(0x20202000,0x00002000), CONST64(0x20202008,0x00002000), CONST64(0x20202000,0x20002000), CONST64(0x20202008,0x20002000), + CONST64(0x20202000,0x00202000), CONST64(0x20202008,0x00202000), CONST64(0x20202000,0x20202000), CONST64(0x20202008,0x20202000), + CONST64(0x20202000,0x00000020), CONST64(0x20202008,0x00000020), CONST64(0x20202000,0x20000020), CONST64(0x20202008,0x20000020), + CONST64(0x20202000,0x00200020), CONST64(0x20202008,0x00200020), CONST64(0x20202000,0x20200020), CONST64(0x20202008,0x20200020), + CONST64(0x20202000,0x00002020), CONST64(0x20202008,0x00002020), CONST64(0x20202000,0x20002020), CONST64(0x20202008,0x20002020), + CONST64(0x20202000,0x00202020), CONST64(0x20202008,0x00202020), CONST64(0x20202000,0x20202020), CONST64(0x20202008,0x20202020) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000020,0x00000000), CONST64(0x00000000,0x80000000), CONST64(0x00000020,0x80000000), + CONST64(0x00000000,0x00800000), CONST64(0x00000020,0x00800000), CONST64(0x00000000,0x80800000), CONST64(0x00000020,0x80800000), + CONST64(0x00000000,0x00008000), CONST64(0x00000020,0x00008000), CONST64(0x00000000,0x80008000), CONST64(0x00000020,0x80008000), + CONST64(0x00000000,0x00808000), CONST64(0x00000020,0x00808000), CONST64(0x00000000,0x80808000), CONST64(0x00000020,0x80808000), + CONST64(0x00000000,0x00000080), CONST64(0x00000020,0x00000080), CONST64(0x00000000,0x80000080), CONST64(0x00000020,0x80000080), + CONST64(0x00000000,0x00800080), CONST64(0x00000020,0x00800080), CONST64(0x00000000,0x80800080), CONST64(0x00000020,0x80800080), + CONST64(0x00000000,0x00008080), CONST64(0x00000020,0x00008080), CONST64(0x00000000,0x80008080), CONST64(0x00000020,0x80008080), + CONST64(0x00000000,0x00808080), CONST64(0x00000020,0x00808080), CONST64(0x00000000,0x80808080), CONST64(0x00000020,0x80808080), + CONST64(0x80000000,0x00000000), CONST64(0x80000020,0x00000000), CONST64(0x80000000,0x80000000), CONST64(0x80000020,0x80000000), + CONST64(0x80000000,0x00800000), CONST64(0x80000020,0x00800000), CONST64(0x80000000,0x80800000), CONST64(0x80000020,0x80800000), + CONST64(0x80000000,0x00008000), CONST64(0x80000020,0x00008000), CONST64(0x80000000,0x80008000), CONST64(0x80000020,0x80008000), + CONST64(0x80000000,0x00808000), CONST64(0x80000020,0x00808000), CONST64(0x80000000,0x80808000), CONST64(0x80000020,0x80808000), + CONST64(0x80000000,0x00000080), CONST64(0x80000020,0x00000080), CONST64(0x80000000,0x80000080), CONST64(0x80000020,0x80000080), + CONST64(0x80000000,0x00800080), CONST64(0x80000020,0x00800080), CONST64(0x80000000,0x80800080), CONST64(0x80000020,0x80800080), + CONST64(0x80000000,0x00008080), CONST64(0x80000020,0x00008080), CONST64(0x80000000,0x80008080), CONST64(0x80000020,0x80008080), + CONST64(0x80000000,0x00808080), CONST64(0x80000020,0x00808080), CONST64(0x80000000,0x80808080), CONST64(0x80000020,0x80808080), + CONST64(0x00800000,0x00000000), CONST64(0x00800020,0x00000000), CONST64(0x00800000,0x80000000), CONST64(0x00800020,0x80000000), + CONST64(0x00800000,0x00800000), CONST64(0x00800020,0x00800000), CONST64(0x00800000,0x80800000), CONST64(0x00800020,0x80800000), + CONST64(0x00800000,0x00008000), CONST64(0x00800020,0x00008000), CONST64(0x00800000,0x80008000), CONST64(0x00800020,0x80008000), + CONST64(0x00800000,0x00808000), CONST64(0x00800020,0x00808000), CONST64(0x00800000,0x80808000), CONST64(0x00800020,0x80808000), + CONST64(0x00800000,0x00000080), CONST64(0x00800020,0x00000080), CONST64(0x00800000,0x80000080), CONST64(0x00800020,0x80000080), + CONST64(0x00800000,0x00800080), CONST64(0x00800020,0x00800080), CONST64(0x00800000,0x80800080), CONST64(0x00800020,0x80800080), + CONST64(0x00800000,0x00008080), CONST64(0x00800020,0x00008080), CONST64(0x00800000,0x80008080), CONST64(0x00800020,0x80008080), + CONST64(0x00800000,0x00808080), CONST64(0x00800020,0x00808080), CONST64(0x00800000,0x80808080), CONST64(0x00800020,0x80808080), + CONST64(0x80800000,0x00000000), CONST64(0x80800020,0x00000000), CONST64(0x80800000,0x80000000), CONST64(0x80800020,0x80000000), + CONST64(0x80800000,0x00800000), CONST64(0x80800020,0x00800000), CONST64(0x80800000,0x80800000), CONST64(0x80800020,0x80800000), + CONST64(0x80800000,0x00008000), CONST64(0x80800020,0x00008000), CONST64(0x80800000,0x80008000), CONST64(0x80800020,0x80008000), + CONST64(0x80800000,0x00808000), CONST64(0x80800020,0x00808000), CONST64(0x80800000,0x80808000), CONST64(0x80800020,0x80808000), + CONST64(0x80800000,0x00000080), CONST64(0x80800020,0x00000080), CONST64(0x80800000,0x80000080), CONST64(0x80800020,0x80000080), + CONST64(0x80800000,0x00800080), CONST64(0x80800020,0x00800080), CONST64(0x80800000,0x80800080), CONST64(0x80800020,0x80800080), + CONST64(0x80800000,0x00008080), CONST64(0x80800020,0x00008080), CONST64(0x80800000,0x80008080), CONST64(0x80800020,0x80008080), + CONST64(0x80800000,0x00808080), CONST64(0x80800020,0x00808080), CONST64(0x80800000,0x80808080), CONST64(0x80800020,0x80808080), + CONST64(0x00008000,0x00000000), CONST64(0x00008020,0x00000000), CONST64(0x00008000,0x80000000), CONST64(0x00008020,0x80000000), + CONST64(0x00008000,0x00800000), CONST64(0x00008020,0x00800000), CONST64(0x00008000,0x80800000), CONST64(0x00008020,0x80800000), + CONST64(0x00008000,0x00008000), CONST64(0x00008020,0x00008000), CONST64(0x00008000,0x80008000), CONST64(0x00008020,0x80008000), + CONST64(0x00008000,0x00808000), CONST64(0x00008020,0x00808000), CONST64(0x00008000,0x80808000), CONST64(0x00008020,0x80808000), + CONST64(0x00008000,0x00000080), CONST64(0x00008020,0x00000080), CONST64(0x00008000,0x80000080), CONST64(0x00008020,0x80000080), + CONST64(0x00008000,0x00800080), CONST64(0x00008020,0x00800080), CONST64(0x00008000,0x80800080), CONST64(0x00008020,0x80800080), + CONST64(0x00008000,0x00008080), CONST64(0x00008020,0x00008080), CONST64(0x00008000,0x80008080), CONST64(0x00008020,0x80008080), + CONST64(0x00008000,0x00808080), CONST64(0x00008020,0x00808080), CONST64(0x00008000,0x80808080), CONST64(0x00008020,0x80808080), + CONST64(0x80008000,0x00000000), CONST64(0x80008020,0x00000000), CONST64(0x80008000,0x80000000), CONST64(0x80008020,0x80000000), + CONST64(0x80008000,0x00800000), CONST64(0x80008020,0x00800000), CONST64(0x80008000,0x80800000), CONST64(0x80008020,0x80800000), + CONST64(0x80008000,0x00008000), CONST64(0x80008020,0x00008000), CONST64(0x80008000,0x80008000), CONST64(0x80008020,0x80008000), + CONST64(0x80008000,0x00808000), CONST64(0x80008020,0x00808000), CONST64(0x80008000,0x80808000), CONST64(0x80008020,0x80808000), + CONST64(0x80008000,0x00000080), CONST64(0x80008020,0x00000080), CONST64(0x80008000,0x80000080), CONST64(0x80008020,0x80000080), + CONST64(0x80008000,0x00800080), CONST64(0x80008020,0x00800080), CONST64(0x80008000,0x80800080), CONST64(0x80008020,0x80800080), + CONST64(0x80008000,0x00008080), CONST64(0x80008020,0x00008080), CONST64(0x80008000,0x80008080), CONST64(0x80008020,0x80008080), + CONST64(0x80008000,0x00808080), CONST64(0x80008020,0x00808080), CONST64(0x80008000,0x80808080), CONST64(0x80008020,0x80808080), + CONST64(0x00808000,0x00000000), CONST64(0x00808020,0x00000000), CONST64(0x00808000,0x80000000), CONST64(0x00808020,0x80000000), + CONST64(0x00808000,0x00800000), CONST64(0x00808020,0x00800000), CONST64(0x00808000,0x80800000), CONST64(0x00808020,0x80800000), + CONST64(0x00808000,0x00008000), CONST64(0x00808020,0x00008000), CONST64(0x00808000,0x80008000), CONST64(0x00808020,0x80008000), + CONST64(0x00808000,0x00808000), CONST64(0x00808020,0x00808000), CONST64(0x00808000,0x80808000), CONST64(0x00808020,0x80808000), + CONST64(0x00808000,0x00000080), CONST64(0x00808020,0x00000080), CONST64(0x00808000,0x80000080), CONST64(0x00808020,0x80000080), + CONST64(0x00808000,0x00800080), CONST64(0x00808020,0x00800080), CONST64(0x00808000,0x80800080), CONST64(0x00808020,0x80800080), + CONST64(0x00808000,0x00008080), CONST64(0x00808020,0x00008080), CONST64(0x00808000,0x80008080), CONST64(0x00808020,0x80008080), + CONST64(0x00808000,0x00808080), CONST64(0x00808020,0x00808080), CONST64(0x00808000,0x80808080), CONST64(0x00808020,0x80808080), + CONST64(0x80808000,0x00000000), CONST64(0x80808020,0x00000000), CONST64(0x80808000,0x80000000), CONST64(0x80808020,0x80000000), + CONST64(0x80808000,0x00800000), CONST64(0x80808020,0x00800000), CONST64(0x80808000,0x80800000), CONST64(0x80808020,0x80800000), + CONST64(0x80808000,0x00008000), CONST64(0x80808020,0x00008000), CONST64(0x80808000,0x80008000), CONST64(0x80808020,0x80008000), + CONST64(0x80808000,0x00808000), CONST64(0x80808020,0x00808000), CONST64(0x80808000,0x80808000), CONST64(0x80808020,0x80808000), + CONST64(0x80808000,0x00000080), CONST64(0x80808020,0x00000080), CONST64(0x80808000,0x80000080), CONST64(0x80808020,0x80000080), + CONST64(0x80808000,0x00800080), CONST64(0x80808020,0x00800080), CONST64(0x80808000,0x80800080), CONST64(0x80808020,0x80800080), + CONST64(0x80808000,0x00008080), CONST64(0x80808020,0x00008080), CONST64(0x80808000,0x80008080), CONST64(0x80808020,0x80008080), + CONST64(0x80808000,0x00808080), CONST64(0x80808020,0x00808080), CONST64(0x80808000,0x80808080), CONST64(0x80808020,0x80808080) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000040,0x00000000), CONST64(0x00000000,0x01000000), CONST64(0x00000040,0x01000000), + CONST64(0x00000000,0x00010000), CONST64(0x00000040,0x00010000), CONST64(0x00000000,0x01010000), CONST64(0x00000040,0x01010000), + CONST64(0x00000000,0x00000100), CONST64(0x00000040,0x00000100), CONST64(0x00000000,0x01000100), CONST64(0x00000040,0x01000100), + CONST64(0x00000000,0x00010100), CONST64(0x00000040,0x00010100), CONST64(0x00000000,0x01010100), CONST64(0x00000040,0x01010100), + CONST64(0x00000000,0x00000001), CONST64(0x00000040,0x00000001), CONST64(0x00000000,0x01000001), CONST64(0x00000040,0x01000001), + CONST64(0x00000000,0x00010001), CONST64(0x00000040,0x00010001), CONST64(0x00000000,0x01010001), CONST64(0x00000040,0x01010001), + CONST64(0x00000000,0x00000101), CONST64(0x00000040,0x00000101), CONST64(0x00000000,0x01000101), CONST64(0x00000040,0x01000101), + CONST64(0x00000000,0x00010101), CONST64(0x00000040,0x00010101), CONST64(0x00000000,0x01010101), CONST64(0x00000040,0x01010101), + CONST64(0x01000000,0x00000000), CONST64(0x01000040,0x00000000), CONST64(0x01000000,0x01000000), CONST64(0x01000040,0x01000000), + CONST64(0x01000000,0x00010000), CONST64(0x01000040,0x00010000), CONST64(0x01000000,0x01010000), CONST64(0x01000040,0x01010000), + CONST64(0x01000000,0x00000100), CONST64(0x01000040,0x00000100), CONST64(0x01000000,0x01000100), CONST64(0x01000040,0x01000100), + CONST64(0x01000000,0x00010100), CONST64(0x01000040,0x00010100), CONST64(0x01000000,0x01010100), CONST64(0x01000040,0x01010100), + CONST64(0x01000000,0x00000001), CONST64(0x01000040,0x00000001), CONST64(0x01000000,0x01000001), CONST64(0x01000040,0x01000001), + CONST64(0x01000000,0x00010001), CONST64(0x01000040,0x00010001), CONST64(0x01000000,0x01010001), CONST64(0x01000040,0x01010001), + CONST64(0x01000000,0x00000101), CONST64(0x01000040,0x00000101), CONST64(0x01000000,0x01000101), CONST64(0x01000040,0x01000101), + CONST64(0x01000000,0x00010101), CONST64(0x01000040,0x00010101), CONST64(0x01000000,0x01010101), CONST64(0x01000040,0x01010101), + CONST64(0x00010000,0x00000000), CONST64(0x00010040,0x00000000), CONST64(0x00010000,0x01000000), CONST64(0x00010040,0x01000000), + CONST64(0x00010000,0x00010000), CONST64(0x00010040,0x00010000), CONST64(0x00010000,0x01010000), CONST64(0x00010040,0x01010000), + CONST64(0x00010000,0x00000100), CONST64(0x00010040,0x00000100), CONST64(0x00010000,0x01000100), CONST64(0x00010040,0x01000100), + CONST64(0x00010000,0x00010100), CONST64(0x00010040,0x00010100), CONST64(0x00010000,0x01010100), CONST64(0x00010040,0x01010100), + CONST64(0x00010000,0x00000001), CONST64(0x00010040,0x00000001), CONST64(0x00010000,0x01000001), CONST64(0x00010040,0x01000001), + CONST64(0x00010000,0x00010001), CONST64(0x00010040,0x00010001), CONST64(0x00010000,0x01010001), CONST64(0x00010040,0x01010001), + CONST64(0x00010000,0x00000101), CONST64(0x00010040,0x00000101), CONST64(0x00010000,0x01000101), CONST64(0x00010040,0x01000101), + CONST64(0x00010000,0x00010101), CONST64(0x00010040,0x00010101), CONST64(0x00010000,0x01010101), CONST64(0x00010040,0x01010101), + CONST64(0x01010000,0x00000000), CONST64(0x01010040,0x00000000), CONST64(0x01010000,0x01000000), CONST64(0x01010040,0x01000000), + CONST64(0x01010000,0x00010000), CONST64(0x01010040,0x00010000), CONST64(0x01010000,0x01010000), CONST64(0x01010040,0x01010000), + CONST64(0x01010000,0x00000100), CONST64(0x01010040,0x00000100), CONST64(0x01010000,0x01000100), CONST64(0x01010040,0x01000100), + CONST64(0x01010000,0x00010100), CONST64(0x01010040,0x00010100), CONST64(0x01010000,0x01010100), CONST64(0x01010040,0x01010100), + CONST64(0x01010000,0x00000001), CONST64(0x01010040,0x00000001), CONST64(0x01010000,0x01000001), CONST64(0x01010040,0x01000001), + CONST64(0x01010000,0x00010001), CONST64(0x01010040,0x00010001), CONST64(0x01010000,0x01010001), CONST64(0x01010040,0x01010001), + CONST64(0x01010000,0x00000101), CONST64(0x01010040,0x00000101), CONST64(0x01010000,0x01000101), CONST64(0x01010040,0x01000101), + CONST64(0x01010000,0x00010101), CONST64(0x01010040,0x00010101), CONST64(0x01010000,0x01010101), CONST64(0x01010040,0x01010101), + CONST64(0x00000100,0x00000000), CONST64(0x00000140,0x00000000), CONST64(0x00000100,0x01000000), CONST64(0x00000140,0x01000000), + CONST64(0x00000100,0x00010000), CONST64(0x00000140,0x00010000), CONST64(0x00000100,0x01010000), CONST64(0x00000140,0x01010000), + CONST64(0x00000100,0x00000100), CONST64(0x00000140,0x00000100), CONST64(0x00000100,0x01000100), CONST64(0x00000140,0x01000100), + CONST64(0x00000100,0x00010100), CONST64(0x00000140,0x00010100), CONST64(0x00000100,0x01010100), CONST64(0x00000140,0x01010100), + CONST64(0x00000100,0x00000001), CONST64(0x00000140,0x00000001), CONST64(0x00000100,0x01000001), CONST64(0x00000140,0x01000001), + CONST64(0x00000100,0x00010001), CONST64(0x00000140,0x00010001), CONST64(0x00000100,0x01010001), CONST64(0x00000140,0x01010001), + CONST64(0x00000100,0x00000101), CONST64(0x00000140,0x00000101), CONST64(0x00000100,0x01000101), CONST64(0x00000140,0x01000101), + CONST64(0x00000100,0x00010101), CONST64(0x00000140,0x00010101), CONST64(0x00000100,0x01010101), CONST64(0x00000140,0x01010101), + CONST64(0x01000100,0x00000000), CONST64(0x01000140,0x00000000), CONST64(0x01000100,0x01000000), CONST64(0x01000140,0x01000000), + CONST64(0x01000100,0x00010000), CONST64(0x01000140,0x00010000), CONST64(0x01000100,0x01010000), CONST64(0x01000140,0x01010000), + CONST64(0x01000100,0x00000100), CONST64(0x01000140,0x00000100), CONST64(0x01000100,0x01000100), CONST64(0x01000140,0x01000100), + CONST64(0x01000100,0x00010100), CONST64(0x01000140,0x00010100), CONST64(0x01000100,0x01010100), CONST64(0x01000140,0x01010100), + CONST64(0x01000100,0x00000001), CONST64(0x01000140,0x00000001), CONST64(0x01000100,0x01000001), CONST64(0x01000140,0x01000001), + CONST64(0x01000100,0x00010001), CONST64(0x01000140,0x00010001), CONST64(0x01000100,0x01010001), CONST64(0x01000140,0x01010001), + CONST64(0x01000100,0x00000101), CONST64(0x01000140,0x00000101), CONST64(0x01000100,0x01000101), CONST64(0x01000140,0x01000101), + CONST64(0x01000100,0x00010101), CONST64(0x01000140,0x00010101), CONST64(0x01000100,0x01010101), CONST64(0x01000140,0x01010101), + CONST64(0x00010100,0x00000000), CONST64(0x00010140,0x00000000), CONST64(0x00010100,0x01000000), CONST64(0x00010140,0x01000000), + CONST64(0x00010100,0x00010000), CONST64(0x00010140,0x00010000), CONST64(0x00010100,0x01010000), CONST64(0x00010140,0x01010000), + CONST64(0x00010100,0x00000100), CONST64(0x00010140,0x00000100), CONST64(0x00010100,0x01000100), CONST64(0x00010140,0x01000100), + CONST64(0x00010100,0x00010100), CONST64(0x00010140,0x00010100), CONST64(0x00010100,0x01010100), CONST64(0x00010140,0x01010100), + CONST64(0x00010100,0x00000001), CONST64(0x00010140,0x00000001), CONST64(0x00010100,0x01000001), CONST64(0x00010140,0x01000001), + CONST64(0x00010100,0x00010001), CONST64(0x00010140,0x00010001), CONST64(0x00010100,0x01010001), CONST64(0x00010140,0x01010001), + CONST64(0x00010100,0x00000101), CONST64(0x00010140,0x00000101), CONST64(0x00010100,0x01000101), CONST64(0x00010140,0x01000101), + CONST64(0x00010100,0x00010101), CONST64(0x00010140,0x00010101), CONST64(0x00010100,0x01010101), CONST64(0x00010140,0x01010101), + CONST64(0x01010100,0x00000000), CONST64(0x01010140,0x00000000), CONST64(0x01010100,0x01000000), CONST64(0x01010140,0x01000000), + CONST64(0x01010100,0x00010000), CONST64(0x01010140,0x00010000), CONST64(0x01010100,0x01010000), CONST64(0x01010140,0x01010000), + CONST64(0x01010100,0x00000100), CONST64(0x01010140,0x00000100), CONST64(0x01010100,0x01000100), CONST64(0x01010140,0x01000100), + CONST64(0x01010100,0x00010100), CONST64(0x01010140,0x00010100), CONST64(0x01010100,0x01010100), CONST64(0x01010140,0x01010100), + CONST64(0x01010100,0x00000001), CONST64(0x01010140,0x00000001), CONST64(0x01010100,0x01000001), CONST64(0x01010140,0x01000001), + CONST64(0x01010100,0x00010001), CONST64(0x01010140,0x00010001), CONST64(0x01010100,0x01010001), CONST64(0x01010140,0x01010001), + CONST64(0x01010100,0x00000101), CONST64(0x01010140,0x00000101), CONST64(0x01010100,0x01000101), CONST64(0x01010140,0x01000101), + CONST64(0x01010100,0x00010101), CONST64(0x01010140,0x00010101), CONST64(0x01010100,0x01010101), CONST64(0x01010140,0x01010101) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000001,0x00000000), CONST64(0x00000000,0x04000000), CONST64(0x00000001,0x04000000), + CONST64(0x00000000,0x00040000), CONST64(0x00000001,0x00040000), CONST64(0x00000000,0x04040000), CONST64(0x00000001,0x04040000), + CONST64(0x00000000,0x00000400), CONST64(0x00000001,0x00000400), CONST64(0x00000000,0x04000400), CONST64(0x00000001,0x04000400), + CONST64(0x00000000,0x00040400), CONST64(0x00000001,0x00040400), CONST64(0x00000000,0x04040400), CONST64(0x00000001,0x04040400), + CONST64(0x00000000,0x00000004), CONST64(0x00000001,0x00000004), CONST64(0x00000000,0x04000004), CONST64(0x00000001,0x04000004), + CONST64(0x00000000,0x00040004), CONST64(0x00000001,0x00040004), CONST64(0x00000000,0x04040004), CONST64(0x00000001,0x04040004), + CONST64(0x00000000,0x00000404), CONST64(0x00000001,0x00000404), CONST64(0x00000000,0x04000404), CONST64(0x00000001,0x04000404), + CONST64(0x00000000,0x00040404), CONST64(0x00000001,0x00040404), CONST64(0x00000000,0x04040404), CONST64(0x00000001,0x04040404), + CONST64(0x04000000,0x00000000), CONST64(0x04000001,0x00000000), CONST64(0x04000000,0x04000000), CONST64(0x04000001,0x04000000), + CONST64(0x04000000,0x00040000), CONST64(0x04000001,0x00040000), CONST64(0x04000000,0x04040000), CONST64(0x04000001,0x04040000), + CONST64(0x04000000,0x00000400), CONST64(0x04000001,0x00000400), CONST64(0x04000000,0x04000400), CONST64(0x04000001,0x04000400), + CONST64(0x04000000,0x00040400), CONST64(0x04000001,0x00040400), CONST64(0x04000000,0x04040400), CONST64(0x04000001,0x04040400), + CONST64(0x04000000,0x00000004), CONST64(0x04000001,0x00000004), CONST64(0x04000000,0x04000004), CONST64(0x04000001,0x04000004), + CONST64(0x04000000,0x00040004), CONST64(0x04000001,0x00040004), CONST64(0x04000000,0x04040004), CONST64(0x04000001,0x04040004), + CONST64(0x04000000,0x00000404), CONST64(0x04000001,0x00000404), CONST64(0x04000000,0x04000404), CONST64(0x04000001,0x04000404), + CONST64(0x04000000,0x00040404), CONST64(0x04000001,0x00040404), CONST64(0x04000000,0x04040404), CONST64(0x04000001,0x04040404), + CONST64(0x00040000,0x00000000), CONST64(0x00040001,0x00000000), CONST64(0x00040000,0x04000000), CONST64(0x00040001,0x04000000), + CONST64(0x00040000,0x00040000), CONST64(0x00040001,0x00040000), CONST64(0x00040000,0x04040000), CONST64(0x00040001,0x04040000), + CONST64(0x00040000,0x00000400), CONST64(0x00040001,0x00000400), CONST64(0x00040000,0x04000400), CONST64(0x00040001,0x04000400), + CONST64(0x00040000,0x00040400), CONST64(0x00040001,0x00040400), CONST64(0x00040000,0x04040400), CONST64(0x00040001,0x04040400), + CONST64(0x00040000,0x00000004), CONST64(0x00040001,0x00000004), CONST64(0x00040000,0x04000004), CONST64(0x00040001,0x04000004), + CONST64(0x00040000,0x00040004), CONST64(0x00040001,0x00040004), CONST64(0x00040000,0x04040004), CONST64(0x00040001,0x04040004), + CONST64(0x00040000,0x00000404), CONST64(0x00040001,0x00000404), CONST64(0x00040000,0x04000404), CONST64(0x00040001,0x04000404), + CONST64(0x00040000,0x00040404), CONST64(0x00040001,0x00040404), CONST64(0x00040000,0x04040404), CONST64(0x00040001,0x04040404), + CONST64(0x04040000,0x00000000), CONST64(0x04040001,0x00000000), CONST64(0x04040000,0x04000000), CONST64(0x04040001,0x04000000), + CONST64(0x04040000,0x00040000), CONST64(0x04040001,0x00040000), CONST64(0x04040000,0x04040000), CONST64(0x04040001,0x04040000), + CONST64(0x04040000,0x00000400), CONST64(0x04040001,0x00000400), CONST64(0x04040000,0x04000400), CONST64(0x04040001,0x04000400), + CONST64(0x04040000,0x00040400), CONST64(0x04040001,0x00040400), CONST64(0x04040000,0x04040400), CONST64(0x04040001,0x04040400), + CONST64(0x04040000,0x00000004), CONST64(0x04040001,0x00000004), CONST64(0x04040000,0x04000004), CONST64(0x04040001,0x04000004), + CONST64(0x04040000,0x00040004), CONST64(0x04040001,0x00040004), CONST64(0x04040000,0x04040004), CONST64(0x04040001,0x04040004), + CONST64(0x04040000,0x00000404), CONST64(0x04040001,0x00000404), CONST64(0x04040000,0x04000404), CONST64(0x04040001,0x04000404), + CONST64(0x04040000,0x00040404), CONST64(0x04040001,0x00040404), CONST64(0x04040000,0x04040404), CONST64(0x04040001,0x04040404), + CONST64(0x00000400,0x00000000), CONST64(0x00000401,0x00000000), CONST64(0x00000400,0x04000000), CONST64(0x00000401,0x04000000), + CONST64(0x00000400,0x00040000), CONST64(0x00000401,0x00040000), CONST64(0x00000400,0x04040000), CONST64(0x00000401,0x04040000), + CONST64(0x00000400,0x00000400), CONST64(0x00000401,0x00000400), CONST64(0x00000400,0x04000400), CONST64(0x00000401,0x04000400), + CONST64(0x00000400,0x00040400), CONST64(0x00000401,0x00040400), CONST64(0x00000400,0x04040400), CONST64(0x00000401,0x04040400), + CONST64(0x00000400,0x00000004), CONST64(0x00000401,0x00000004), CONST64(0x00000400,0x04000004), CONST64(0x00000401,0x04000004), + CONST64(0x00000400,0x00040004), CONST64(0x00000401,0x00040004), CONST64(0x00000400,0x04040004), CONST64(0x00000401,0x04040004), + CONST64(0x00000400,0x00000404), CONST64(0x00000401,0x00000404), CONST64(0x00000400,0x04000404), CONST64(0x00000401,0x04000404), + CONST64(0x00000400,0x00040404), CONST64(0x00000401,0x00040404), CONST64(0x00000400,0x04040404), CONST64(0x00000401,0x04040404), + CONST64(0x04000400,0x00000000), CONST64(0x04000401,0x00000000), CONST64(0x04000400,0x04000000), CONST64(0x04000401,0x04000000), + CONST64(0x04000400,0x00040000), CONST64(0x04000401,0x00040000), CONST64(0x04000400,0x04040000), CONST64(0x04000401,0x04040000), + CONST64(0x04000400,0x00000400), CONST64(0x04000401,0x00000400), CONST64(0x04000400,0x04000400), CONST64(0x04000401,0x04000400), + CONST64(0x04000400,0x00040400), CONST64(0x04000401,0x00040400), CONST64(0x04000400,0x04040400), CONST64(0x04000401,0x04040400), + CONST64(0x04000400,0x00000004), CONST64(0x04000401,0x00000004), CONST64(0x04000400,0x04000004), CONST64(0x04000401,0x04000004), + CONST64(0x04000400,0x00040004), CONST64(0x04000401,0x00040004), CONST64(0x04000400,0x04040004), CONST64(0x04000401,0x04040004), + CONST64(0x04000400,0x00000404), CONST64(0x04000401,0x00000404), CONST64(0x04000400,0x04000404), CONST64(0x04000401,0x04000404), + CONST64(0x04000400,0x00040404), CONST64(0x04000401,0x00040404), CONST64(0x04000400,0x04040404), CONST64(0x04000401,0x04040404), + CONST64(0x00040400,0x00000000), CONST64(0x00040401,0x00000000), CONST64(0x00040400,0x04000000), CONST64(0x00040401,0x04000000), + CONST64(0x00040400,0x00040000), CONST64(0x00040401,0x00040000), CONST64(0x00040400,0x04040000), CONST64(0x00040401,0x04040000), + CONST64(0x00040400,0x00000400), CONST64(0x00040401,0x00000400), CONST64(0x00040400,0x04000400), CONST64(0x00040401,0x04000400), + CONST64(0x00040400,0x00040400), CONST64(0x00040401,0x00040400), CONST64(0x00040400,0x04040400), CONST64(0x00040401,0x04040400), + CONST64(0x00040400,0x00000004), CONST64(0x00040401,0x00000004), CONST64(0x00040400,0x04000004), CONST64(0x00040401,0x04000004), + CONST64(0x00040400,0x00040004), CONST64(0x00040401,0x00040004), CONST64(0x00040400,0x04040004), CONST64(0x00040401,0x04040004), + CONST64(0x00040400,0x00000404), CONST64(0x00040401,0x00000404), CONST64(0x00040400,0x04000404), CONST64(0x00040401,0x04000404), + CONST64(0x00040400,0x00040404), CONST64(0x00040401,0x00040404), CONST64(0x00040400,0x04040404), CONST64(0x00040401,0x04040404), + CONST64(0x04040400,0x00000000), CONST64(0x04040401,0x00000000), CONST64(0x04040400,0x04000000), CONST64(0x04040401,0x04000000), + CONST64(0x04040400,0x00040000), CONST64(0x04040401,0x00040000), CONST64(0x04040400,0x04040000), CONST64(0x04040401,0x04040000), + CONST64(0x04040400,0x00000400), CONST64(0x04040401,0x00000400), CONST64(0x04040400,0x04000400), CONST64(0x04040401,0x04000400), + CONST64(0x04040400,0x00040400), CONST64(0x04040401,0x00040400), CONST64(0x04040400,0x04040400), CONST64(0x04040401,0x04040400), + CONST64(0x04040400,0x00000004), CONST64(0x04040401,0x00000004), CONST64(0x04040400,0x04000004), CONST64(0x04040401,0x04000004), + CONST64(0x04040400,0x00040004), CONST64(0x04040401,0x00040004), CONST64(0x04040400,0x04040004), CONST64(0x04040401,0x04040004), + CONST64(0x04040400,0x00000404), CONST64(0x04040401,0x00000404), CONST64(0x04040400,0x04000404), CONST64(0x04040401,0x04000404), + CONST64(0x04040400,0x00040404), CONST64(0x04040401,0x00040404), CONST64(0x04040400,0x04040404), CONST64(0x04040401,0x04040404) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000004,0x00000000), CONST64(0x00000000,0x10000000), CONST64(0x00000004,0x10000000), + CONST64(0x00000000,0x00100000), CONST64(0x00000004,0x00100000), CONST64(0x00000000,0x10100000), CONST64(0x00000004,0x10100000), + CONST64(0x00000000,0x00001000), CONST64(0x00000004,0x00001000), CONST64(0x00000000,0x10001000), CONST64(0x00000004,0x10001000), + CONST64(0x00000000,0x00101000), CONST64(0x00000004,0x00101000), CONST64(0x00000000,0x10101000), CONST64(0x00000004,0x10101000), + CONST64(0x00000000,0x00000010), CONST64(0x00000004,0x00000010), CONST64(0x00000000,0x10000010), CONST64(0x00000004,0x10000010), + CONST64(0x00000000,0x00100010), CONST64(0x00000004,0x00100010), CONST64(0x00000000,0x10100010), CONST64(0x00000004,0x10100010), + CONST64(0x00000000,0x00001010), CONST64(0x00000004,0x00001010), CONST64(0x00000000,0x10001010), CONST64(0x00000004,0x10001010), + CONST64(0x00000000,0x00101010), CONST64(0x00000004,0x00101010), CONST64(0x00000000,0x10101010), CONST64(0x00000004,0x10101010), + CONST64(0x10000000,0x00000000), CONST64(0x10000004,0x00000000), CONST64(0x10000000,0x10000000), CONST64(0x10000004,0x10000000), + CONST64(0x10000000,0x00100000), CONST64(0x10000004,0x00100000), CONST64(0x10000000,0x10100000), CONST64(0x10000004,0x10100000), + CONST64(0x10000000,0x00001000), CONST64(0x10000004,0x00001000), CONST64(0x10000000,0x10001000), CONST64(0x10000004,0x10001000), + CONST64(0x10000000,0x00101000), CONST64(0x10000004,0x00101000), CONST64(0x10000000,0x10101000), CONST64(0x10000004,0x10101000), + CONST64(0x10000000,0x00000010), CONST64(0x10000004,0x00000010), CONST64(0x10000000,0x10000010), CONST64(0x10000004,0x10000010), + CONST64(0x10000000,0x00100010), CONST64(0x10000004,0x00100010), CONST64(0x10000000,0x10100010), CONST64(0x10000004,0x10100010), + CONST64(0x10000000,0x00001010), CONST64(0x10000004,0x00001010), CONST64(0x10000000,0x10001010), CONST64(0x10000004,0x10001010), + CONST64(0x10000000,0x00101010), CONST64(0x10000004,0x00101010), CONST64(0x10000000,0x10101010), CONST64(0x10000004,0x10101010), + CONST64(0x00100000,0x00000000), CONST64(0x00100004,0x00000000), CONST64(0x00100000,0x10000000), CONST64(0x00100004,0x10000000), + CONST64(0x00100000,0x00100000), CONST64(0x00100004,0x00100000), CONST64(0x00100000,0x10100000), CONST64(0x00100004,0x10100000), + CONST64(0x00100000,0x00001000), CONST64(0x00100004,0x00001000), CONST64(0x00100000,0x10001000), CONST64(0x00100004,0x10001000), + CONST64(0x00100000,0x00101000), CONST64(0x00100004,0x00101000), CONST64(0x00100000,0x10101000), CONST64(0x00100004,0x10101000), + CONST64(0x00100000,0x00000010), CONST64(0x00100004,0x00000010), CONST64(0x00100000,0x10000010), CONST64(0x00100004,0x10000010), + CONST64(0x00100000,0x00100010), CONST64(0x00100004,0x00100010), CONST64(0x00100000,0x10100010), CONST64(0x00100004,0x10100010), + CONST64(0x00100000,0x00001010), CONST64(0x00100004,0x00001010), CONST64(0x00100000,0x10001010), CONST64(0x00100004,0x10001010), + CONST64(0x00100000,0x00101010), CONST64(0x00100004,0x00101010), CONST64(0x00100000,0x10101010), CONST64(0x00100004,0x10101010), + CONST64(0x10100000,0x00000000), CONST64(0x10100004,0x00000000), CONST64(0x10100000,0x10000000), CONST64(0x10100004,0x10000000), + CONST64(0x10100000,0x00100000), CONST64(0x10100004,0x00100000), CONST64(0x10100000,0x10100000), CONST64(0x10100004,0x10100000), + CONST64(0x10100000,0x00001000), CONST64(0x10100004,0x00001000), CONST64(0x10100000,0x10001000), CONST64(0x10100004,0x10001000), + CONST64(0x10100000,0x00101000), CONST64(0x10100004,0x00101000), CONST64(0x10100000,0x10101000), CONST64(0x10100004,0x10101000), + CONST64(0x10100000,0x00000010), CONST64(0x10100004,0x00000010), CONST64(0x10100000,0x10000010), CONST64(0x10100004,0x10000010), + CONST64(0x10100000,0x00100010), CONST64(0x10100004,0x00100010), CONST64(0x10100000,0x10100010), CONST64(0x10100004,0x10100010), + CONST64(0x10100000,0x00001010), CONST64(0x10100004,0x00001010), CONST64(0x10100000,0x10001010), CONST64(0x10100004,0x10001010), + CONST64(0x10100000,0x00101010), CONST64(0x10100004,0x00101010), CONST64(0x10100000,0x10101010), CONST64(0x10100004,0x10101010), + CONST64(0x00001000,0x00000000), CONST64(0x00001004,0x00000000), CONST64(0x00001000,0x10000000), CONST64(0x00001004,0x10000000), + CONST64(0x00001000,0x00100000), CONST64(0x00001004,0x00100000), CONST64(0x00001000,0x10100000), CONST64(0x00001004,0x10100000), + CONST64(0x00001000,0x00001000), CONST64(0x00001004,0x00001000), CONST64(0x00001000,0x10001000), CONST64(0x00001004,0x10001000), + CONST64(0x00001000,0x00101000), CONST64(0x00001004,0x00101000), CONST64(0x00001000,0x10101000), CONST64(0x00001004,0x10101000), + CONST64(0x00001000,0x00000010), CONST64(0x00001004,0x00000010), CONST64(0x00001000,0x10000010), CONST64(0x00001004,0x10000010), + CONST64(0x00001000,0x00100010), CONST64(0x00001004,0x00100010), CONST64(0x00001000,0x10100010), CONST64(0x00001004,0x10100010), + CONST64(0x00001000,0x00001010), CONST64(0x00001004,0x00001010), CONST64(0x00001000,0x10001010), CONST64(0x00001004,0x10001010), + CONST64(0x00001000,0x00101010), CONST64(0x00001004,0x00101010), CONST64(0x00001000,0x10101010), CONST64(0x00001004,0x10101010), + CONST64(0x10001000,0x00000000), CONST64(0x10001004,0x00000000), CONST64(0x10001000,0x10000000), CONST64(0x10001004,0x10000000), + CONST64(0x10001000,0x00100000), CONST64(0x10001004,0x00100000), CONST64(0x10001000,0x10100000), CONST64(0x10001004,0x10100000), + CONST64(0x10001000,0x00001000), CONST64(0x10001004,0x00001000), CONST64(0x10001000,0x10001000), CONST64(0x10001004,0x10001000), + CONST64(0x10001000,0x00101000), CONST64(0x10001004,0x00101000), CONST64(0x10001000,0x10101000), CONST64(0x10001004,0x10101000), + CONST64(0x10001000,0x00000010), CONST64(0x10001004,0x00000010), CONST64(0x10001000,0x10000010), CONST64(0x10001004,0x10000010), + CONST64(0x10001000,0x00100010), CONST64(0x10001004,0x00100010), CONST64(0x10001000,0x10100010), CONST64(0x10001004,0x10100010), + CONST64(0x10001000,0x00001010), CONST64(0x10001004,0x00001010), CONST64(0x10001000,0x10001010), CONST64(0x10001004,0x10001010), + CONST64(0x10001000,0x00101010), CONST64(0x10001004,0x00101010), CONST64(0x10001000,0x10101010), CONST64(0x10001004,0x10101010), + CONST64(0x00101000,0x00000000), CONST64(0x00101004,0x00000000), CONST64(0x00101000,0x10000000), CONST64(0x00101004,0x10000000), + CONST64(0x00101000,0x00100000), CONST64(0x00101004,0x00100000), CONST64(0x00101000,0x10100000), CONST64(0x00101004,0x10100000), + CONST64(0x00101000,0x00001000), CONST64(0x00101004,0x00001000), CONST64(0x00101000,0x10001000), CONST64(0x00101004,0x10001000), + CONST64(0x00101000,0x00101000), CONST64(0x00101004,0x00101000), CONST64(0x00101000,0x10101000), CONST64(0x00101004,0x10101000), + CONST64(0x00101000,0x00000010), CONST64(0x00101004,0x00000010), CONST64(0x00101000,0x10000010), CONST64(0x00101004,0x10000010), + CONST64(0x00101000,0x00100010), CONST64(0x00101004,0x00100010), CONST64(0x00101000,0x10100010), CONST64(0x00101004,0x10100010), + CONST64(0x00101000,0x00001010), CONST64(0x00101004,0x00001010), CONST64(0x00101000,0x10001010), CONST64(0x00101004,0x10001010), + CONST64(0x00101000,0x00101010), CONST64(0x00101004,0x00101010), CONST64(0x00101000,0x10101010), CONST64(0x00101004,0x10101010), + CONST64(0x10101000,0x00000000), CONST64(0x10101004,0x00000000), CONST64(0x10101000,0x10000000), CONST64(0x10101004,0x10000000), + CONST64(0x10101000,0x00100000), CONST64(0x10101004,0x00100000), CONST64(0x10101000,0x10100000), CONST64(0x10101004,0x10100000), + CONST64(0x10101000,0x00001000), CONST64(0x10101004,0x00001000), CONST64(0x10101000,0x10001000), CONST64(0x10101004,0x10001000), + CONST64(0x10101000,0x00101000), CONST64(0x10101004,0x00101000), CONST64(0x10101000,0x10101000), CONST64(0x10101004,0x10101000), + CONST64(0x10101000,0x00000010), CONST64(0x10101004,0x00000010), CONST64(0x10101000,0x10000010), CONST64(0x10101004,0x10000010), + CONST64(0x10101000,0x00100010), CONST64(0x10101004,0x00100010), CONST64(0x10101000,0x10100010), CONST64(0x10101004,0x10100010), + CONST64(0x10101000,0x00001010), CONST64(0x10101004,0x00001010), CONST64(0x10101000,0x10001010), CONST64(0x10101004,0x10001010), + CONST64(0x10101000,0x00101010), CONST64(0x10101004,0x00101010), CONST64(0x10101000,0x10101010), CONST64(0x10101004,0x10101010) + }, +{ CONST64(0x00000000,0x00000000), CONST64(0x00000010,0x00000000), CONST64(0x00000000,0x40000000), CONST64(0x00000010,0x40000000), + CONST64(0x00000000,0x00400000), CONST64(0x00000010,0x00400000), CONST64(0x00000000,0x40400000), CONST64(0x00000010,0x40400000), + CONST64(0x00000000,0x00004000), CONST64(0x00000010,0x00004000), CONST64(0x00000000,0x40004000), CONST64(0x00000010,0x40004000), + CONST64(0x00000000,0x00404000), CONST64(0x00000010,0x00404000), CONST64(0x00000000,0x40404000), CONST64(0x00000010,0x40404000), + CONST64(0x00000000,0x00000040), CONST64(0x00000010,0x00000040), CONST64(0x00000000,0x40000040), CONST64(0x00000010,0x40000040), + CONST64(0x00000000,0x00400040), CONST64(0x00000010,0x00400040), CONST64(0x00000000,0x40400040), CONST64(0x00000010,0x40400040), + CONST64(0x00000000,0x00004040), CONST64(0x00000010,0x00004040), CONST64(0x00000000,0x40004040), CONST64(0x00000010,0x40004040), + CONST64(0x00000000,0x00404040), CONST64(0x00000010,0x00404040), CONST64(0x00000000,0x40404040), CONST64(0x00000010,0x40404040), + CONST64(0x40000000,0x00000000), CONST64(0x40000010,0x00000000), CONST64(0x40000000,0x40000000), CONST64(0x40000010,0x40000000), + CONST64(0x40000000,0x00400000), CONST64(0x40000010,0x00400000), CONST64(0x40000000,0x40400000), CONST64(0x40000010,0x40400000), + CONST64(0x40000000,0x00004000), CONST64(0x40000010,0x00004000), CONST64(0x40000000,0x40004000), CONST64(0x40000010,0x40004000), + CONST64(0x40000000,0x00404000), CONST64(0x40000010,0x00404000), CONST64(0x40000000,0x40404000), CONST64(0x40000010,0x40404000), + CONST64(0x40000000,0x00000040), CONST64(0x40000010,0x00000040), CONST64(0x40000000,0x40000040), CONST64(0x40000010,0x40000040), + CONST64(0x40000000,0x00400040), CONST64(0x40000010,0x00400040), CONST64(0x40000000,0x40400040), CONST64(0x40000010,0x40400040), + CONST64(0x40000000,0x00004040), CONST64(0x40000010,0x00004040), CONST64(0x40000000,0x40004040), CONST64(0x40000010,0x40004040), + CONST64(0x40000000,0x00404040), CONST64(0x40000010,0x00404040), CONST64(0x40000000,0x40404040), CONST64(0x40000010,0x40404040), + CONST64(0x00400000,0x00000000), CONST64(0x00400010,0x00000000), CONST64(0x00400000,0x40000000), CONST64(0x00400010,0x40000000), + CONST64(0x00400000,0x00400000), CONST64(0x00400010,0x00400000), CONST64(0x00400000,0x40400000), CONST64(0x00400010,0x40400000), + CONST64(0x00400000,0x00004000), CONST64(0x00400010,0x00004000), CONST64(0x00400000,0x40004000), CONST64(0x00400010,0x40004000), + CONST64(0x00400000,0x00404000), CONST64(0x00400010,0x00404000), CONST64(0x00400000,0x40404000), CONST64(0x00400010,0x40404000), + CONST64(0x00400000,0x00000040), CONST64(0x00400010,0x00000040), CONST64(0x00400000,0x40000040), CONST64(0x00400010,0x40000040), + CONST64(0x00400000,0x00400040), CONST64(0x00400010,0x00400040), CONST64(0x00400000,0x40400040), CONST64(0x00400010,0x40400040), + CONST64(0x00400000,0x00004040), CONST64(0x00400010,0x00004040), CONST64(0x00400000,0x40004040), CONST64(0x00400010,0x40004040), + CONST64(0x00400000,0x00404040), CONST64(0x00400010,0x00404040), CONST64(0x00400000,0x40404040), CONST64(0x00400010,0x40404040), + CONST64(0x40400000,0x00000000), CONST64(0x40400010,0x00000000), CONST64(0x40400000,0x40000000), CONST64(0x40400010,0x40000000), + CONST64(0x40400000,0x00400000), CONST64(0x40400010,0x00400000), CONST64(0x40400000,0x40400000), CONST64(0x40400010,0x40400000), + CONST64(0x40400000,0x00004000), CONST64(0x40400010,0x00004000), CONST64(0x40400000,0x40004000), CONST64(0x40400010,0x40004000), + CONST64(0x40400000,0x00404000), CONST64(0x40400010,0x00404000), CONST64(0x40400000,0x40404000), CONST64(0x40400010,0x40404000), + CONST64(0x40400000,0x00000040), CONST64(0x40400010,0x00000040), CONST64(0x40400000,0x40000040), CONST64(0x40400010,0x40000040), + CONST64(0x40400000,0x00400040), CONST64(0x40400010,0x00400040), CONST64(0x40400000,0x40400040), CONST64(0x40400010,0x40400040), + CONST64(0x40400000,0x00004040), CONST64(0x40400010,0x00004040), CONST64(0x40400000,0x40004040), CONST64(0x40400010,0x40004040), + CONST64(0x40400000,0x00404040), CONST64(0x40400010,0x00404040), CONST64(0x40400000,0x40404040), CONST64(0x40400010,0x40404040), + CONST64(0x00004000,0x00000000), CONST64(0x00004010,0x00000000), CONST64(0x00004000,0x40000000), CONST64(0x00004010,0x40000000), + CONST64(0x00004000,0x00400000), CONST64(0x00004010,0x00400000), CONST64(0x00004000,0x40400000), CONST64(0x00004010,0x40400000), + CONST64(0x00004000,0x00004000), CONST64(0x00004010,0x00004000), CONST64(0x00004000,0x40004000), CONST64(0x00004010,0x40004000), + CONST64(0x00004000,0x00404000), CONST64(0x00004010,0x00404000), CONST64(0x00004000,0x40404000), CONST64(0x00004010,0x40404000), + CONST64(0x00004000,0x00000040), CONST64(0x00004010,0x00000040), CONST64(0x00004000,0x40000040), CONST64(0x00004010,0x40000040), + CONST64(0x00004000,0x00400040), CONST64(0x00004010,0x00400040), CONST64(0x00004000,0x40400040), CONST64(0x00004010,0x40400040), + CONST64(0x00004000,0x00004040), CONST64(0x00004010,0x00004040), CONST64(0x00004000,0x40004040), CONST64(0x00004010,0x40004040), + CONST64(0x00004000,0x00404040), CONST64(0x00004010,0x00404040), CONST64(0x00004000,0x40404040), CONST64(0x00004010,0x40404040), + CONST64(0x40004000,0x00000000), CONST64(0x40004010,0x00000000), CONST64(0x40004000,0x40000000), CONST64(0x40004010,0x40000000), + CONST64(0x40004000,0x00400000), CONST64(0x40004010,0x00400000), CONST64(0x40004000,0x40400000), CONST64(0x40004010,0x40400000), + CONST64(0x40004000,0x00004000), CONST64(0x40004010,0x00004000), CONST64(0x40004000,0x40004000), CONST64(0x40004010,0x40004000), + CONST64(0x40004000,0x00404000), CONST64(0x40004010,0x00404000), CONST64(0x40004000,0x40404000), CONST64(0x40004010,0x40404000), + CONST64(0x40004000,0x00000040), CONST64(0x40004010,0x00000040), CONST64(0x40004000,0x40000040), CONST64(0x40004010,0x40000040), + CONST64(0x40004000,0x00400040), CONST64(0x40004010,0x00400040), CONST64(0x40004000,0x40400040), CONST64(0x40004010,0x40400040), + CONST64(0x40004000,0x00004040), CONST64(0x40004010,0x00004040), CONST64(0x40004000,0x40004040), CONST64(0x40004010,0x40004040), + CONST64(0x40004000,0x00404040), CONST64(0x40004010,0x00404040), CONST64(0x40004000,0x40404040), CONST64(0x40004010,0x40404040), + CONST64(0x00404000,0x00000000), CONST64(0x00404010,0x00000000), CONST64(0x00404000,0x40000000), CONST64(0x00404010,0x40000000), + CONST64(0x00404000,0x00400000), CONST64(0x00404010,0x00400000), CONST64(0x00404000,0x40400000), CONST64(0x00404010,0x40400000), + CONST64(0x00404000,0x00004000), CONST64(0x00404010,0x00004000), CONST64(0x00404000,0x40004000), CONST64(0x00404010,0x40004000), + CONST64(0x00404000,0x00404000), CONST64(0x00404010,0x00404000), CONST64(0x00404000,0x40404000), CONST64(0x00404010,0x40404000), + CONST64(0x00404000,0x00000040), CONST64(0x00404010,0x00000040), CONST64(0x00404000,0x40000040), CONST64(0x00404010,0x40000040), + CONST64(0x00404000,0x00400040), CONST64(0x00404010,0x00400040), CONST64(0x00404000,0x40400040), CONST64(0x00404010,0x40400040), + CONST64(0x00404000,0x00004040), CONST64(0x00404010,0x00004040), CONST64(0x00404000,0x40004040), CONST64(0x00404010,0x40004040), + CONST64(0x00404000,0x00404040), CONST64(0x00404010,0x00404040), CONST64(0x00404000,0x40404040), CONST64(0x00404010,0x40404040), + CONST64(0x40404000,0x00000000), CONST64(0x40404010,0x00000000), CONST64(0x40404000,0x40000000), CONST64(0x40404010,0x40000000), + CONST64(0x40404000,0x00400000), CONST64(0x40404010,0x00400000), CONST64(0x40404000,0x40400000), CONST64(0x40404010,0x40400000), + CONST64(0x40404000,0x00004000), CONST64(0x40404010,0x00004000), CONST64(0x40404000,0x40004000), CONST64(0x40404010,0x40004000), + CONST64(0x40404000,0x00404000), CONST64(0x40404010,0x00404000), CONST64(0x40404000,0x40404000), CONST64(0x40404010,0x40404000), + CONST64(0x40404000,0x00000040), CONST64(0x40404010,0x00000040), CONST64(0x40404000,0x40000040), CONST64(0x40404010,0x40000040), + CONST64(0x40404000,0x00400040), CONST64(0x40404010,0x00400040), CONST64(0x40404000,0x40400040), CONST64(0x40404010,0x40400040), + CONST64(0x40404000,0x00004040), CONST64(0x40404010,0x00004040), CONST64(0x40404000,0x40004040), CONST64(0x40404010,0x40004040), + CONST64(0x40404000,0x00404040), CONST64(0x40404010,0x00404040), CONST64(0x40404000,0x40404040), CONST64(0x40404010,0x40404040) + }}; + + +static void cookey(const ulong32 *raw1, ulong32 *keyout); + +void deskey(const unsigned char *key, short edf, ulong32 *keyout) +{ + ulong32 i, j, l, m, n, kn[32]; + unsigned char pc1m[56], pcr[56]; + + for (j=0; j < 56; j++) { + l = (ulong32)pc1[j]; + m = l & 7; + pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); + } + + for (i=0; i < 16; i++) { + if (edf == DE1) { + m = (15 - i) << 1; + } else { + m = i << 1; + } + n = m + 1; + kn[m] = kn[n] = 0L; + for (j=0; j < 28; j++) { + l = j + (ulong32)totrot[i]; + if (l < 28) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (/*j = 28*/; j < 56; j++) { + l = j + (ulong32)totrot[i]; + if (l < 56) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (j=0; j < 24; j++) { + if ((int)pcr[(int)pc2[j]] != 0) { + kn[m] |= bigbyte[j]; + } + if ((int)pcr[(int)pc2[j+24]] != 0) { + kn[n] |= bigbyte[j]; + } + } + } + + cookey(kn, keyout); +} + +static void cookey(const ulong32 *raw1, ulong32 *keyout) +{ + ulong32 *cook; + const ulong32 *raw0; + ulong32 dough[32]; + int i; + + cook = dough; + for(i=0; i < 16; i++, raw1++) + { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + + memcpy(keyout, dough, sizeof dough); +} + +static void desfunc(ulong32 *block, const ulong32 *keys) +{ + ulong64 tmp; + ulong32 work, right, leftt; + int cur_round; + + leftt = block[0]; + right = block[1]; + + tmp = des_ip[0][byte(leftt, 0)] ^ + des_ip[1][byte(leftt, 1)] ^ + des_ip[2][byte(leftt, 2)] ^ + des_ip[3][byte(leftt, 3)] ^ + des_ip[4][byte(right, 0)] ^ + des_ip[5][byte(right, 1)] ^ + des_ip[6][byte(right, 2)] ^ + des_ip[7][byte(right, 3)]; + leftt = (ulong32)(tmp >> 32); + right = (ulong32)(tmp & 0xFFFFFFFFUL); + + for (cur_round = 0; cur_round < 8; cur_round++) { + work = ROR(right, 4) ^ *keys++; + leftt ^= SP7[work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + leftt ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + + work = ROR(leftt, 4) ^ *keys++; + right ^= SP7[ work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + right ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + } + + tmp = des_fp[0][byte(leftt, 0)] ^ + des_fp[1][byte(leftt, 1)] ^ + des_fp[2][byte(leftt, 2)] ^ + des_fp[3][byte(leftt, 3)] ^ + des_fp[4][byte(right, 0)] ^ + des_fp[5][byte(right, 1)] ^ + des_fp[6][byte(right, 2)] ^ + des_fp[7][byte(right, 3)]; + leftt = (ulong32)(tmp >> 32); + right = (ulong32)(tmp & 0xFFFFFFFFUL); + + block[0] = right; + block[1] = leftt; +} + +int des_setup(const unsigned char *key, int keylen, int num_rounds, des_key *des) +{ + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, des->ek); + deskey(key, DE1, des->dk); + + return CRYPT_OK; +} + +int des3_setup(const unsigned char *key, int keylen, int num_rounds, des3_key *des3) +{ + if(num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 24) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, des3->ek[0]); + deskey(key+8, DE1, des3->ek[1]); + deskey(key+16, EN0, des3->ek[2]); + + deskey(key, DE1, des3->dk[2]); + deskey(key+8, EN0, des3->dk[1]); + deskey(key+16, DE1, des3->dk[0]); + + return CRYPT_OK; +} + +void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, des_key *des) +{ + ulong32 work[2]; + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, des->ek); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); +} + +void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, des_key *des) +{ + ulong32 work[2]; + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, des->dk); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); +} + +void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, des3_key *des3) +{ + ulong32 work[2]; + + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, des3->ek[0]); + desfunc(work, des3->ek[1]); + desfunc(work, des3->ek[2]); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); +} + +void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, des3_key *des3) +{ + ulong32 work[2]; + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, des3->dk[0]); + desfunc(work, des3->dk[1]); + desfunc(work, des3->dk[2]); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); +} diff --git a/dlls/rsaenh/implglue.c b/dlls/rsaenh/implglue.c new file mode 100644 index 00000000000..75c39c92c0a --- /dev/null +++ b/dlls/rsaenh/implglue.c @@ -0,0 +1,442 @@ +/* + * dlls/rsaenh/implglue.c + * Glueing the RSAENH specific code to the crypto library + * + * Copyright (c) 2004 Michael Jung + * + * based on code by Mike McCormack and David Hammerton + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "config.h" + +#include "wine/port.h" +#include "wine/library.h" +#include "wine/debug.h" + +#include "windef.h" +#include "wincrypt.h" + +#include "implglue.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +/* Function prototypes copied from dlls/advapi32/crypt_md4.c */ +VOID WINAPI MD4Init( MD4_CTX *ctx ); +VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len ); +VOID WINAPI MD4Final( MD4_CTX *ctx ); +/* Function prototypes copied from dlls/advapi32/crypt_md5.c */ +VOID WINAPI MD5Init( MD5_CTX *ctx ); +VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len ); +VOID WINAPI MD5Final( MD5_CTX *ctx ); +/* Function prototypes copied from dlls/advapi32/crypt_sha.c */ +VOID WINAPI A_SHAInit(PSHA_CTX Context); +VOID WINAPI A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize); +VOID WINAPI A_SHAFinal(PSHA_CTX Context, PULONG Result); + +BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext) +{ + switch (aiAlgid) + { + case CALG_MD2: + md2_init(&pHashContext->md2); + break; + + case CALG_MD4: + MD4Init(&pHashContext->md4); + break; + + case CALG_MD5: + MD5Init(&pHashContext->md5); + break; + + case CALG_SHA: + A_SHAInit(&pHashContext->sha); + break; + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pbData, + DWORD dwDataLen) +{ + switch (aiAlgid) + { + case CALG_MD2: + md2_process(&pHashContext->md2, pbData, dwDataLen); + break; + + case CALG_MD4: + MD4Update(&pHashContext->md4, pbData, dwDataLen); + break; + + case CALG_MD5: + MD5Update(&pHashContext->md5, pbData, dwDataLen); + break; + + case CALG_SHA: + A_SHAUpdate(&pHashContext->sha, (PCHAR)pbData, dwDataLen); + break; + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHashValue) +{ + switch (aiAlgid) + { + case CALG_MD2: + md2_done(&pHashContext->md2, pbHashValue); + break; + + case CALG_MD4: + MD4Final(&pHashContext->md4); + memcpy(pbHashValue, pHashContext->md4.digest, 16); + break; + + case CALG_MD5: + MD5Final(&pHashContext->md5); + memcpy(pbHashValue, pHashContext->md5.digest, 16); + break; + + case CALG_SHA: + A_SHAFinal(&pHashContext->sha, (PULONG)pbHashValue); + break; + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +BOOL duplicate_hash_impl(ALG_ID aiAlgid, CONST HASH_CONTEXT *pSrcHashContext, + HASH_CONTEXT *pDestHashContext) +{ + memcpy(pDestHashContext, pSrcHashContext, sizeof(HASH_CONTEXT)); + + return TRUE; +} + +BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen) +{ + switch (aiAlgid) + { + case CALG_RSA_KEYX: + case CALG_RSA_SIGN: + if (rsa_make_key((int)dwKeyLen, 65537, &pKeyContext->rsa) == CRYPT_OK) { + return TRUE; + } else { + printf("Error generating rsakey of len %ld!\n", dwKeyLen); + return FALSE; + } + } + + return TRUE; +} + +BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext) +{ + switch (aiAlgid) + { + case CALG_RSA_KEYX: + case CALG_RSA_SIGN: + rsa_free(&pKeyContext->rsa); + } + + return TRUE; +} + +BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen, + BYTE *abKeyValue) +{ + switch (aiAlgid) + { + case CALG_RC4: + rc4_start(&pKeyContext->rc4); + rc4_add_entropy(abKeyValue, dwKeyLen + dwSaltLen, &pKeyContext->rc4); + rc4_ready(&pKeyContext->rc4); + break; + + case CALG_RC2: + rc2_setup(abKeyValue, dwKeyLen + dwSaltLen, dwKeyLen << 3, 0, &pKeyContext->rc2); + break; + + case CALG_3DES: + des3_setup(abKeyValue, 24, 0, &pKeyContext->des3); + break; + + case CALG_3DES_112: + memcpy(abKeyValue+16, abKeyValue, 8); + des3_setup(abKeyValue, 24, 0, &pKeyContext->des3); + break; + + case CALG_DES: + des_setup(abKeyValue, 8, 0, &pKeyContext->des); + break; + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +BOOL duplicate_key_impl(ALG_ID aiAlgid, CONST KEY_CONTEXT *pSrcKeyContext, + KEY_CONTEXT *pDestKeyContext) +{ + switch (aiAlgid) + { + case CALG_RC4: + case CALG_RC2: + case CALG_3DES: + case CALG_3DES_112: + case CALG_DES: + memcpy(pDestKeyContext, pSrcKeyContext, sizeof(KEY_CONTEXT)); + break; + case CALG_RSA_KEYX: + case CALG_RSA_SIGN: + pDestKeyContext->rsa.type = pSrcKeyContext->rsa.type; + mp_init_copy(&pDestKeyContext->rsa.e, &pSrcKeyContext->rsa.e); + mp_init_copy(&pDestKeyContext->rsa.d, &pSrcKeyContext->rsa.d); + mp_init_copy(&pDestKeyContext->rsa.N, &pSrcKeyContext->rsa.N); + mp_init_copy(&pDestKeyContext->rsa.p, &pSrcKeyContext->rsa.p); + mp_init_copy(&pDestKeyContext->rsa.q, &pSrcKeyContext->rsa.q); + mp_init_copy(&pDestKeyContext->rsa.qP, &pSrcKeyContext->rsa.qP); + mp_init_copy(&pDestKeyContext->rsa.dP, &pSrcKeyContext->rsa.dP); + mp_init_copy(&pDestKeyContext->rsa.dQ, &pSrcKeyContext->rsa.dQ); + break; + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +static inline void reverse_bytes(BYTE *pbData, DWORD dwLen) { + BYTE swap; + DWORD i; + + for (i=0; irc2); + } else { + rc2_ecb_decrypt(in, out, &pKeyContext->rc2); + } + break; + + case CALG_3DES: + case CALG_3DES_112: + if (enc) { + des3_ecb_encrypt(in, out, &pKeyContext->des3); + } else { + des3_ecb_decrypt(in, out, &pKeyContext->des3); + } + break; + + case CALG_DES: + if (enc) { + des_ecb_encrypt(in, out, &pKeyContext->des); + } else { + des_ecb_decrypt(in, out, &pKeyContext->des); + } + break; + + case CALG_RSA_KEYX: + outlen = inlen = (mp_count_bits(&pKeyContext->rsa.N)+7)/8; + if (enc) { + rsa_exptmod(in, inlen, out, &outlen, PK_PUBLIC, &pKeyContext->rsa); + reverse_bytes((BYTE*)in, inlen); + } else { + reverse_bytes((BYTE*)in, inlen); + rsa_exptmod(in, inlen, out, &outlen, PK_PRIVATE, &pKeyContext->rsa); + } + break; + + case CALG_RSA_SIGN: + outlen = inlen = (mp_count_bits(&pKeyContext->rsa.N)+7)/8; + if (enc) { + rsa_exptmod(in, inlen, out, &outlen, PK_PRIVATE, &pKeyContext->rsa); + reverse_bytes((BYTE*)in, inlen); + } else { + reverse_bytes((BYTE*)in, inlen); + rsa_exptmod(in, inlen, out, &outlen, PK_PUBLIC, &pKeyContext->rsa); + } + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +BOOL encrypt_stream_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, BYTE *stream, DWORD dwLen) +{ + switch (aiAlgid) { + case CALG_RC4: + rc4_read(stream, dwLen, &pKeyContext->rc4); + break; + + default: + SetLastError(NTE_BAD_ALGID); + return FALSE; + } + + return TRUE; +} + +BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen) +{ + int dev_random; + + /* FIXME: /dev/urandom does not provide random numbers of a sufficient + * quality for cryptographic applications. /dev/random is much better, + * but it blocks if the kernel has not yet collected enough entropy for + * the request, which will suspend the calling thread for an indefinite + * amount of time. */ + dev_random = open("/dev/urandom", O_RDONLY); + if (dev_random != -1) + { + if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen) + { + close(dev_random); + return TRUE; + } + close(dev_random); + } + SetLastError(NTE_FAIL); + return FALSE; +} + +BOOL export_public_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,DWORD *pdwPubExp) +{ + mp_to_unsigned_bin(&pKeyContext->rsa.N, pbDest); + reverse_bytes(pbDest, dwKeyLen); + *pdwPubExp = (DWORD)mp_get_int(&pKeyContext->rsa.e); + return TRUE; +} + +BOOL import_public_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, + DWORD dwPubExp) +{ + BYTE *pbTemp; + + pbTemp = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwKeyLen); + if (!pbTemp) return FALSE; + memcpy(pbTemp, pbSrc, dwKeyLen); + + pKeyContext->rsa.type = PK_PUBLIC; + reverse_bytes(pbTemp, dwKeyLen); + mp_read_unsigned_bin(&pKeyContext->rsa.N, pbTemp, dwKeyLen); + HeapFree(GetProcessHeap(), 0, pbTemp); + mp_set_int(&pKeyContext->rsa.e, dwPubExp); + + return TRUE; +} + +BOOL export_private_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, + DWORD *pdwPubExp) +{ + mp_to_unsigned_bin(&pKeyContext->rsa.N, pbDest); + reverse_bytes(pbDest, dwKeyLen); + pbDest += dwKeyLen; + mp_to_unsigned_bin(&pKeyContext->rsa.p, pbDest); + reverse_bytes(pbDest, (dwKeyLen+1)>>1); + pbDest += (dwKeyLen+1)>>1; + mp_to_unsigned_bin(&pKeyContext->rsa.q, pbDest); + reverse_bytes(pbDest, (dwKeyLen+1)>>1); + pbDest += (dwKeyLen+1)>>1; + mp_to_unsigned_bin(&pKeyContext->rsa.dP, pbDest); + reverse_bytes(pbDest, (dwKeyLen+1)>>1); + pbDest += (dwKeyLen+1)>>1; + mp_to_unsigned_bin(&pKeyContext->rsa.dQ, pbDest); + reverse_bytes(pbDest, (dwKeyLen+1)>>1); + pbDest += (dwKeyLen+1)>>1; + mp_to_unsigned_bin(&pKeyContext->rsa.qP, pbDest); + reverse_bytes(pbDest, (dwKeyLen+1)>>1); + pbDest += (dwKeyLen+1)>>1; + mp_to_unsigned_bin(&pKeyContext->rsa.d, pbDest); + reverse_bytes(pbDest, dwKeyLen); + *pdwPubExp = (DWORD)mp_get_int(&pKeyContext->rsa.e); + + return TRUE; +} + +BOOL import_private_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, + DWORD dwPubExp) +{ + BYTE *pbTemp, *pbBigNum; + + pbTemp = HeapAlloc(GetProcessHeap(), 0, 2*dwKeyLen+5*((dwKeyLen+1)>>1)); + if (!pbTemp) return FALSE; + memcpy(pbTemp, pbSrc, 2*dwKeyLen+5*((dwKeyLen+1)>>1)); + pbBigNum = pbTemp; + + pKeyContext->rsa.type = PK_PRIVATE; + reverse_bytes(pbBigNum, dwKeyLen); + mp_read_unsigned_bin(&pKeyContext->rsa.N, pbBigNum, dwKeyLen); + pbBigNum += dwKeyLen; + reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); + mp_read_unsigned_bin(&pKeyContext->rsa.p, pbBigNum, (dwKeyLen+1)>>1); + pbBigNum += (dwKeyLen+1)>>1; + reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); + mp_read_unsigned_bin(&pKeyContext->rsa.q, pbBigNum, (dwKeyLen+1)>>1); + pbBigNum += (dwKeyLen+1)>>1; + reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); + mp_read_unsigned_bin(&pKeyContext->rsa.dP, pbBigNum, (dwKeyLen+1)>>1); + pbBigNum += (dwKeyLen+1)>>1; + reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); + mp_read_unsigned_bin(&pKeyContext->rsa.dQ, pbBigNum, (dwKeyLen+1)>>1); + pbBigNum += (dwKeyLen+1)>>1; + reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); + mp_read_unsigned_bin(&pKeyContext->rsa.qP, pbBigNum, (dwKeyLen+1)>>1); + pbBigNum += (dwKeyLen+1)>>1; + reverse_bytes(pbBigNum, dwKeyLen); + mp_read_unsigned_bin(&pKeyContext->rsa.d, pbBigNum, dwKeyLen); + mp_set_int(&pKeyContext->rsa.e, dwPubExp); + + HeapFree(GetProcessHeap(), 0, pbTemp); + return TRUE; +} diff --git a/dlls/rsaenh/implossl.h b/dlls/rsaenh/implglue.h similarity index 80% rename from dlls/rsaenh/implossl.h rename to dlls/rsaenh/implglue.h index 0f63b63ac7d..cc2e577180c 100644 --- a/dlls/rsaenh/implossl.h +++ b/dlls/rsaenh/implglue.h @@ -1,6 +1,6 @@ /* - * dlls/rsaenh/implossl.h - * Encapsulating the OpenSSL dependend parts of RSABASE + * dlls/rsaenh/implglue.h + * Glueing the RSAENH specific code to the crypto library * * Copyright (c) 2004 Michael Jung * @@ -21,28 +21,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef __WINE_IMPLOSSL_H -#define __WINE_IMPLOSSL_H +#ifndef __WINE_IMPLGLUE_H +#define __WINE_IMPLGLUE_H -#ifdef HAVE_OPENSSL_MD2_H -#include -#endif - -#ifdef HAVE_OPENSSL_RC2_H -#include -#endif - -#ifdef HAVE_OPENSSL_RC4_H -#include -#endif - -#ifdef HAVE_OPENSSL_DES_H -#include -#endif - -#ifdef HAVE_OPENSSL_RSA_H -#include -#endif +#include "tomcrypt.h" /* Next typedef copied from dlls/advapi32/crypt_md4.c */ typedef struct tagMD4_CTX { @@ -71,32 +53,20 @@ typedef struct tagSHA_CTX } SHA_CTX, *PSHA_CTX; typedef union tagHASH_CONTEXT { -#ifdef HAVE_OPENSSL_MD2_H - MD2_CTX md2; -#endif + md2_state md2; MD4_CTX md4; MD5_CTX md5; SHA_CTX sha; } HASH_CONTEXT; typedef union tagKEY_CONTEXT { -#ifdef HAVE_OPENSSL_RC2_H - RC2_KEY rc2; -#endif -#ifdef HAVE_OPENSSL_RC4_H - RC4_KEY rc4; -#endif -#ifdef HAVE_OPENSSL_DES_H - DES_key_schedule des[3]; -#endif -#ifdef HAVE_OPENSSL_RSA_H - RSA *rsa; -#endif - DWORD dwDummy; + rc2_key rc2; + des_key des; + des3_key des3; + prng_state rc4; + rsa_key rsa; } KEY_CONTEXT; -BOOL load_lib(void); - BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext); BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pbData, DWORD dwDataLen); @@ -126,4 +96,4 @@ BOOL import_private_key_impl(CONST BYTE* pbSrc, KEY_CONTEXT *pKeyContext, DWORD BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen); -#endif /* __WINE_IMPLOSSL_H */ +#endif /* __WINE_IMPLGLUE_H */ diff --git a/dlls/rsaenh/implossl.c b/dlls/rsaenh/implossl.c deleted file mode 100644 index fc02bd109ff..00000000000 --- a/dlls/rsaenh/implossl.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * dlls/rsaenh/implossl.c - * Encapsulating the OpenSSL dependend parts of RSAENH - * - * Copyright (c) 2004 Michael Jung - * - * based on code by Mike McCormack and David Hammerton - * - * 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 library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "config.h" - -#include "wine/port.h" -#include "wine/library.h" -#include "wine/debug.h" - -#include "windef.h" -#include "wincrypt.h" - -#include "implossl.h" - -#include - -WINE_DEFAULT_DEBUG_CHANNEL(crypt); - -#ifndef SONAME_LIBCRYPTO -#define SONAME_LIBCRYPTO "libcrypto.so" -#endif - -static void *libcrypto; - -#define MAKE_FUNCPTR(f) static typeof(f) * p##f - -/* OpenSSL funtions that we use */ -#ifdef HAVE_OPENSSL_MD2_H -MAKE_FUNCPTR(MD2_Init); -MAKE_FUNCPTR(MD2_Update); -MAKE_FUNCPTR(MD2_Final); -#endif -#ifdef HAVE_OPENSSL_RC2_H -MAKE_FUNCPTR(RC2_set_key); -MAKE_FUNCPTR(RC2_ecb_encrypt); -#endif -#ifdef HAVE_OPENSSL_RC4_H -MAKE_FUNCPTR(RC4_set_key); -MAKE_FUNCPTR(RC4); -#endif -#ifdef HAVE_OPENSSL_DES_H -MAKE_FUNCPTR(DES_set_odd_parity); -MAKE_FUNCPTR(DES_set_key_unchecked); -MAKE_FUNCPTR(DES_ecb_encrypt); -MAKE_FUNCPTR(DES_ecb3_encrypt); -#endif -#ifdef HAVE_OPENSSL_RSA_H -MAKE_FUNCPTR(RSA_generate_key); -MAKE_FUNCPTR(RSA_free); -MAKE_FUNCPTR(RSA_size); -MAKE_FUNCPTR(RSA_check_key); -MAKE_FUNCPTR(RSA_public_encrypt); -MAKE_FUNCPTR(RSA_private_encrypt); -MAKE_FUNCPTR(RSAPrivateKey_dup); -MAKE_FUNCPTR(BN_bn2bin); -MAKE_FUNCPTR(BN_bin2bn); -MAKE_FUNCPTR(BN_get_word); -MAKE_FUNCPTR(BN_set_word); -MAKE_FUNCPTR(BN_num_bits); -#endif - -/* Function prototypes copied from dlls/advapi32/crypt_md4.c */ -VOID WINAPI MD4Init( MD4_CTX *ctx ); -VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len ); -VOID WINAPI MD4Final( MD4_CTX *ctx ); -/* Function prototypes copied from dlls/advapi32/crypt_md5.c */ -VOID WINAPI MD5Init( MD5_CTX *ctx ); -VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len ); -VOID WINAPI MD5Final( MD5_CTX *ctx ); -/* Function prototypes copied from dlls/advapi32/crypt_sha.c */ -VOID WINAPI A_SHAInit(PSHA_CTX Context); -VOID WINAPI A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize); -VOID WINAPI A_SHAFinal(PSHA_CTX Context, PULONG Result); - - -BOOL load_lib( void ) -{ -/* FIXME: Is this portable? */ -#if defined HAVE_OPENSSL_MD2_H || defined HAVE_OPENSSL_RC2_H || defined HAVE_OPENSSL_RC4_H || \ - defined HAVE_OPENSSL_DES_H || defined HAVE_OPENSSL_RSA_H - libcrypto = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0); - if (!libcrypto) - { - MESSAGE("Couldn't load %s, RSA encryption not available.\n", SONAME_LIBCRYPTO); - MESSAGE("Install the openssl package if you're have problems.\n"); - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - -#define GETFUNC(x) p##x = wine_dlsym(libcrypto, #x, NULL, 0); - -#ifdef HAVE_OPENSSL_MD2_H - GETFUNC(MD2_Init); - GETFUNC(MD2_Update); - GETFUNC(MD2_Final); -#endif -#ifdef HAVE_OPENSSL_RC2_H - GETFUNC(RC2_set_key); - GETFUNC(RC2_ecb_encrypt); -#endif -#ifdef HAVE_OPENSSL_RC4_H - GETFUNC(RC4_set_key); - GETFUNC(RC4); -#endif -#ifdef HAVE_OPENSSL_DES_H - GETFUNC(DES_set_odd_parity); - GETFUNC(DES_set_key_unchecked); - GETFUNC(DES_ecb_encrypt); - GETFUNC(DES_ecb3_encrypt); -#endif -#ifdef HAVE_OPENSSL_RSA_H - GETFUNC(RSA_generate_key); - GETFUNC(RSA_free); - GETFUNC(RSA_size); - GETFUNC(RSA_check_key); - GETFUNC(RSA_public_encrypt); - GETFUNC(RSA_private_encrypt); - GETFUNC(RSAPrivateKey_dup); - GETFUNC(BN_bn2bin); - GETFUNC(BN_bin2bn); - GETFUNC(BN_get_word); - GETFUNC(BN_set_word); - GETFUNC(BN_num_bits); -#endif - -#endif /* ifdef have any openssl header */ - return TRUE; -} - -BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext) -{ - switch (aiAlgid) - { -#ifdef HAVE_OPENSSL_MD2_H - case CALG_MD2: - if (!pMD2_Init) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pMD2_Init(&pHashContext->md2); - break; -#endif - case CALG_MD4: - MD4Init(&pHashContext->md4); - break; - - case CALG_MD5: - MD5Init(&pHashContext->md5); - break; - - case CALG_SHA: - A_SHAInit(&pHashContext->sha); - break; - - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pbData, - DWORD dwDataLen) -{ - switch (aiAlgid) - { -#ifdef HAVE_OPENSSL_MD2_H - case CALG_MD2: - if (!pMD2_Update) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pMD2_Update(&pHashContext->md2, pbData, dwDataLen); - break; -#endif - case CALG_MD4: - MD4Update(&pHashContext->md4, pbData, dwDataLen); - break; - - case CALG_MD5: - MD5Update(&pHashContext->md5, pbData, dwDataLen); - break; - - case CALG_SHA: - A_SHAUpdate(&pHashContext->sha, (PCHAR)pbData, dwDataLen); - break; - - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHashValue) -{ - switch (aiAlgid) - { -#ifdef HAVE_OPENSSL_MD2_H - case CALG_MD2: - if (!pMD2_Final) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pMD2_Final(pbHashValue, &pHashContext->md2); - break; -#endif - case CALG_MD4: - MD4Final(&pHashContext->md4); - memcpy(pbHashValue, pHashContext->md4.digest, 16); - break; - - case CALG_MD5: - MD5Final(&pHashContext->md5); - memcpy(pbHashValue, pHashContext->md5.digest, 16); - break; - - case CALG_SHA: - A_SHAFinal(&pHashContext->sha, (PULONG)pbHashValue); - break; - - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL duplicate_hash_impl(ALG_ID aiAlgid, CONST HASH_CONTEXT *pSrcHashContext, - HASH_CONTEXT *pDestHashContext) -{ - memcpy(pDestHashContext, pSrcHashContext, sizeof(HASH_CONTEXT)); - - return TRUE; -} - -BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen) -{ - switch (aiAlgid) - { -#ifdef HAVE_OPENSSL_RSA_H - case CALG_RSA_KEYX: - case CALG_RSA_SIGN: - if (!pRSA_generate_key) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pKeyContext->rsa = pRSA_generate_key((int)dwKeyLen*8, 65537, NULL, NULL); - break; -#endif - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext) -{ - switch (aiAlgid) - { -#ifdef HAVE_OPENSSL_RSA_H - case CALG_RSA_KEYX: - case CALG_RSA_SIGN: - if (!pRSA_free) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - if (pKeyContext->rsa) pRSA_free(pKeyContext->rsa); - break; -#endif - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen, - BYTE *abKeyValue) -{ - switch (aiAlgid) - { -#ifdef HAVE_OPENSSL_RC4_H - case CALG_RC4: - if (!pRC4_set_key) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pRC4_set_key(&pKeyContext->rc4, dwKeyLen + dwSaltLen, abKeyValue); - break; -#endif -#ifdef HAVE_OPENSSL_RC2_H - case CALG_RC2: - if (!pRC2_set_key) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pRC2_set_key(&pKeyContext->rc2, dwKeyLen + dwSaltLen, abKeyValue, dwKeyLen * 8); - break; -#endif -#ifdef HAVE_OPENSSL_DES_H - case CALG_3DES: - if (!pDES_set_odd_parity || !pDES_set_key_unchecked) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDES_set_odd_parity(&((DES_cblock*)abKeyValue)[2]); - pDES_set_key_unchecked(&((DES_cblock*)abKeyValue)[2], &pKeyContext->des[2]); - - case CALG_3DES_112: - if (!pDES_set_odd_parity || !pDES_set_key_unchecked) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDES_set_odd_parity(&((DES_cblock*)abKeyValue)[1]); - pDES_set_key_unchecked(&((DES_cblock*)abKeyValue)[1], &pKeyContext->des[1]); - - case CALG_DES: - if (!pDES_set_odd_parity || !pDES_set_key_unchecked) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDES_set_odd_parity((DES_cblock*)abKeyValue); - pDES_set_key_unchecked((DES_cblock*)abKeyValue, &pKeyContext->des[0]); - break; -#endif - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL duplicate_key_impl(ALG_ID aiAlgid, CONST KEY_CONTEXT *pSrcKeyContext, - KEY_CONTEXT *pDestKeyContext) -{ - switch (aiAlgid) - { - case CALG_RC4: - case CALG_RC2: - case CALG_3DES: - case CALG_3DES_112: - case CALG_DES: - memcpy(pDestKeyContext, pSrcKeyContext, sizeof(KEY_CONTEXT)); - break; -#ifdef HAVE_OPENSSL_RSA_H - case CALG_RSA_KEYX: - case CALG_RSA_SIGN: - if (!pRSAPrivateKey_dup) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDestKeyContext->rsa = pRSAPrivateKey_dup(pSrcKeyContext->rsa); - break; -#endif - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -#ifdef HAVE_OPENSSL_RSA_H -static inline void reverse_bytes(BYTE *pbData, DWORD dwLen) { - BYTE swap; - DWORD i; - - for (i=0; irc2, enc ? RC2_ENCRYPT : RC2_DECRYPT); - break; -#endif -#ifdef HAVE_OPENSSL_DES_H - case CALG_DES: - if (!pDES_ecb_encrypt) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDES_ecb_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &pKeyContext->des[0], - enc ? DES_ENCRYPT : DES_DECRYPT); - break; - - case CALG_3DES_112: - if (!pDES_ecb3_encrypt) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, - &pKeyContext->des[0], &pKeyContext->des[1], &pKeyContext->des[0], - enc ? DES_ENCRYPT : DES_DECRYPT); - break; - - case CALG_3DES: - if (!pDES_ecb3_encrypt) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pDES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, - &pKeyContext->des[0], &pKeyContext->des[1], &pKeyContext->des[2], - enc ? DES_ENCRYPT : DES_DECRYPT); - break; -#endif -#ifdef HAVE_OPENSSL_RSA_H - case CALG_RSA_KEYX: - if (!pBN_num_bits || !pRSA_public_encrypt || !pRSA_private_encrypt) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - cLen = pBN_num_bits(pKeyContext->rsa->n)/8; - if (enc) { - pRSA_public_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING); - reverse_bytes((BYTE*)in, cLen); - } else { - reverse_bytes((BYTE*)in, cLen); - pRSA_private_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING); - } - break; - - case CALG_RSA_SIGN: - if (!pBN_num_bits || !pRSA_public_encrypt || !pRSA_private_encrypt) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - cLen = pBN_num_bits(pKeyContext->rsa->n)/8; - if (enc) { - pRSA_private_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING); - reverse_bytes((BYTE*)in, cLen); - } else { - reverse_bytes((BYTE*)in, cLen); - pRSA_public_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING); - } - break; -#endif - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL encrypt_stream_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, BYTE *stream, DWORD dwLen) -{ - switch (aiAlgid) { -#ifdef HAVE_OPENSSL_RC4_H - case CALG_RC4: - if (!pRC4) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - pRC4(&pKeyContext->rc4, (unsigned long)dwLen, stream, stream); - break; -#endif - default: - SetLastError(NTE_BAD_ALGID); - return FALSE; - } - - return TRUE; -} - -BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen) -{ - FILE *dev_random; - - /* FIXME: /dev/urandom does not provide random numbers of a sufficient - * quality for cryptographic applications. /dev/random is much better, - * but it blocks if the kernel has not yet collected enough entropy for - * the request, which will suspend the calling thread for an indefinite - * amount of time. */ - dev_random = fopen("/dev/urandom", "r"); - if (dev_random) - { - if (fread(pbBuffer, (size_t)dwLen, 1, dev_random) == 1) - { - fclose(dev_random); - return TRUE; - } - fclose(dev_random); - } - SetLastError(NTE_FAIL); - return FALSE; -} - -BOOL export_public_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,DWORD *pdwPubExp) -{ -#ifdef HAVE_OPENSSL_RSA_H - if (!pBN_bn2bin || !pBN_get_word) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - - pBN_bn2bin(pKeyContext->rsa->n, pbDest); - reverse_bytes(pbDest, dwKeyLen); - *pdwPubExp = (DWORD)pBN_get_word(pKeyContext->rsa->e); - - return TRUE; -#else - SetLastError(NTE_FAIL); - return FALSE; -#endif -} - -BOOL import_public_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, - DWORD dwPubExp) -{ -#ifdef HAVE_OPENSSL_RSA_H - BYTE *pbTemp; - - if (!pBN_bin2bn || !pBN_set_word) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - - pbTemp = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwKeyLen); - if (!pbTemp) return FALSE; - memcpy(pbTemp, pbSrc, dwKeyLen); - reverse_bytes(pbTemp, dwKeyLen); - pBN_bin2bn(pbTemp, dwKeyLen, pKeyContext->rsa->n); - HeapFree(GetProcessHeap(), 0, pbTemp); - - pBN_set_word(pKeyContext->rsa->e, (BN_ULONG)dwPubExp); - - return TRUE; -#else - SetLastError(NTE_FAIL); - return FALSE; -#endif -} - -BOOL export_private_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, - DWORD *pdwPubExp) -{ -#ifdef HAVE_OPENSSL_RSA_H - if (!pBN_bn2bin || !pBN_get_word) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - - pBN_bn2bin(pKeyContext->rsa->n, pbDest); - reverse_bytes(pbDest, dwKeyLen); - pbDest += dwKeyLen; - pBN_bn2bin(pKeyContext->rsa->p, pbDest); - reverse_bytes(pbDest, (dwKeyLen+1)>>1); - pbDest += (dwKeyLen+1)>>1; - pBN_bn2bin(pKeyContext->rsa->q, pbDest); - reverse_bytes(pbDest, (dwKeyLen+1)>>1); - pbDest += (dwKeyLen+1)>>1; - pBN_bn2bin(pKeyContext->rsa->dmp1, pbDest); - reverse_bytes(pbDest, (dwKeyLen+1)>>1); - pbDest += (dwKeyLen+1)>>1; - pBN_bn2bin(pKeyContext->rsa->dmq1, pbDest); - reverse_bytes(pbDest, (dwKeyLen+1)>>1); - pbDest += (dwKeyLen+1)>>1; - pBN_bn2bin(pKeyContext->rsa->iqmp, pbDest); - reverse_bytes(pbDest, (dwKeyLen+1)>>1); - pbDest += (dwKeyLen+1)>>1; - pBN_bn2bin(pKeyContext->rsa->d, pbDest); - reverse_bytes(pbDest, dwKeyLen); - *pdwPubExp = (DWORD)pBN_get_word(pKeyContext->rsa->e); - - return TRUE; -#else - SetLastError(NTE_FAIL); - return FALSE; -#endif -} - -BOOL import_private_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, - DWORD dwPubExp) -{ -#ifdef HAVE_OPENSSL_RSA_H - BYTE *pbTemp, *pbBigNum; - - if (!pBN_bin2bn || !pBN_set_word) - { - SetLastError(NTE_PROVIDER_DLL_FAIL); - return FALSE; - } - - pbTemp = HeapAlloc(GetProcessHeap(), 0, 2*dwKeyLen+5*((dwKeyLen+1)>>1)); - if (!pbTemp) return FALSE; - memcpy(pbTemp, pbSrc, 2*dwKeyLen+5*((dwKeyLen+1)>>1)); - pbBigNum = pbTemp; - - reverse_bytes(pbBigNum, dwKeyLen); - pBN_bin2bn(pbBigNum, dwKeyLen, pKeyContext->rsa->n); - pbBigNum += dwKeyLen; - reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); - pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->p); - pbBigNum += (dwKeyLen+1)>>1; - reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); - pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->q); - pbBigNum += (dwKeyLen+1)>>1; - reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); - pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->dmp1); - pbBigNum += (dwKeyLen+1)>>1; - reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); - pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->dmq1); - pbBigNum += (dwKeyLen+1)>>1; - reverse_bytes(pbBigNum, (dwKeyLen+1)>>1); - pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->iqmp); - pbBigNum += (dwKeyLen+1)>>1; - reverse_bytes(pbBigNum, dwKeyLen); - pBN_bin2bn(pbBigNum, dwKeyLen, pKeyContext->rsa->d); - pBN_set_word(pKeyContext->rsa->e, (BN_ULONG)dwPubExp); - - HeapFree(GetProcessHeap(), 0, pbTemp); - - return TRUE; -#else - SetLastError(NTE_FAIL); - return FALSE; -#endif -} diff --git a/dlls/rsaenh/md2.c b/dlls/rsaenh/md2.c new file mode 100644 index 00000000000..340edc1aa60 --- /dev/null +++ b/dlls/rsaenh/md2.c @@ -0,0 +1,151 @@ +/* + * dlls/rsaenh/md2.c + * MD2 (RFC 1319) hash function implementation by Tom St Denis + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#include "tomcrypt.h" + +static const unsigned char PI_SUBST[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 +}; + +/* adds 16 bytes to the checksum */ +static void md2_update_chksum(md2_state *md2) +{ + int j; + unsigned char L; + L = md2->chksum[15]; + for (j = 0; j < 16; j++) { + +/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say + otherwise. +*/ + L = (md2->chksum[j] ^= PI_SUBST[(int)(md2->buf[j] ^ L)] & 255); + } +} + +static void md2_compress(md2_state *md2) +{ + int j, k; + unsigned char t; + + /* copy block */ + for (j = 0; j < 16; j++) { + md2->X[16+j] = md2->buf[j]; + md2->X[32+j] = md2->X[j] ^ md2->X[16+j]; + } + + t = (unsigned char)0; + + /* do 18 rounds */ + for (j = 0; j < 18; j++) { + for (k = 0; k < 48; k++) { + t = (md2->X[k] ^= PI_SUBST[(int)(t & 255)]); + } + t = (t + (unsigned char)j) & 255; + } +} + +int md2_init(md2_state *md2) +{ + /* MD2 uses a zero'ed state... */ + memset(md2->X, 0, sizeof(md2->X)); + memset(md2->chksum, 0, sizeof(md2->chksum)); + memset(md2->buf, 0, sizeof(md2->buf)); + md2->curlen = 0; + return CRYPT_OK; +} + +int md2_process(md2_state *md2, const unsigned char *buf, unsigned long len) +{ + unsigned long n; + + if (md2->curlen > sizeof(md2->buf)) { + return CRYPT_INVALID_ARG; + } + while (len > 0) { + n = MIN(len, (16 - md2->curlen)); + memcpy(md2->buf + md2->curlen, buf, (size_t)n); + md2->curlen += n; + buf += n; + len -= n; + + /* is 16 bytes full? */ + if (md2->curlen == 16) { + md2_compress(md2); + md2_update_chksum(md2); + md2->curlen = 0; + } + } + return CRYPT_OK; +} + +int md2_done(md2_state * md2, unsigned char *hash) +{ + unsigned long i, k; + + if (md2->curlen >= sizeof(md2->buf)) { + return CRYPT_INVALID_ARG; + } + + /* pad the message */ + k = 16 - md2->curlen; + for (i = md2->curlen; i < 16; i++) { + md2->buf[i] = (unsigned char)k; + } + + /* hash and update */ + md2_compress(md2); + md2_update_chksum(md2); + + /* hash checksum */ + memcpy(md2->buf, md2->chksum, 16); + md2_compress(md2); + + /* output is lower 16 bytes of X */ + memcpy(hash, md2->X, 16); + + return CRYPT_OK; +} diff --git a/dlls/rsaenh/mpi.c b/dlls/rsaenh/mpi.c new file mode 100644 index 00000000000..f8bf02a0a8f --- /dev/null +++ b/dlls/rsaenh/mpi.c @@ -0,0 +1,4422 @@ +/* + * dlls/rsaenh/mpi.c + * Multi Precision Integer functions + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#include +#include "tomcrypt.h" + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on slow invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +int +fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, B, D; + int res, neg; + + /* 2. [modified] b must be odd */ + if (mp_iseven (b) == 1) { + return MP_VAL; + } + + /* init all our temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x == modulus, y == value to invert */ + if ((res = mp_copy (b, &x)) != MP_OKAY) { + goto __ERR; + } + + /* we need y = |a| */ + if ((res = mp_abs (a, &y)) != MP_OKAY) { + goto __ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto __ERR; + } + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto __ERR; + } + /* 4.2 if B is odd then */ + if (mp_isodd (&B) == 1) { + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto __ERR; + } + } + /* B = B/2 */ + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto __ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto __ERR; + } + /* 5.2 if D is odd then */ + if (mp_isodd (&D) == 1) { + /* D = (D-x)/2 */ + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto __ERR; + } + } + /* D = D/2 */ + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto __ERR; + } + } else { + /* v - v - u, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto __ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((res = mp_add (&D, b, &D)) != MP_OKAY) { + goto __ERR; + } + } + mp_exch (&D, c); + c->sign = neg; + res = MP_OKAY; + +__ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); + return res; +} + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +int +fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, olduse; + mp_word W[MP_WARRAY]; + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < n->used + 1) { + if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { + return res; + } + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + { + register mp_word *_W; + register mp_digit *tmpx; + + /* alias for the W[] array */ + _W = W; + + /* alias for the digits of x*/ + tmpx = x->dp; + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + *_W++ = *tmpx++; + } + + /* zero the high words of W[a->used..m->used*2] */ + for (; ix < n->used * 2 + 1; ix++) { + *_W++ = 0; + } + } + + /* now we proceed to zero successive digits + * from the least significant upwards + */ + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + register mp_digit mu; + mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offseting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + { + register int iy; + register mp_digit *tmpn; + register mp_word *_W; + + /* alias for the digits of the modulus */ + tmpn = n->dp; + + /* Alias for the columns set by an offset of ix */ + _W = W + ix; + + /* inner loop */ + for (iy = 0; iy < n->used; iy++) { + *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); + } + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + { + register mp_digit *tmpx; + register mp_word *_W, *_W1; + + /* nox fix rest of carries */ + + /* alias for current word */ + _W1 = W + ix; + + /* alias for next word, where the carry goes */ + _W = W + ++ix; + + for (; ix <= n->used * 2 + 1; ix++) { + *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + + /* alias for destination word */ + tmpx = x->dp; + + /* alias for shifted double precision result */ + _W = W + n->used; + + for (ix = 0; ix < n->used + 1; ix++) { + *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); + } + + /* zero oldused digits, if the input a was larger than + * m->used+1 we'll have to clear the digits + */ + for (; ix < olduse; ix++) { + *tmpx++ = 0; + } + } + + /* set the max used and clamp */ + x->used = n->used + 1; + mp_clamp (x); + + /* if A >= m then A = A - m */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + return MP_OKAY; +} + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +int +fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY]; + register mp_word _W; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((res = mp_grow (c, digs)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = MIN(digs, a->used + b->used); + + /* clear the carry */ + _W = 0; + for (ix = 0; ix <= pa; ix++) { + int tx, ty; + int iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterrate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; ++iz) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* store term */ + W[ix] = ((mp_digit)_W) & MP_MASK; + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = digs; + + { + register mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; ix < digs; ix++) { + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + return MP_OKAY; +} + +/* this is a modified version of fast_s_mul_digs that only produces + * output digits *above* digs. See the comments for fast_s_mul_digs + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +int +fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + pa = a->used + b->used; + if (c->alloc < pa) { + if ((res = mp_grow (c, pa)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = a->used + b->used; + _W = 0; + for (ix = digs; ix <= pa; ix++) { + int tx, ty, iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterrate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* store term */ + W[ix] = ((mp_digit)_W) & MP_MASK; + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + register mp_digit *tmpc; + + tmpc = c->dp + digs; + for (ix = digs; ix <= pa; ix++) { + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + return MP_OKAY; +} + +/* fast squaring + * + * This is the comba method where the columns of the product + * are computed first then the carries are computed. This + * has the effect of making a very simple inner loop that + * is executed the most + * + * W2 represents the outer products and W the inner. + * + * A further optimizations is made because the inner + * products are of the form "A * B * 2". The *2 part does + * not need to be computed until the end which is good + * because 64-bit shifts are slow! + * + * Based on Algorithm 14.16 on pp.597 of HAC. + * + */ +/* the jist of squaring... + +you do like mult except the offset of the tmpx [one that starts closer to zero] +can't equal the offset of tmpy. So basically you set up iy like before then you min it with +(ty-tx) so that it never happens. You double all those you add in the inner loop + +After that loop you do the squares and add them in. + +Remove W2 and don't memset W + +*/ + +int fast_s_mp_sqr (mp_int * a, mp_int * b) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY], *tmpx; + mp_word W1; + + /* grow the destination as required */ + pa = a->used + a->used; + if (b->alloc < pa) { + if ((res = mp_grow (b, pa)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + W1 = 0; + for (ix = 0; ix <= pa; ix++) { + int tx, ty, iy; + mp_word _W; + mp_digit *tmpy; + + /* clear counter */ + _W = 0; + + /* get offsets into the two bignums */ + ty = MIN(a->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = a->dp + ty; + + /* this is the number of times the loop will iterrate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach at a rate of 2x + * and we have to round because odd cases need to be executed + */ + iy = MIN(iy, (ty-tx+1)>>1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* double the inner product and add carry */ + _W = _W + _W + W1; + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); + } + + /* store it */ + W[ix] = _W; + + /* make next carry */ + W1 = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = b->used; + b->used = a->used+a->used; + + { + mp_digit *tmpb; + tmpb = b->dp; + for (ix = 0; ix < pa; ix++) { + *tmpb++ = W[ix] & MP_MASK; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpb++ = 0; + } + } + mp_clamp (b); + return MP_OKAY; +} + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +int +mp_2expt (mp_int * a, int b) +{ + int res; + + /* zero a as per default */ + mp_zero (a); + + /* grow a to accomodate the single bit */ + if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + + /* set the used count of where the bit will go */ + a->used = b / DIGIT_BIT + 1; + + /* put the single bit in its place */ + a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); + + return MP_OKAY; +} + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +int +mp_abs (mp_int * a, mp_int * b) +{ + int res; + + /* copy a to b */ + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} + +/* high level addition (handles signs) */ +int mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag (a, b) == MP_LT) { + c->sign = sb; + res = s_mp_sub (b, a, c); + } else { + c->sign = sa; + res = s_mp_sub (a, b, c); + } + } + return res; +} + + +/* single digit addition */ +int +mp_add_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, ix, oldused; + mp_digit *tmpa, *tmpc, mu; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { + /* temporarily fix sign of a */ + a->sign = MP_ZPOS; + + /* c = |a| - b */ + res = mp_sub_d(a, b, c); + + /* fix sign */ + a->sign = c->sign = MP_NEG; + + return res; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digit, after this we're propagating + * the carry. + */ + *tmpc = *tmpa++ + b; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + + /* now handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + ix++; + *tmpc++ = mu; + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } + + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } + + /* now zero to oldused */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + + return MP_OKAY; +} + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void +mp_clamp (mp_int * a) +{ + /* decrease used while the most significant digit is + * zero. + */ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } + + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = MP_ZPOS; + } +} + +/* clear one (frees) */ +void +mp_clear (mp_int * a) +{ + int i; + + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* first zero the digits */ + for (i = 0; i < a->used; i++) { + a->dp[i] = 0; + } + + /* free ram */ + free(a->dp); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} + + +void mp_clear_multi(mp_int *mp, ...) +{ + mp_int* next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int*); + } + va_end(args); +} + +/* compare two ints (signed)*/ +int +mp_cmp (mp_int * a, mp_int * b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + if (a->sign == MP_NEG) { + return MP_LT; + } else { + return MP_GT; + } + } + + /* compare digits */ + if (a->sign == MP_NEG) { + /* if negative compare opposite direction */ + return mp_cmp_mag(b, a); + } else { + return mp_cmp_mag(a, b); + } +} + +/* compare a digit */ +int mp_cmp_d(mp_int * a, mp_digit b) +{ + /* compare based on sign */ + if (a->sign == MP_NEG) { + return MP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return MP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return MP_GT; + } else if (a->dp[0] < b) { + return MP_LT; + } else { + return MP_EQ; + } +} + +/* compare maginitude of two ints (unsigned) */ +int mp_cmp_mag (mp_int * a, mp_int * b) +{ + int n; + mp_digit *tmpa, *tmpb; + + /* compare based on # of non-zero digits */ + if (a->used > b->used) { + return MP_GT; + } + + if (a->used < b->used) { + return MP_LT; + } + + /* alias for a */ + tmpa = a->dp + (a->used - 1); + + /* alias for b */ + tmpb = b->dp + (a->used - 1); + + /* compare based on digits */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return MP_GT; + } + + if (*tmpa < *tmpb) { + return MP_LT; + } + } + return MP_EQ; +} + +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a) +{ + int x; + mp_digit q, qq; + + /* easy out */ + if (mp_iszero(a) == 1) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; x < a->used && a->dp[x] == 0; x++); + q = a->dp[x]; + x *= DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1) == 0) { + do { + qq = q & 15; + x += lnz[qq]; + q >>= 4; + } while (qq == 0); + } + return x; +} + +/* copy, b = a */ +int +mp_copy (const mp_int * a, mp_int * b) +{ + int res, n; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + /* zero b and copy the parameters over */ + { + register mp_digit *tmpa, *tmpb; + + /* pointer aliases */ + + /* source */ + tmpa = a->dp; + + /* destination */ + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->used; n++) { + *tmpb++ = 0; + } + } + + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; +} + +/* returns the number of bits in an int */ +int +mp_count_bits (mp_int * a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((mp_digit) 0)) { + ++r; + q >>= ((mp_digit) 1); + } + return r; +} + +/* integer signed division. + * c*b + d == a [e.g. a/b, c=quotient, d=remainder] + * HAC pp.598 Algorithm 14.20 + * + * Note that the description in HAC is horribly + * incomplete. For example, it doesn't consider + * the case where digits are removed from 'x' in + * the inner loop. It also doesn't consider the + * case that y has fewer than three digits, etc.. + * + * The overall algorithm is as described as + * 14.20 from HAC but fixed to treat these cases. +*/ +int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int q, x, y, t1, t2; + int res, n, t, i, norm, neg; + + /* is divisor zero ? */ + if (mp_iszero (b) == 1) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { + return res; + } + q.used = a->used + 2; + + if ((res = mp_init (&t1)) != MP_OKAY) { + goto __Q; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto __T1; + } + + if ((res = mp_init_copy (&x, a)) != MP_OKAY) { + goto __T2; + } + + if ((res = mp_init_copy (&y, b)) != MP_OKAY) { + goto __X; + } + + /* fix the sign */ + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + x.sign = y.sign = MP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ + norm = mp_count_bits(&y) % DIGIT_BIT; + if (norm < (int)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { + goto __Y; + } + if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { + goto __Y; + } + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ + goto __Y; + } + + while (mp_cmp (&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { + goto __Y; + } + } + + /* reset y by shifting it back down */ + mp_rshd (&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x.dp[i] == y.dp[t]) { + q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); + } else { + mp_word tmp; + tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); + tmp |= ((mp_word) x.dp[i - 1]); + tmp /= ((mp_word) y.dp[t]); + if (tmp > (mp_word) MP_MASK) + tmp = MP_MASK; + q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; + do { + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; + + /* find left hand */ + mp_zero (&t1); + t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto __Y; + } + + /* find right hand */ + t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; + t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; + t2.dp[2] = x.dp[i]; + t2.used = 3; + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto __Y; + } + + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto __Y; + } + + if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { + goto __Y; + } + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (x.sign == MP_NEG) { + if ((res = mp_copy (&y, &t1)) != MP_OKAY) { + goto __Y; + } + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto __Y; + } + if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { + goto __Y; + } + + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; + } + } + + /* now q is the quotient and x is the remainder + * [which we have to normalize] + */ + + /* get sign before writing to c */ + x.sign = x.used == 0 ? MP_ZPOS : a->sign; + + if (c != NULL) { + mp_clamp (&q); + mp_exch (&q, c); + c->sign = neg; + } + + if (d != NULL) { + mp_div_2d (&x, norm, &x, NULL); + mp_exch (&x, d); + } + + res = MP_OKAY; + +__Y:mp_clear (&y); +__X:mp_clear (&x); +__T2:mp_clear (&t2); +__T1:mp_clear (&t1); +__Q:mp_clear (&q); + return res; +} + +/* b = a/2 */ +int mp_div_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* copy */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + mp_clamp (b); + return MP_OKAY; +} + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) +{ + mp_digit D, r, rr; + int x, res; + mp_int t; + + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + res = mp_copy (a, c); + if (d != NULL) { + mp_zero (d); + } + return res; + } + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + /* get the remainder */ + if (d != NULL) { + if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + mp_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (mp_digit) (b % DIGIT_BIT); + if (D != 0) { + register mp_digit *tmpc, mask, shift; + + /* mask */ + mask = (((mp_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from the previous word */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp (c); + if (d != NULL) { + mp_exch (&t, d); + } + mp_clear (&t); + return MP_OKAY; +} + +static int s_is_power_of_two(mp_digit b, int *p) +{ + int x; + + for (x = 1; x < DIGIT_BIT; x++) { + if (b == (((mp_digit)1)<dp[0] & ((((mp_digit)1)<used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= b) { + t = (mp_digit)(w / b); + w -= ((mp_word)t) * ((mp_word)b); + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Loong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + * + * Input x must be in the range 0 <= x <= (n-1)**2 + */ +int +mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) +{ + int err, i, m; + mp_word r; + mp_digit mu, *tmpx1, *tmpx2; + + /* m = digits in modulus */ + m = n->used; + + /* ensure that "x" has at least 2m digits */ + if (x->alloc < m + m) { + if ((err = mp_grow (x, m + m)) != MP_OKAY) { + return err; + } + } + +/* top of loop, this is where the code resumes if + * another reduction pass is required. + */ +top: + /* aliases for digits */ + /* alias for lower half of x */ + tmpx1 = x->dp; + + /* alias for upper half of x, or x/B**m */ + tmpx2 = x->dp + m; + + /* set carry to zero */ + mu = 0; + + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; + *tmpx1++ = (mp_digit)(r & MP_MASK); + mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT)); + } + + /* set final carry */ + *tmpx1++ = mu; + + /* zero words above m */ + for (i = m + 1; i < x->used; i++) { + *tmpx1++ = 0; + } + + /* clamp, sub and return */ + mp_clamp (x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag (x, n) != MP_LT) { + s_mp_sub(x, n, x); + goto top; + } + return MP_OKAY; +} + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void +mp_exch (mp_int * a, mp_int * b) +{ + mp_int t; + + t = *a; + *a = *b; + *b = t; +} + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted alot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + int dr; + + /* modulus P must be positive */ + if (P->sign == MP_NEG) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (X->sign == MP_NEG) { + mp_int tmpG, tmpX; + int err; + + /* first compute 1/G mod P */ + if ((err = mp_init(&tmpG)) != MP_OKAY) { + return err; + } + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + + /* now get |X| */ + if ((err = mp_init(&tmpX)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + dr = 0; + + /* if the modulus is odd or dr != 0 use the fast method */ + if (mp_isodd (P) == 1 || dr != 0) { + return mp_exptmod_fast (G, X, P, Y, dr); + } else { + /* otherwise use the generic Barrett reduction technique */ + return s_mp_exptmod (G, X, P, Y); + } +} + +/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ + +int +mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[256], res; + mp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + int (*redux)(mp_int*,mp_int*,mp_digit); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { + goto __M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (((P->used * 2 + 1) < MP_WARRAY) && + P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + redux = fast_mp_montgomery_reduce; + } else { + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; + } + } else if (redmode == 1) { + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; + } else { + /* setup DR reduction for moduli of the form 2**k - b */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { + goto __M; + } + redux = mp_reduce_2k; + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto __M; + } + + /* create M table + * + + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { + goto __RES; + } + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { + goto __RES; + } + } else { + mp_set(&res, 1); + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { + goto __RES; + } + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __RES; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&M[x], P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + if ((err = redux(&res, P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* swap res with Y */ + mp_exch (&res, Y); + err = MP_OKAY; +__RES:mp_clear (&res); +__M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} + +/* Greatest Common Divisor using the binary method */ +int mp_gcd (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int u, v; + int k, u_lsb, v_lsb, res; + + /* either zero than gcd is the largest */ + if (mp_iszero (a) == 1 && mp_iszero (b) == 0) { + return mp_abs (b, c); + } + if (mp_iszero (a) == 0 && mp_iszero (b) == 1) { + return mp_abs (a, c); + } + + /* optimized. At this point if a == 0 then + * b must equal zero too + */ + if (mp_iszero (a) == 1) { + mp_zero(c); + return MP_OKAY; + } + + /* get copies of a and b we can modify */ + if ((res = mp_init_copy (&u, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init_copy (&v, b)) != MP_OKAY) { + goto __U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto __V; + } + + if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto __V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto __V; + } + } + + if (v_lsb != k) { + if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto __V; + } + } + + while (mp_iszero(&v) == 0) { + /* make sure v is the largest */ + if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ + mp_exch(&u, &v); + } + + /* subtract smallest from largest */ + if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto __V; + } + + /* Divide out all factors of two */ + if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { + goto __V; + } + } + + /* multiply by 2**k which we divided out at the beginning */ + if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { + goto __V; + } + c->sign = MP_ZPOS; + res = MP_OKAY; +__V:mp_clear (&u); +__U:mp_clear (&v); + return res; +} + +/* get the lower 32-bits of an mp_int */ +unsigned long mp_get_int(mp_int * a) +{ + int i; + unsigned long res; + + if (a->used == 0) { + return 0; + } + + /* get number of digits of the lsb we have to read */ + i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1; + + /* get most significant digit of result */ + res = DIGIT(a,i); + + while (--i >= 0) { + res = (res << DIGIT_BIT) | DIGIT(a,i); + } + + /* force result to 32-bits always so it is consistent on non 32-bit platforms */ + return res & 0xFFFFFFFFUL; +} + +/* grow as required */ +int mp_grow (mp_int * a, int size) +{ + int i; + mp_digit *tmp; + + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + /* ensure there are always at least MP_PREC digits extra on top */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* reallocate the array a->dp + * + * We store the return in a temporary variable + * in case the operation failed we don't want + * to overwrite the dp member of a. + */ + tmp = realloc (a->dp, sizeof (mp_digit) * size); + if (tmp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } + + /* reallocation succeeded so set a->dp */ + a->dp = tmp; + + /* zero excess digits */ + i = a->alloc; + a->alloc = size; + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return MP_OKAY; +} + +/* init a new mp_int */ +int mp_init (mp_int * a) +{ + int i; + + /* allocate memory required and clear it */ + a->dp = malloc (sizeof (mp_digit) * MP_PREC); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the digits to zero */ + for (i = 0; i < MP_PREC; i++) { + a->dp[i] = 0; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_PREC; + a->sign = MP_ZPOS; + + return MP_OKAY; +} + +/* creates "a" then copies b into it */ +int mp_init_copy (mp_int * a, const mp_int * b) +{ + int res; + + if ((res = mp_init (a)) != MP_OKAY) { + return res; + } + return mp_copy (b, a); +} + +int mp_init_multi(mp_int *mp, ...) +{ + mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ + int n = 0; /* Number of ok inits */ + mp_int* cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + if (mp_init(cur_arg) != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* end the current list */ + va_end(args); + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n--) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int*); + } + va_end(clean_args); + res = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int*); + } + va_end(args); + return res; /* Assumed ok, if error flagged above. */ +} + +/* init an mp_init for a given size */ +int mp_init_size (mp_int * a, int size) +{ + int x; + + /* pad size so there are always extra digits */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* alloc mem */ + a->dp = malloc (sizeof (mp_digit) * size); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + /* zero the digits */ + for (x = 0; x < size; x++) { + a->dp[x] = 0; + } + + return MP_OKAY; +} + +/* hac 14.61, pp608 */ +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + return MP_VAL; + } + + /* if the modulus is odd we can use a faster routine instead */ + if (mp_isodd (b) == 1) { + return fast_mp_invmod (a, b, c); + } + + return mp_invmod_slow(a, b, c); +} + +/* hac 14.61, pp608 */ +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, A, B, C, D; + int res; + + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + return MP_VAL; + } + + /* init temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x = a, y = b */ + if ((res = mp_copy (a, &x)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_copy (b, &y)) != MP_OKAY) { + goto __ERR; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + res = MP_VAL; + goto __ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto __ERR; + } + mp_set (&A, 1); + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto __ERR; + } + /* 4.2 if A or B is odd then */ + if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto __ERR; + } + } + /* A = A/2, B = B/2 */ + if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto __ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto __ERR; + } + /* 5.2 if C or D is odd then */ + if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto __ERR; + } + } + /* C = C/2, D = D/2 */ + if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto __ERR; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto __ERR; + } + + /* if its too low */ + while (mp_cmp_d(&C, 0) == MP_LT) { + if ((res = mp_add(&C, b, &C)) != MP_OKAY) { + goto __ERR; + } + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { + goto __ERR; + } + } + + /* C is now the inverse */ + mp_exch (&C, c); + res = MP_OKAY; +__ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return res; +} + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**DIGIT_BIT] and + * let n represent half of the number of digits in + * the min(a,b) + * + * a = a1 * B**n + a0 + * b = b1 * B**n + b0 + * + * Then, a * b => + a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0 + * + * Note that a1b1 and a0b0 are used twice and only need to be + * computed once. So in total three half size (half # of + * digit) multiplications are performed, a0b0, a1b1 and + * (a1-b1)(a0-b0) + * + * Note that a multiplication of half the digits requires + * 1/4th the number of single precision multiplications so in + * total after one call 25% of the single precision multiplications + * are saved. Note also that the call to mp_mul can end up back + * in this function if the a0, a1, b0, or b1 are above the threshold. + * This is known as divide-and-conquer and leads to the famous + * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than + * the standard O(N**2) that the baseline/comba methods use. + * Generally though the overhead of this method doesn't pay off + * until a certain size (N ~ 80) is reached. + */ +int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B, err; + + /* default the return code to an error */ + err = MP_MEM; + + /* min # of digits */ + B = MIN (a->used, b->used); + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + if (mp_init_size (&y0, B) != MP_OKAY) + goto X1; + if (mp_init_size (&y1, b->used - B) != MP_OKAY) + goto Y0; + + /* init temps */ + if (mp_init_size (&t1, B * 2) != MP_OKAY) + goto Y1; + if (mp_init_size (&x0y0, B * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x1y1, B * 2) != MP_OKAY) + goto X0Y0; + + /* now shift the digits */ + x0.used = y0.used = B; + x1.used = a->used - B; + y1.used = b->used - B; + + { + register int x; + register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; + + /* we copy the digits directly instead of using higher level functions + * since we also need to shift the digits + */ + tmpa = a->dp; + tmpb = b->dp; + + tmpx = x0.dp; + tmpy = y0.dp; + for (x = 0; x < B; x++) { + *tmpx++ = *tmpa++; + *tmpy++ = *tmpb++; + } + + tmpx = x1.dp; + for (x = B; x < a->used; x++) { + *tmpx++ = *tmpa++; + } + + tmpy = y1.dp; + for (x = B; x < b->used; x++) { + *tmpy++ = *tmpb++; + } + } + + /* only need to clamp the lower words since by definition the + * upper words x1/y1 must have a known number of digits + */ + mp_clamp (&x0); + mp_clamp (&y0); + + /* now calc the products x0y0 and x1y1 */ + /* after this x0 is no longer required, free temp [x0==t2]! */ + if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) + goto X1Y1; /* x0y0 = x0*y0 */ + if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) + goto X1Y1; /* x1y1 = x1*y1 */ + + /* now calc x1-x0 and y1-y0 */ + if (mp_sub (&x1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = x1 - x0 */ + if (mp_sub (&y1, &y0, &x0) != MP_OKAY) + goto X1Y1; /* t2 = y1 - y0 */ + if (mp_mul (&t1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = (x1 - x0) * (y1 - y0) */ + + /* add x0y0 */ + if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY) + goto X1Y1; /* t2 = x0y0 + x1y1 */ + if (mp_sub (&x0, &t1, &t1) != MP_OKAY) + goto X1Y1; /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + + /* init temps */ + if (mp_init_size (&t1, a->used * 2) != MP_OKAY) + goto X1; + if (mp_init_size (&t2, a->used * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x0x0, B * 2) != MP_OKAY) + goto T2; + if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) + goto X0X0; + + { + register int x; + register mp_digit *dst, *src; + + src = a->dp; + + /* now shift the digits */ + dst = x0.dp; + for (x = 0; x < B; x++) { + *dst++ = *src++; + } + + dst = x1.dp; + for (x = B; x < a->used; x++) { + *dst++ = *src++; + } + } + + x0.used = B; + x1.used = a->used - B; + + mp_clamp (&x0); + + /* now calc the products x0*x0 and x1*x1 */ + if (mp_sqr (&x0, &x0x0) != MP_OKAY) + goto X1X1; /* x0x0 = x0*x0 */ + if (mp_sqr (&x1, &x1x1) != MP_OKAY) + goto X1X1; /* x1x1 = x1*x1 */ + + /* now calc (x1-x0)**2 */ + if (mp_sub (&x1, &x0, &t1) != MP_OKAY) + goto X1X1; /* t1 = x1 - x0 */ + if (mp_sqr (&t1, &t1) != MP_OKAY) + goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ + + /* add x0y0 */ + if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) + goto X1X1; /* t2 = x0x0 + x1x1 */ + if (mp_sub (&t2, &t1, &t1) != MP_OKAY) + goto X1X1; /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<sign = MP_ZPOS; + +__T: + mp_clear_multi (&t1, &t2, NULL); + return res; +} + +/* shift left a certain amount of digits */ +int mp_lshd (mp_int * a, int b) +{ + int x, res; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if (a->alloc < a->used + b) { + if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { + return res; + } + } + + { + register mp_digit *top, *bottom; + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* top */ + top = a->dp + a->used - 1; + + /* base */ + bottom = a->dp + a->used - 1 - b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the otherway around. Copying from + * the bottom to the top. see bn_mp_rshd.c for more info. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return MP_OKAY; +} + +/* c = a mod b, 0 <= c < b */ +int +mp_mod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int t; + int res; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if (t.sign != b->sign) { + res = mp_add (b, &t, c); + } else { + res = MP_OKAY; + mp_exch (&t, c); + } + + mp_clear (&t); + return res; +} + +/* calc a value mod 2**b */ +int +mp_mod_2d (mp_int * a, int b, mp_int * c) +{ + int x, res; + + /* if b is <= 0 then zero the int */ + if (b <= 0) { + mp_zero (c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b > (int) (a->used * DIGIT_BIT)) { + res = mp_copy (a, c); + return res; + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= + (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); + mp_clamp (c); + return MP_OKAY; +} + +int +mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) +{ + return mp_div_d(a, b, NULL, c); +} + +/* + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves alot of multiple precision shifting. + */ +int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) +{ + int x, bits, res; + + /* how many bits of last digit does b use */ + bits = mp_count_bits (b) % DIGIT_BIT; + + + if (b->used > 1) { + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { + return res; + } + } else { + mp_set(a, 1); + bits = 1; + } + + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)DIGIT_BIT; x++) { + if ((res = mp_mul_2 (a, a)) != MP_OKAY) { + return res; + } + if (mp_cmp_mag (a, b) != MP_LT) { + if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { + return res; + } + } + } + + return MP_OKAY; +} + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +int +mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, digs; + mp_digit mu; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = n->used * 2 + 1; + if ((digs < MP_WARRAY) && + n->used < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_mp_montgomery_reduce (x, n, rho); + } + + /* grow the input as required */ + if (x->alloc < digs) { + if ((res = mp_grow (x, digs)) != MP_OKAY) { + return res; + } + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * rho mod b + * + * The value of rho must be precalculated via + * montgomery_setup() such that + * it equals -1/n0 mod b this allows the + * following inner loop to reduce the + * input one digit at a time + */ + mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK); + + /* a = a + mu * m * b**i */ + { + register int iy; + register mp_digit *tmpn, *tmpx, u; + register mp_word r; + + /* alias for digits of the modulus */ + tmpn = n->dp; + + /* alias for the digits of x [the input] */ + tmpx = x->dp + ix; + + /* set the carry to zero */ + u = 0; + + /* Multiply and add in place */ + for (iy = 0; iy < n->used; iy++) { + /* compute product and sum */ + r = ((mp_word)mu) * ((mp_word)*tmpn++) + + ((mp_word) u) + ((mp_word) * tmpx); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* fix digit */ + *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK)); + } + /* At this point the ix'th digit of x should be zero */ + + + /* propagate carries upwards as required*/ + while (u) { + *tmpx += u; + u = *tmpx >> DIGIT_BIT; + *tmpx++ &= MP_MASK; + } + } + } + + /* at this point the n.used'th least + * significant digits of x are all zero + * which means we can shift x to the + * right by n.used digits and the + * residue is unchanged. + */ + + /* x = x/b**n.used */ + mp_clamp(x); + mp_rshd (x, n->used); + + /* if x >= n then x = x - n */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + + return MP_OKAY; +} + +/* setups the montgomery reduction stuff */ +int +mp_montgomery_setup (mp_int * n, mp_digit * rho) +{ + mp_digit x, b; + +/* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1) == 0) { + return MP_VAL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; + + return MP_OKAY; +} + +/* high level multiplication (handles sign) */ +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +{ + int res, neg; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + + /* use Karatsuba? */ + if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { + res = mp_karatsuba_mul (a, b, c); + } else + { + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + int digs = a->used + b->used + 1; + + if ((digs < MP_WARRAY) && + MIN(a->used, b->used) <= + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + res = fast_s_mp_mul_digs (a, b, c, digs); + } else + res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ + } + c->sign = (c->used > 0) ? neg : MP_ZPOS; + return res; +} + +/* b = a*2 */ +int mp_mul_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* grow to accomodate result */ + if (b->alloc < a->used + 1) { + if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return MP_OKAY; +} + +/* shift left by a certain bit count */ +int mp_mul_2d (mp_int * a, int b, mp_int * c) +{ + mp_digit d; + int res; + + /* copy */ + if (a != c) { + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + } + + if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { + if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { + return res; + } + } + + /* shift any bit count < DIGIT_BIT */ + d = (mp_digit) (b % DIGIT_BIT); + if (d != 0) { + register mp_digit *tmpc, shift, mask, r, rr; + register int x; + + /* bitmask for carries */ + mask = (((mp_digit)1) << d) - 1; + + /* shift for msbs */ + shift = DIGIT_BIT - d; + + /* alias */ + tmpc = c->dp; + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + rr = (*tmpc >> shift) & mask; + + /* shift the current word and OR in the carry */ + *tmpc = ((*tmpc << d) | r) & MP_MASK; + ++tmpc; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + + /* set final carry */ + if (r != 0) { + c->dp[(c->used)++] = r; + } + } + mp_clamp (c); + return MP_OKAY; +} + +/* multiply by a digit */ +int +mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit u, *tmpa, *tmpc; + mp_word r; + int ix, res, olduse; + + /* make sure c is big enough to hold a*b */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* get the original destinations used count */ + olduse = c->used; + + /* set the sign */ + c->sign = a->sign; + + /* alias for a->dp [source] */ + tmpa = a->dp; + + /* alias for c->dp [dest] */ + tmpc = c->dp; + + /* zero carry */ + u = 0; + + /* compute columns */ + for (ix = 0; ix < a->used; ix++) { + /* compute product and carry sum for this term */ + r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); + + /* mask off higher bits to get a single digit */ + *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* send carry into next iteration */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + + /* store final carry [if any] */ + *tmpc++ = u; + + /* now zero digits above the top */ + while (ix++ < olduse) { + *tmpc++ = 0; + } + + /* set used count */ + c->used = a->used + 1; + mp_clamp(c); + + return MP_OKAY; +} + +/* d = a * b (mod c) */ +int +mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_mul (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} + +/* determines if an integers is divisible by one + * of the first PRIME_SIZE primes or not + * + * sets result to 0 if not, 1 if yes + */ +int mp_prime_is_divisible (mp_int * a, int *result) +{ + int err, ix; + mp_digit res; + + /* default to not */ + *result = MP_NO; + + for (ix = 0; ix < PRIME_SIZE; ix++) { + /* what is a mod __prime_tab[ix] */ + if ((err = mp_mod_d (a, __prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0) { + *result = MP_YES; + return MP_OKAY; + } + } + + return MP_OKAY; +} + +/* performs a variable number of rounds of Miller-Rabin + * + * Probability of error after t rounds is no more than + + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime (mp_int * a, int t, int *result) +{ + mp_int b; + int ix, err, res; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, __prime_tab[ix]) == MP_EQ) { + *result = 1; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + + for (ix = 0; ix < t; ix++) { + /* set the prime */ + mp_set (&b, __prime_tab[ix]); + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto __B; + } + + if (res == MP_NO) { + goto __B; + } + } + + /* passed the test */ + *result = MP_YES; +__B:mp_clear (&b); + return err; +} + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) +{ + mp_int n1, y, r; + int s, j, err; + + /* default */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1) != MP_GT) { + return MP_VAL; + } + + /* get n1 = a - 1 */ + if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { + goto __N1; + } + + /* set 2**s * r = n1 */ + if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { + goto __N1; + } + + /* count the number of least significant bits + * which are zero + */ + s = mp_cnt_lsb(&r); + + /* now divide n - 1 by 2**s */ + if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) { + goto __R; + } + + /* compute y = b**r mod a */ + if ((err = mp_init (&y)) != MP_OKAY) { + goto __R; + } + if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { + goto __Y; + } + + /* if y != 1 and y != n1 do */ + if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { + if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { + goto __Y; + } + + /* if y == 1 then composite */ + if (mp_cmp_d (&y, 1) == MP_EQ) { + goto __Y; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp (&y, &n1) != MP_EQ) { + goto __Y; + } + } + + /* probably prime now */ + *result = MP_YES; +__Y:mp_clear (&y); +__R:mp_clear (&r); +__N1:mp_clear (&n1); + return err; +} + +static const struct { + int k, t; +} sizes[] = { +{ 128, 28 }, +{ 256, 16 }, +{ 384, 10 }, +{ 512, 7 }, +{ 640, 6 }, +{ 768, 5 }, +{ 896, 4 }, +{ 1024, 4 } +}; + +/* returns # of RM trials required for a given bit size */ +int mp_prime_rabin_miller_trials(int size) +{ + int x; + + for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { + if (sizes[x].k == size) { + return sizes[x].t; + } else if (sizes[x].k > size) { + return (x == 0) ? sizes[0].t : sizes[x - 1].t; + } + } + return sizes[x-1].t + 1; +} + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ + +/* This is possibly the mother of all prime generation functions, muahahahahaha! */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat) +{ + unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; + int res, err, bsize, maskOR_msb_offset; + + /* sanity check the input */ + if (size <= 1 || t <= 0) { + return MP_VAL; + } + + /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */ + if (flags & LTM_PRIME_SAFE) { + flags |= LTM_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3)+(size&7?1:0); + + /* we need a buffer of bsize bytes */ + tmp = malloc(bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = 0xFF >> (8 - (size & 7)); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = (size - 2) >> 3; + if (flags & LTM_PRIME_2MSB_ON) { + maskOR_msb |= 1 << ((size - 2) & 7); + } else if (flags & LTM_PRIME_2MSB_OFF) { + maskAND &= ~(1 << ((size - 2) & 7)); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 0; + if (flags & LTM_PRIME_BBS) { + maskOR_lsb |= 3; + } + + do { + /* read the bytes */ + if (cb(tmp, bsize, dat) != bsize) { + err = MP_VAL; + goto error; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= 1 << ((size - 1) & 7); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + if (res == MP_NO) { + continue; + } + + if (flags & LTM_PRIME_SAFE) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; } + if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + } + } while (res == MP_NO); + + if (flags & LTM_PRIME_SAFE) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; } + if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; } + } + + err = MP_OKAY; +error: + free(tmp); + return err; +} + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +int +mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c) +{ + int res; + + /* make sure there are at least two digits */ + if (a->alloc < 2) { + if ((res = mp_grow(a, 2)) != MP_OKAY) { + return res; + } + } + + /* zero the int */ + mp_zero (a); + + /* read the bytes in */ + while (c-- > 0) { + if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { + return res; + } + + a->dp[0] |= *b++; + a->used += 1; + } + mp_clamp (a); + return MP_OKAY; +} + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +int +mp_reduce (mp_int * x, mp_int * m, mp_int * mu) +{ + mp_int q; + int res, um = m->used; + + /* q = x */ + if ((res = mp_init_copy (&q, x)) != MP_OKAY) { + return res; + } + + /* q1 = x / b**(k-1) */ + mp_rshd (&q, um - 1); + + /* according to HAC this optimization is ok */ + if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { + if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else { + if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { + goto CLEANUP; + } + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd (&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto CLEANUP; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + + /* x = x - q */ + if ((res = mp_sub (x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d (x, 0) == MP_LT) { + mp_set (&q, 1); + if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if ((res = mp_add (x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while (mp_cmp (x, m) != MP_LT) { + if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { + goto CLEANUP; + } + } + +CLEANUP: + mp_clear (&q); + + return res; +} + +/* reduces a modulo n where n is of the form 2**p - d */ +int +mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (d != 1) { + /* q = q * d */ + if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + +/* determines the setup value */ +int +mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +int mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} + +/* shift right a certain amount of digits */ +void mp_rshd (mp_int * a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero (a); + return; + } + + { + register mp_digit *bottom, *top; + + /* shift the digits down */ + + /* bottom */ + bottom = a->dp; + + /* top [offset into digits] */ + top = a->dp + b; + + /* this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + *bottom++ = *top++; + } + + /* zero the top digits */ + for (; x < a->used; x++) { + *bottom++ = 0; + } + } + + /* remove excess digits */ + a->used -= b; +} + +/* set to a digit */ +void mp_set (mp_int * a, mp_digit b) +{ + mp_zero (a); + a->dp[0] = b & MP_MASK; + a->used = (a->dp[0] != 0) ? 1 : 0; +} + +/* set a 32-bit const */ +int mp_set_int (mp_int * a, unsigned long b) +{ + int x, res; + + mp_zero (a); + + /* set four bits at a time */ + for (x = 0; x < 8; x++) { + /* shift the number up four bits */ + if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + return res; + } + + /* OR in the top four bits of the source */ + a->dp[0] |= (b >> 28) & 15; + + /* shift the source up to the next four bits */ + b <<= 4; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + mp_clamp (a); + return MP_OKAY; +} + +/* shrink a bignum */ +int mp_shrink (mp_int * a) +{ + mp_digit *tmp; + if (a->alloc != a->used && a->used > 0) { + if ((tmp = realloc (a->dp, sizeof (mp_digit) * a->used)) == NULL) { + return MP_MEM; + } + a->dp = tmp; + a->alloc = a->used; + } + return MP_OKAY; +} + +/* get the size for an signed equivalent */ +int mp_signed_bin_size (mp_int * a) +{ + return 1 + mp_unsigned_bin_size (a); +} + +/* computes b = a*a */ +int +mp_sqr (mp_int * a, mp_int * b) +{ + int res; + +if (a->used >= KARATSUBA_SQR_CUTOFF) { + res = mp_karatsuba_sqr (a, b); + } else + { + /* can we use the fast comba multiplier? */ + if ((a->used * 2 + 1) < MP_WARRAY && + a->used < + (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { + res = fast_s_mp_sqr (a, b); + } else + res = s_mp_sqr (a, b); + } + b->sign = MP_ZPOS; + return res; +} + +/* c = a * a (mod b) */ +int +mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sqr (a, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, b, c); + mp_clear (&t); + return res; +} + +/* high level subtraction (handles signs) */ +int +mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag (a, b) != MP_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + res = s_mp_sub (a, b, c); + } else { + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; + /* The second has a larger magnitude */ + res = s_mp_sub (b, a, c); + } + } + return res; +} + +/* single digit subtraction */ +int +mp_sub_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit *tmpa, *tmpc, mu; + int res, ix, oldused; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + a->sign = MP_ZPOS; + res = mp_add_d(a, b, c); + a->sign = c->sign = MP_NEG; + return res; + } + + /* setup regs */ + oldused = c->used; + tmpa = a->dp; + tmpc = c->dp; + + /* if a <= b simply fix the single digit */ + if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } + ix = 1; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract first digit */ + *tmpc = *tmpa++ - b; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + + /* handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + } + } + + /* zero excess digits */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + return MP_OKAY; +} + +/* store in unsigned [big endian] format */ +int +mp_to_unsigned_bin (mp_int * a, unsigned char *b) +{ + int x, res; + mp_int t; + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + x = 0; + while (mp_iszero (&t) == 0) { + b[x++] = (unsigned char) (t.dp[0] & 255); + if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + bn_reverse (b, x); + mp_clear (&t); + return MP_OKAY; +} + +/* get the size for an unsigned equivalent */ +int +mp_unsigned_bin_size (mp_int * a) +{ + int size = mp_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} + +/* set to zero */ +void +mp_zero (mp_int * a) +{ + a->sign = MP_ZPOS; + a->used = 0; + memset (a->dp, 0, sizeof (mp_digit) * a->alloc); +} + +const mp_digit __prime_tab[] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +}; + +/* reverse an array, used for radix code */ +void +bn_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +int +s_mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int *x; + int olduse, res, min, max; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used > b->used) { + min = b->used; + max = a->used; + x = a; + } else { + min = a->used; + max = b->used; + x = b; + } + + /* init result */ + if (c->alloc < max + 1) { + if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + return res; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + + /* first input */ + tmpa = a->dp; + + /* second input */ + tmpb = b->dp; + + /* destination */ + tmpc = c->dp; + + /* zero the carry */ + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + *tmpc = *tmpa++ + *tmpb++ + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = X[i] + U */ + *tmpc = x->dp[i] + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above oldused */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + mp_int M[256], res, mu; + mp_digit buf; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init (&mu)) != MP_OKAY) { + goto __M; + } + if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { + goto __MU; + } + + /* create M table + * + * The M table contains powers of the base, + * e.g. M[x] = G**x mod P + * + * The first half of the table is not + * computed though accept for M[0] and M[1] + */ + if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { + goto __MU; + } + + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __MU; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], + &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __MU; + } + if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { + goto __MU; + } + } + + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto __MU; + } + if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) { + goto __MU; + } + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto __MU; + } + mp_set (&res, 1); + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ + if (digidx == -1) { + break; + } + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int) DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + } + } + } + + mp_exch (&res, Y); + err = MP_OKAY; +__RES:mp_clear (&res); +__MU:mp_clear (&mu); +__M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} + +/* multiplies |a| * |b| and only computes upto digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +int +s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if (((digs) < MP_WARRAY) && + MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, digs)) != MP_OKAY) { + return res; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + /* set the carry to zero */ + u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MIN (b->used, digs - ix); + + /* setup some aliases */ + /* copy of the digit from a used within the nested loop */ + tmpx = a->dp[ix]; + + /* an alias for the destination shifted ix places */ + tmpt = t.dp + ix; + + /* an alias for the digits of b */ + tmpy = b->dp; + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* the new column is the lower part of the result */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry word from the result */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + /* set carry if it is placed below digs */ + if (ix + iy < digs) { + *tmpt = u; + } + } + + mp_clamp (&t); + mp_exch (&t, c); + + mp_clear (&t); + return MP_OKAY; +} + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +int +s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if (((a->used + b->used + 1) < MP_WARRAY) + && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_high_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { + return res; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa; ix++) { + /* clear the carry */ + u = 0; + + /* left hand side of A[ix] * B[iy] */ + tmpx = a->dp[ix]; + + /* alias to the address of where the digits will be stored */ + tmpt = &(t.dp[digs]); + + /* alias for where to read the right hand side from */ + tmpy = b->dp + (digs - ix); + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* get the lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* carry the carry */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + *tmpt = u; + } + mp_clamp (&t); + mp_exch (&t, c); + mp_clear (&t); + return MP_OKAY; +} + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +int +s_mp_sqr (mp_int * a, mp_int * b) +{ + mp_int t; + int res, ix, iy, pa; + mp_word r; + mp_digit u, tmpx, *tmpt; + + pa = a->used; + if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { + return res; + } + + /* default used is maximum possible size */ + t.used = 2*pa + 1; + + for (ix = 0; ix < pa; ix++) { + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + r = ((mp_word) t.dp[2*ix]) + + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); + + /* store lower part in result */ + t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* left hand side of A[ix] * A[iy] */ + tmpx = a->dp[ix]; + + /* alias for where to store the results */ + tmpt = t.dp + (2*ix + 1); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); + + /* now calculate the double precision result, note we use + * addition instead of *2 since it's easier to optimize + */ + r = ((mp_word) *tmpt) + r + r + ((mp_word) u); + + /* store lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + /* propagate upwards */ + while (u != ((mp_digit) 0)) { + r = ((mp_word) *tmpt) + ((mp_word) u); + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + } + + mp_clamp (&t); + mp_exch (&t, b); + mp_clear (&t); + return MP_OKAY; +} + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +int +s_mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int olduse, res, min, max; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((res = mp_grow (c, max)) != MP_OKAY) { + return res; + } + } + olduse = c->used; + c->used = max; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +/* Known optimal configurations + + CPU /Compiler /MUL CUTOFF/SQR CUTOFF +------------------------------------------------------------- + Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-) + +*/ + +int KARATSUBA_MUL_CUTOFF = 88, /* Min. number of digits before Karatsuba multiplication is used. */ + KARATSUBA_SQR_CUTOFF = 128; /* Min. number of digits before Karatsuba squaring is used. */ diff --git a/dlls/rsaenh/rc2.c b/dlls/rsaenh/rc2.c new file mode 100644 index 00000000000..e07521bd12f --- /dev/null +++ b/dlls/rsaenh/rc2.c @@ -0,0 +1,203 @@ +/* + * dlls/rsaen/rc2.c + * RC2 functions + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#include "tomcrypt.h" + +/* 256-entry permutation table, probably derived somehow from pi */ +static const unsigned char permute[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 +}; + +int rc2_setup(const unsigned char *key, int keylen, int bits, int rounds, rc2_key *rc2) +{ + unsigned *xkey = rc2->xkey; + unsigned char tmp[128]; + unsigned T8, TM; + int i; + + if (keylen < 5 || keylen > 128) { + return CRYPT_INVALID_KEYSIZE; + } + + if (rounds != 0 && rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + /* Following comment is from Eric Young's rc2 code: */ + /* It has come to my attention that there are 2 versions of the RC2 + * key schedule. One which is normal, and anther which has a hook to + * use a reduced key length. + * BSAFE uses the 'retarded' version. What I previously shipped is + * the same as specifying 1024 for the 'bits' parameter. Bsafe uses + * a version where the bits parameter is the same as len*8 */ + /* Seems like MS uses the 'retarded' version, too. + * Adjust effective keylen bits */ + if (bits <= 0) bits = keylen << 3; + if (bits > 1024) bits = 1024; + + for (i = 0; i < keylen; i++) { + tmp[i] = key[i] & 255; + } + + /* Phase 1: Expand input key to 128 bytes */ + if (keylen < 128) { + for (i = keylen; i < 128; i++) { + tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255]; + } + } + + /* Phase 2 - reduce effective key size to "bits" */ + /*bits = keylen<<3; */ + T8 = (unsigned)(bits+7)>>3; + TM = (255 >> (unsigned)(7 & -bits)); + tmp[128 - T8] = permute[tmp[128 - T8] & TM]; + for (i = 127 - T8; i >= 0; i--) { + tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]]; + } + + /* Phase 3 - copy to xkey in little-endian order */ + for (i = 0; i < 64; i++) { + xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8); + } + + return CRYPT_OK; +} + +/**********************************************************************\ +* Encrypt an 8-byte block of plaintext using the given key. * +\**********************************************************************/ +void rc2_ecb_encrypt( const unsigned char *plain, + unsigned char *cipher, + rc2_key *rc2) +{ + unsigned *xkey; + unsigned x76, x54, x32, x10, i; + + xkey = rc2->xkey; + + x76 = ((unsigned)plain[7] << 8) + (unsigned)plain[6]; + x54 = ((unsigned)plain[5] << 8) + (unsigned)plain[4]; + x32 = ((unsigned)plain[3] << 8) + (unsigned)plain[2]; + x10 = ((unsigned)plain[1] << 8) + (unsigned)plain[0]; + + for (i = 0; i < 16; i++) { + x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF; + x10 = ((x10 << 1) | (x10 >> 15)); + + x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF; + x32 = ((x32 << 2) | (x32 >> 14)); + + x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF; + x54 = ((x54 << 3) | (x54 >> 13)); + + x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF; + x76 = ((x76 << 5) | (x76 >> 11)); + + if (i == 4 || i == 10) { + x10 = (x10 + xkey[x76 & 63]) & 0xFFFF; + x32 = (x32 + xkey[x10 & 63]) & 0xFFFF; + x54 = (x54 + xkey[x32 & 63]) & 0xFFFF; + x76 = (x76 + xkey[x54 & 63]) & 0xFFFF; + } + } + + cipher[0] = (unsigned char)x10; + cipher[1] = (unsigned char)(x10 >> 8); + cipher[2] = (unsigned char)x32; + cipher[3] = (unsigned char)(x32 >> 8); + cipher[4] = (unsigned char)x54; + cipher[5] = (unsigned char)(x54 >> 8); + cipher[6] = (unsigned char)x76; + cipher[7] = (unsigned char)(x76 >> 8); +} + +/**********************************************************************\ +* Decrypt an 8-byte block of ciphertext using the given key. * +\**********************************************************************/ +void rc2_ecb_decrypt( const unsigned char *cipher, + unsigned char *plain, + rc2_key *rc2) +{ + unsigned x76, x54, x32, x10; + unsigned *xkey; + int i; + + xkey = rc2->xkey; + + x76 = ((unsigned)cipher[7] << 8) + (unsigned)cipher[6]; + x54 = ((unsigned)cipher[5] << 8) + (unsigned)cipher[4]; + x32 = ((unsigned)cipher[3] << 8) + (unsigned)cipher[2]; + x10 = ((unsigned)cipher[1] << 8) + (unsigned)cipher[0]; + + for (i = 15; i >= 0; i--) { + if (i == 4 || i == 10) { + x76 = (x76 - xkey[x54 & 63]) & 0xFFFF; + x54 = (x54 - xkey[x32 & 63]) & 0xFFFF; + x32 = (x32 - xkey[x10 & 63]) & 0xFFFF; + x10 = (x10 - xkey[x76 & 63]) & 0xFFFF; + } + + x76 = ((x76 << 11) | (x76 >> 5)); + x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF; + + x54 = ((x54 << 13) | (x54 >> 3)); + x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF; + + x32 = ((x32 << 14) | (x32 >> 2)); + x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF; + + x10 = ((x10 << 15) | (x10 >> 1)); + x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF; + } + + plain[0] = (unsigned char)x10; + plain[1] = (unsigned char)(x10 >> 8); + plain[2] = (unsigned char)x32; + plain[3] = (unsigned char)(x32 >> 8); + plain[4] = (unsigned char)x54; + plain[5] = (unsigned char)(x54 >> 8); + plain[6] = (unsigned char)x76; + plain[7] = (unsigned char)(x76 >> 8); +} diff --git a/dlls/rsaenh/rc4.c b/dlls/rsaenh/rc4.c new file mode 100644 index 00000000000..0a3e48df637 --- /dev/null +++ b/dlls/rsaenh/rc4.c @@ -0,0 +1,108 @@ +/* + * dlls/rsaenh/rc4.c + * RC4 functions + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#include "tomcrypt.h" + +int rc4_start(prng_state *prng) +{ + /* set keysize to zero */ + prng->rc4.x = 0; + + return CRYPT_OK; +} + +int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) +{ + /* trim as required */ + if (prng->rc4.x + len > 256) { + if (prng->rc4.x == 256) { + /* I can't possibly accept another byte, ok maybe a mint wafer... */ + return CRYPT_OK; + } else { + /* only accept part of it */ + len = 256 - prng->rc4.x; + } + } + + while (len--) { + prng->rc4.buf[prng->rc4.x++] = *buf++; + } + + return CRYPT_OK; +} + +int rc4_ready(prng_state *prng) +{ + unsigned char key[256], tmp, *s; + int keylen, x, y, j; + + /* extract the key */ + s = prng->rc4.buf; + memcpy(key, s, 256); + keylen = prng->rc4.x; + + /* make RC4 perm and shuffle */ + for (x = 0; x < 256; x++) { + s[x] = x; + } + + for (j = x = y = 0; x < 256; x++) { + y = (y + prng->rc4.buf[x] + key[j++]) & 255; + if (j == keylen) { + j = 0; + } + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + } + prng->rc4.x = 0; + prng->rc4.y = 0; + + return CRYPT_OK; +} + +unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng) +{ + unsigned char x, y, *s, tmp; + unsigned long n; + + n = len; + x = prng->rc4.x; + y = prng->rc4.y; + s = prng->rc4.buf; + while (len--) { + x = (x + 1) & 255; + y = (y + s[x]) & 255; + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + tmp = (s[x] + s[y]) & 255; + *buf++ ^= s[tmp]; + } + prng->rc4.x = x; + prng->rc4.y = y; + return n; +} diff --git a/dlls/rsaenh/rsa.c b/dlls/rsaenh/rsa.c new file mode 100644 index 00000000000..a69550ad3eb --- /dev/null +++ b/dlls/rsaenh/rsa.c @@ -0,0 +1,246 @@ +/* + * dlls/rsaenh/rsa.c + * RSA public key cryptographic functions + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#include "tomcrypt.h" + +static const struct { + int mpi_code, ltc_code; +} mpi_to_ltc_codes[] = { + { MP_OKAY , CRYPT_OK}, + { MP_MEM , CRYPT_MEM}, + { MP_VAL , CRYPT_INVALID_ARG}, +}; + +/* convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) */ +int mpi_to_ltc_error(int err) +{ + int x; + + for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) { + if (err == mpi_to_ltc_codes[x].mpi_code) { + return mpi_to_ltc_codes[x].ltc_code; + } + } + return CRYPT_ERROR; +} + +extern int gen_rand_impl(unsigned char *dst, unsigned int len); + +static int rand_prime_helper(unsigned char *dst, int len, void *dat) +{ + return gen_rand_impl(dst, len) ? len : 0; +} + +int rand_prime(mp_int *N, long len) +{ + int type; + + /* allow sizes between 2 and 256 bytes for a prime size */ + if (len < 16 || len > 8192) { + printf("Invalid prime size!\n"); + return CRYPT_INVALID_PRIME_SIZE; + } + + /* get type */ + if (len < 0) { + type = LTM_PRIME_BBS; + len = -len; + } else { + type = 0; + } + + /* New prime generation makes the code even more cryptoish-insane. Do you know what this means!!! + -- Gir: Yeah, oh wait, er, no. + */ + return mpi_to_ltc_error(mp_prime_random_ex(N, mp_prime_rabin_miller_trials(len), len, type, rand_prime_helper, NULL)); +} + +int rsa_make_key(int size, long e, rsa_key *key) +{ + mp_int p, q, tmp1, tmp2, tmp3; + int err; + + if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) { + return CRYPT_INVALID_KEYSIZE; + } + + if ((e < 3) || ((e & 1) == 0)) { + return CRYPT_INVALID_ARG; + } + + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) { + return mpi_to_ltc_error(err); + } + + /* make primes p and q (optimization provided by Wayne Scott) */ + if ((err = mp_set_int(&tmp3, e)) != MP_OKAY) { goto error; } /* tmp3 = e */ + + /* make prime "p" */ + do { + if ((err = rand_prime(&p, size*4)) != CRYPT_OK) { goto done; } + if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = p-1 */ + if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(p-1, e) */ + } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides p-1 */ + + /* make prime "q" */ + do { + if ((err = rand_prime(&q, size*4)) != CRYPT_OK) { goto done; } + if ((err = mp_sub_d(&q, 1, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = q-1 */ + if ((err = mp_gcd(&tmp1, &tmp3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = gcd(q-1, e) */ + } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides q-1 */ + + /* tmp1 = lcm(p-1, q-1) */ + if ((err = mp_sub_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p-1 */ + /* tmp1 = q-1 (previous do/while loop) */ + if ((err = mp_lcm(&tmp1, &tmp2, &tmp1)) != MP_OKAY) { goto error; } /* tmp1 = lcm(p-1, q-1) */ + + /* make key */ + if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, + &key->qP, &key->p, &key->q, NULL)) != MP_OKAY) { + goto error; + } + + if ((err = mp_set_int(&key->e, e)) != MP_OKAY) { goto error2; } /* key->e = e */ + if ((err = mp_invmod(&key->e, &tmp1, &key->d)) != MP_OKAY) { goto error2; } /* key->d = 1/e mod lcm(p-1,q-1) */ + if ((err = mp_mul(&p, &q, &key->N)) != MP_OKAY) { goto error2; } /* key->N = pq */ + + /* optimize for CRT now */ + /* find d mod q-1 and d mod p-1 */ + if ((err = mp_sub_d(&p, 1, &tmp1)) != MP_OKAY) { goto error2; } /* tmp1 = q-1 */ + if ((err = mp_sub_d(&q, 1, &tmp2)) != MP_OKAY) { goto error2; } /* tmp2 = p-1 */ + if ((err = mp_mod(&key->d, &tmp1, &key->dP)) != MP_OKAY) { goto error2; } /* dP = d mod p-1 */ + if ((err = mp_mod(&key->d, &tmp2, &key->dQ)) != MP_OKAY) { goto error2; } /* dQ = d mod q-1 */ + if ((err = mp_invmod(&q, &p, &key->qP)) != MP_OKAY) { goto error2; } /* qP = 1/q mod p */ + + if ((err = mp_copy(&p, &key->p)) != MP_OKAY) { goto error2; } + if ((err = mp_copy(&q, &key->q)) != MP_OKAY) { goto error2; } + + /* shrink ram required */ + if ((err = mp_shrink(&key->e)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->d)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->N)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->dQ)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->dP)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->qP)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error2; } + if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error2; } + + /* set key type (in this case it's CRT optimized) */ + key->type = PK_PRIVATE; + + /* return ok and free temps */ + err = CRYPT_OK; + goto done; +error2: + mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, + &key->qP, &key->p, &key->q, NULL); +error: + err = mpi_to_ltc_error(err); +done: + mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL); + return err; +} + +void rsa_free(rsa_key *key) +{ + mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, + &key->qP, &key->p, &key->q, NULL); +} + +/* compute an RSA modular exponentiation */ +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key) +{ + mp_int tmp, tmpa, tmpb; + unsigned long x; + int err; + + /* is the key of the right type for the operation? */ + if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* must be a private or public operation */ + if (which != PK_PRIVATE && which != PK_PUBLIC) { + return CRYPT_PK_INVALID_TYPE; + } + + /* init and copy into tmp */ + if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != MP_OKAY) { return mpi_to_ltc_error(err); } + if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; } + + /* sanity check on the input */ + if (mp_cmp(&key->N, &tmp) == MP_LT) { + err = CRYPT_PK_INVALID_SIZE; + goto done; + } + + /* are we using the private exponent and is the key optimized? */ + if (which == PK_PRIVATE) { + /* tmpa = tmp^dP mod p */ + if ((err = mpi_to_ltc_error(mp_exptmod(&tmp, &key->dP, &key->p, &tmpa))) != MP_OKAY) { goto error; } + + /* tmpb = tmp^dQ mod q */ + if ((err = mpi_to_ltc_error(mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb))) != MP_OKAY) { goto error; } + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if ((err = mp_sub(&tmpa, &tmpb, &tmp)) != MP_OKAY) { goto error; } + if ((err = mp_mulmod(&tmp, &key->qP, &key->p, &tmp)) != MP_OKAY) { goto error; } + + /* tmp = tmpb + q * tmp */ + if ((err = mp_mul(&tmp, &key->q, &tmp)) != MP_OKAY) { goto error; } + if ((err = mp_add(&tmp, &tmpb, &tmp)) != MP_OKAY) { goto error; } + } else { + /* exptmod it */ + if ((err = mp_exptmod(&tmp, &key->e, &key->N, &tmp)) != MP_OKAY) { goto error; } + } + + /* read it back */ + x = (unsigned long)mp_unsigned_bin_size(&key->N); + if (x > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + goto done; + } + *outlen = x; + + /* convert it */ + memset(out, 0, x); + if ((err = mp_to_unsigned_bin(&tmp, out+(x-mp_unsigned_bin_size(&tmp)))) != MP_OKAY) { goto error; } + + /* clean up and return */ + err = CRYPT_OK; + goto done; +error: + err = mpi_to_ltc_error(err); +done: + mp_clear_multi(&tmp, &tmpa, &tmpb, NULL); + return err; +} diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c index 5a2f0368571..6e636a12472 100644 --- a/dlls/rsaenh/rsaenh.c +++ b/dlls/rsaenh/rsaenh.c @@ -35,7 +35,7 @@ #include "wincrypt.h" #include "lmcons.h" #include "handle.h" -#include "implossl.h" +#include "implglue.h" WINE_DEFAULT_DEBUG_CHANNEL(crypt); @@ -939,8 +939,6 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer, debugstr_a(pszContainer), dwFlags, pVTable); SetLastError(ERROR_SUCCESS); - - if (!load_lib()) return FALSE; if (pszContainer ? strlen(pszContainer) : 0) { @@ -1787,18 +1785,23 @@ BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYP case AT_SIGNATURE: RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair); pKeyContainer->hSignatureKeyPair = - new_key(hProv, CALG_RSA_SIGN, dwFlags, abKeyValue, 0); + new_key(hProv, CALG_RSA_SIGN, dwFlags, NULL, 0); copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY, (unsigned int*)phKey); break; case AT_KEYEXCHANGE: RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair); - pKeyContainer->hKeyExchangeKeyPair = new_key(hProv, CALG_RSA_KEYX, dwFlags, abKeyValue, 0); + pKeyContainer->hKeyExchangeKeyPair = new_key(hProv, CALG_RSA_KEYX, dwFlags, NULL, 0); copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY, (unsigned int*)phKey); break; - + + case CALG_RSA_SIGN: + case CALG_RSA_KEYX: + *phKey = new_key(hProv, Algid, dwFlags, NULL, 0); + break; + case CALG_RC2: case CALG_RC4: case CALG_DES: diff --git a/dlls/rsaenh/tomcrypt.h b/dlls/rsaenh/tomcrypt.h new file mode 100644 index 00000000000..78cc22c93b5 --- /dev/null +++ b/dlls/rsaenh/tomcrypt.h @@ -0,0 +1,618 @@ +/* + * dlls/rsaenh/tomcrypt.h + * Function prototypes, type definitions and constant definitions + * for LibTomCrypt code. + * + * Copyright 2004 Michael Jung + * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca) + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains code from the LibTomCrypt cryptographic + * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt + * is in the public domain. The code in this file is tailored to + * special requirements. Take a look at http://libtomcrypt.org for the + * original version. + */ + +#ifndef __WINE_TOMCRYPT_H_ +#define __WINE_TOMCRYPT_H_ + +#include +#include +#include +#include +#include "basetsd.h" + +/* error codes [will be expanded in future releases] */ +enum { + CRYPT_OK=0, /* Result OK */ + CRYPT_ERROR, /* Generic Error */ + CRYPT_NOP, /* Not a failure but no operation was performed */ + + CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ + CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ + CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ + + CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ + CRYPT_INVALID_PACKET, /* Invalid input packet given */ + + CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ + CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ + + CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ + CRYPT_INVALID_HASH, /* Invalid hash specified */ + CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ + + CRYPT_MEM, /* Out of memory */ + + CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ + CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ + + CRYPT_INVALID_ARG, /* Generic invalid argument */ + CRYPT_FILE_NOTFOUND, /* File Not Found */ + + CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ + CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */ + CRYPT_PK_DUP, /* Duplicate key already in key ring */ + CRYPT_PK_NOT_FOUND, /* Key not found in keyring */ + CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ + + CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */ +}; + +#define CONST64(a,b) ((((ULONG64)(a)) << 32) | (b)) +typedef ULONG64 ulong64; + +/* this is the "32-bit at least" data type + * Re-define it to suit your platform but it must be at least 32-bits + */ +typedef ULONG32 ulong32; + +/* ---- HELPER MACROS ---- */ +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) + +static inline unsigned ROR(unsigned word, int i) +{ + __asm__("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#else + +/* rotates the hard way */ +#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ + ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#endif + +#undef MIN +#define MIN(x, y) ( ((x)<(y))?(x):(y) ) + +#define byte(x, n) (((x) >> (8 * (n))) & 255) + +typedef struct tag_rc2_key { + unsigned xkey[64]; +} rc2_key; + +typedef struct tag_des_key { + ulong32 ek[32], dk[32]; +} des_key; + +typedef struct tag_des3_key { + ulong32 ek[3][32], dk[3][32]; +} des3_key; + +int rc2_setup(const unsigned char *key, int keylen, int bits, int num_rounds, rc2_key *skey); +void rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, rc2_key *key); +void rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, rc2_key *key); + +int des_setup(const unsigned char *key, int keylen, int num_rounds, des_key *skey); +void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, des_key *key); +void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, des_key *key); + +int des3_setup(const unsigned char *key, int keylen, int num_rounds, des3_key *skey); +void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, des3_key *key); +void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, des3_key *key); + +typedef struct tag_md2_state { + unsigned char chksum[16], X[48], buf[16]; + unsigned long curlen; +} md2_state; + +int md2_init(md2_state * md); +int md2_process(md2_state * md, const unsigned char *buf, unsigned long len); +int md2_done(md2_state * md, unsigned char *hash); + +struct rc4_prng { + int x, y; + unsigned char buf[256]; +}; + +typedef union Prng_state { + struct rc4_prng rc4; +} prng_state; + +int rc4_start(prng_state *prng); +int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng); +int rc4_ready(prng_state *prng); +unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng); + +/* some default configurations. + * + * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits + * + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] + */ +typedef unsigned long mp_digit; +typedef ulong64 mp_word; +#define DIGIT_BIT 28 + +#define MP_DIGIT_BIT DIGIT_BIT +#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) +#define MP_DIGIT_MAX MP_MASK + +/* equalities */ +#define MP_LT -1 /* less than */ +#define MP_EQ 0 /* equal to */ +#define MP_GT 1 /* greater than */ + +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ + +#define MP_OKAY 0 /* ok result */ +#define MP_MEM -2 /* out of mem */ +#define MP_VAL -3 /* invalid input */ +#define MP_RANGE MP_VAL + +#define MP_YES 1 /* yes response */ +#define MP_NO 0 /* no response */ + +/* Primality generation flags */ +#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ +#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */ +#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef int mp_err; + +/* you'll have to tune these... */ +extern int KARATSUBA_MUL_CUTOFF, + KARATSUBA_SQR_CUTOFF; + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +#define MP_PREC 64 /* default digits of precision */ + +/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ +#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc, sign; + mp_digit *dp; +} mp_int; + +/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ +typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); + +#define DIGIT(m,k) ((m)->dp[(k)]) + +/* error code to char* string */ +char *mp_error_to_string(int code); + +/* ---> init and deinit bignum functions <--- */ +/* init a bignum */ +int mp_init(mp_int *a); + +/* free a bignum */ +void mp_clear(mp_int *a); + +/* init a null terminated series of arguments */ +int mp_init_multi(mp_int *mp, ...); + +/* clear a null terminated series of arguments */ +void mp_clear_multi(mp_int *mp, ...); + +/* exchange two ints */ +void mp_exch(mp_int *a, mp_int *b); + +/* shrink ram required for a bignum */ +int mp_shrink(mp_int *a); + +/* grow an int to a given size */ +int mp_grow(mp_int *a, int size); + +/* init to a given number of digits */ +int mp_init_size(mp_int *a, int size); + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) +#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) + +/* set to zero */ +void mp_zero(mp_int *a); + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b); + +/* set a 32-bit const */ +int mp_set_int(mp_int *a, unsigned long b); + +/* get a 32-bit value */ +unsigned long mp_get_int(mp_int * a); + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b); + +/* initialize and set 32-bit value */ +int mp_init_set_int (mp_int * a, unsigned long b); + +/* copy, b = a */ +int mp_copy(const mp_int *a, mp_int *b); + +/* inits and copies, a = b */ +int mp_init_copy(mp_int *a, const mp_int *b); + +/* trim unused digits */ +void mp_clamp(mp_int *a); + +/* ---> digit manipulation <--- */ + +/* right shift by "b" digits */ +void mp_rshd(mp_int *a, int b); + +/* left shift by "b" digits */ +int mp_lshd(mp_int *a, int b); + +/* c = a / 2**b */ +int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d); + +/* b = a/2 */ +int mp_div_2(mp_int *a, mp_int *b); + +/* c = a * 2**b */ +int mp_mul_2d(mp_int *a, int b, mp_int *c); + +/* b = a*2 */ +int mp_mul_2(mp_int *a, mp_int *b); + +/* c = a mod 2**d */ +int mp_mod_2d(mp_int *a, int b, mp_int *c); + +/* computes a = 2**b */ +int mp_2expt(mp_int *a, int b); + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a); + +/* I Love Earth! */ + +/* makes a pseudo-random int of a given size */ +int mp_rand(mp_int *a, int digits); + +/* ---> binary operations <--- */ +/* c = a XOR b */ +int mp_xor(mp_int *a, mp_int *b, mp_int *c); + +/* c = a OR b */ +int mp_or(mp_int *a, mp_int *b, mp_int *c); + +/* c = a AND b */ +int mp_and(mp_int *a, mp_int *b, mp_int *c); + +/* ---> Basic arithmetic <--- */ + +/* b = -a */ +int mp_neg(mp_int *a, mp_int *b); + +/* b = |a| */ +int mp_abs(mp_int *a, mp_int *b); + +/* compare a to b */ +int mp_cmp(mp_int *a, mp_int *b); + +/* compare |a| to |b| */ +int mp_cmp_mag(mp_int *a, mp_int *b); + +/* c = a + b */ +int mp_add(mp_int *a, mp_int *b, mp_int *c); + +/* c = a - b */ +int mp_sub(mp_int *a, mp_int *b, mp_int *c); + +/* c = a * b */ +int mp_mul(mp_int *a, mp_int *b, mp_int *c); + +/* b = a*a */ +int mp_sqr(mp_int *a, mp_int *b); + +/* a/b => cb + d == a */ +int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* c = a mod b, 0 <= c < b */ +int mp_mod(mp_int *a, mp_int *b, mp_int *c); + +/* ---> single digit functions <--- */ + +/* compare against a single digit */ +int mp_cmp_d(mp_int *a, mp_digit b); + +/* c = a + b */ +int mp_add_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a - b */ +int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a * b */ +int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); + +/* a/b => cb + d == a */ +int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d); + +/* a/3 => 3c + d == a */ +int mp_div_3(mp_int *a, mp_int *c, mp_digit *d); + +/* c = a**b */ +int mp_expt_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a mod b, 0 <= c < b */ +int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); + +/* ---> number theory <--- */ + +/* d = a + b (mod c) */ +int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* d = a - b (mod c) */ +int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* d = a * b (mod c) */ +int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* c = a * a (mod b) */ +int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c); + +/* c = 1/a (mod b) */ +int mp_invmod(mp_int *a, mp_int *b, mp_int *c); + +/* c = (a, b) */ +int mp_gcd(mp_int *a, mp_int *b, mp_int *c); + +/* produces value such that U1*a + U2*b = U3 */ +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); + +/* c = [a, b] or (a*b)/(a, b) */ +int mp_lcm(mp_int *a, mp_int *b, mp_int *c); + +/* finds one of the b'th root of a, such that |c|**b <= |a| + * + * returns error if a < 0 and b is even + */ +int mp_n_root(mp_int *a, mp_digit b, mp_int *c); + +/* special sqrt algo */ +int mp_sqrt(mp_int *arg, mp_int *ret); + +/* is number a square? */ +int mp_is_square(mp_int *arg, int *ret); + +/* computes the jacobi c = (a | n) (or Legendre if b is prime) */ +int mp_jacobi(mp_int *a, mp_int *n, int *c); + +/* used to setup the Barrett reduction for a given modulus b */ +int mp_reduce_setup(mp_int *a, mp_int *b); + +/* Barrett Reduction, computes a (mod b) with a precomputed value c + * + * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely + * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code]. + */ +int mp_reduce(mp_int *a, mp_int *b, mp_int *c); + +/* setups the montgomery reduction */ +int mp_montgomery_setup(mp_int *a, mp_digit *mp); + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); + +/* computes x/R == x (mod N) via Montgomery Reduction */ +int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); + +/* returns 1 if a is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a); + +/* sets the value of "d" required for mp_dr_reduce */ +void mp_dr_setup(mp_int *a, mp_digit *d); + +/* reduces a modulo b using the Diminished Radix method */ +int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp); + +/* returns true if a can be reduced with mp_reduce_2k */ +int mp_reduce_is_2k(mp_int *a); + +/* determines k value for 2k reduction */ +int mp_reduce_2k_setup(mp_int *a, mp_digit *d); + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); + +/* d = a**b (mod c) */ +int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* ---> Primes <--- */ + +/* number of primes */ +#define PRIME_SIZE 256 + +/* table of first PRIME_SIZE primes */ +extern const mp_digit __prime_tab[]; + +/* result=1 if a is divisible by one of the first PRIME_SIZE primes */ +int mp_prime_is_divisible(mp_int *a, int *result); + +/* performs one Fermat test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_fermat(mp_int *a, mp_int *b, int *result); + +/* performs one Miller-Rabin test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); + +/* This gives [for a given bit size] the number of trials required + * such that Miller-Rabin gives a prob of failure lower than 2^-96 + */ +int mp_prime_rabin_miller_trials(int size); + +/* performs t rounds of Miller-Rabin on "a" using the first + * t prime bases. Also performs an initial sieve of trial + * division. Determines if "a" is prime with probability + * of error no more than (1/4)**t. + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime(mp_int *a, int t, int *result); + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = 1 means the prime must be congruent to 3 mod 4 + */ +int mp_prime_next_prime(mp_int *a, int t, int bbs_style); + +/* makes a truly random prime of a given size (bytes), + * call with bbs = 1 if you want it to be congruent to 3 mod 4 + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + * The prime generated will be larger than 2^(8*size). + */ +#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); + +/* ---> radix conversion <--- */ +int mp_count_bits(mp_int *a); + +int mp_unsigned_bin_size(mp_int *a); +int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c); +int mp_to_unsigned_bin(mp_int *a, unsigned char *b); + +int mp_signed_bin_size(mp_int *a); +int mp_read_signed_bin(mp_int *a, unsigned char *b, int c); +int mp_to_signed_bin(mp_int *a, unsigned char *b); + +int mp_read_radix(mp_int *a, char *str, int radix); +int mp_toradix(mp_int *a, char *str, int radix); +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen); +int mp_radix_size(mp_int *a, int radix, int *size); + +int mp_fread(mp_int *a, int radix, FILE *stream); +int mp_fwrite(mp_int *a, int radix, FILE *stream); + +#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) +#define mp_raw_size(mp) mp_signed_bin_size(mp) +#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) + +#define mp_tobinary(M, S) mp_toradix((M), (S), 2) +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) +#define mp_tohex(M, S) mp_toradix((M), (S), 16) + +/* lowlevel functions, do not call! */ +int s_mp_add(mp_int *a, mp_int *b, mp_int *c); +int s_mp_sub(mp_int *a, mp_int *b, mp_int *c); +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) +int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int fast_s_mp_sqr(mp_int *a, mp_int *b); +int s_mp_sqr(mp_int *a, mp_int *b); +int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c); +int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c); +int mp_karatsuba_sqr(mp_int *a, mp_int *b); +int mp_toom_sqr(mp_int *a, mp_int *b); +int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c); +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); +int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); +int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode); +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); +void bn_reverse(unsigned char *s, int len); + +extern const char *mp_s_rmap; + +#define PK_PRIVATE 0 /* PK private keys */ +#define PK_PUBLIC 1 /* PK public keys */ + +/* Min and Max RSA key sizes (in bits) */ +#define MIN_RSA_SIZE 384 +#define MAX_RSA_SIZE 16384 + +typedef struct Rsa_key { + int type; + mp_int e, d, N, p, q, qP, dP, dQ; +} rsa_key; + +int rsa_make_key(int size, long e, rsa_key *key); + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + rsa_key *key); + +void rsa_free(rsa_key *key); + +#endif /* __WINE_TOMCRYPT_H_ */ -- 2.11.4.GIT