diff options
Diffstat (limited to 'src')
55 files changed, 2119 insertions, 490 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index af7a43a2..8f393089 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,7 +69,7 @@ m_cheat.c m_cheat.h \ m_config.c m_config.h \ m_controls.c m_controls.h \ m_fixed.c m_fixed.h \ -md5.c md5.h \ +sha1.c sha1.h \ memio.c memio.h \ tables.c tables.h \ v_video.c v_video.h \ @@ -95,6 +95,7 @@ deh_text.c # source files needed for FEATURE_MULTIPLAYER FEATURE_MULTIPLAYER_SOURCE_FILES= \ +aes_prng.c aes_prng.h \ net_client.c net_client.h \ net_common.c net_common.h \ net_dedicated.c net_dedicated.h \ @@ -210,13 +211,13 @@ appdir = $(prefix)/share/applications app_DATA = @PROGRAM_PREFIX@doom.desktop @PROGRAM_PREFIX@doom.desktop : doom.desktop - cp $< $@ + cp doom.desktop $@ screensaverdir = $(prefix)/share/applications/screensavers screensaver_DATA = @PROGRAM_PREFIX@doom-screensaver.desktop @PROGRAM_PREFIX@doom-screensaver.desktop: doom-screensaver.desktop - cp $< $@ + cp doom-screensaver.desktop $@ .rc.o: $(WINDRES) $< -o $@ diff --git a/src/aes_prng.c b/src/aes_prng.c new file mode 100644 index 00000000..4d9963f0 --- /dev/null +++ b/src/aes_prng.c @@ -0,0 +1,1048 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2012 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +//----------------------------------------------------------------------------- +// +// This implements a cryptographically secure pseudorandom number +// generator for implementing secure demos. The approach taken is to +// use the AES (Rijndael) stream cipher in "counter" mode, encrypting +// an incrementing counter. The cipher key acts as the random seed. +// Cryptanalysis of AES used in this way has shown it to be an +// effective PRNG (see: Empirical Evidence concerning AES, Hellekalek +// & Wegenkittl, 2003). +// +// The AES implementation is from GnuPG. Original copyright notice is +// below. +// +//----------------------------------------------------------------------------- + +/* Rijndael (AES) for GnuPG + * Copyright (C) 2000, 2001, 2008 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + ******************************************************************* + * The code here is based on the optimized implementation taken from + * http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ on Oct 2, 2000, + * which carries this notice: + *------------------------------------------ + * rijndael-alg-fst.c v2.3 April '2000 + * + * Optimised ANSI C code + * + * authors: v1.0: Antoon Bosselaers + * v2.0: Vincent Rijmen + * v2.3: Paulo Barreto + * + * This code is placed in the public domain. + *------------------------------------------ + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> /* for memcmp() */ + +#include "aes_prng.h" +#include "doomtype.h" +#include "i_system.h" + +#define MAXKC (256/32) +#define MAXROUNDS 14 + + +typedef struct +{ + int ROUNDS; /* key-length-dependent number of rounds */ + uint32_t keySched[MAXROUNDS+1][4]; /* key schedule */ +} RIJNDAEL_context; + +static const byte S[256] = +{ + 99, 124, 119, 123, 242, 107, 111, 197, + 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, + 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, + 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, + 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, + 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, + 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, + 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, + 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, + 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, + 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, + 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, + 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, + 155, 30, 135, 233, 206, 85, 40, 223, + 140, 161, 137, 13, 191, 230, 66, 104, + 65, 153, 45, 15, 176, 84, 187, 22 +}; + + +static const byte T1[256][4] = +{ + { 0xc6,0x63,0x63,0xa5 }, { 0xf8,0x7c,0x7c,0x84 }, + { 0xee,0x77,0x77,0x99 }, { 0xf6,0x7b,0x7b,0x8d }, + { 0xff,0xf2,0xf2,0x0d }, { 0xd6,0x6b,0x6b,0xbd }, + { 0xde,0x6f,0x6f,0xb1 }, { 0x91,0xc5,0xc5,0x54 }, + { 0x60,0x30,0x30,0x50 }, { 0x02,0x01,0x01,0x03 }, + { 0xce,0x67,0x67,0xa9 }, { 0x56,0x2b,0x2b,0x7d }, + { 0xe7,0xfe,0xfe,0x19 }, { 0xb5,0xd7,0xd7,0x62 }, + { 0x4d,0xab,0xab,0xe6 }, { 0xec,0x76,0x76,0x9a }, + { 0x8f,0xca,0xca,0x45 }, { 0x1f,0x82,0x82,0x9d }, + { 0x89,0xc9,0xc9,0x40 }, { 0xfa,0x7d,0x7d,0x87 }, + { 0xef,0xfa,0xfa,0x15 }, { 0xb2,0x59,0x59,0xeb }, + { 0x8e,0x47,0x47,0xc9 }, { 0xfb,0xf0,0xf0,0x0b }, + { 0x41,0xad,0xad,0xec }, { 0xb3,0xd4,0xd4,0x67 }, + { 0x5f,0xa2,0xa2,0xfd }, { 0x45,0xaf,0xaf,0xea }, + { 0x23,0x9c,0x9c,0xbf }, { 0x53,0xa4,0xa4,0xf7 }, + { 0xe4,0x72,0x72,0x96 }, { 0x9b,0xc0,0xc0,0x5b }, + { 0x75,0xb7,0xb7,0xc2 }, { 0xe1,0xfd,0xfd,0x1c }, + { 0x3d,0x93,0x93,0xae }, { 0x4c,0x26,0x26,0x6a }, + { 0x6c,0x36,0x36,0x5a }, { 0x7e,0x3f,0x3f,0x41 }, + { 0xf5,0xf7,0xf7,0x02 }, { 0x83,0xcc,0xcc,0x4f }, + { 0x68,0x34,0x34,0x5c }, { 0x51,0xa5,0xa5,0xf4 }, + { 0xd1,0xe5,0xe5,0x34 }, { 0xf9,0xf1,0xf1,0x08 }, + { 0xe2,0x71,0x71,0x93 }, { 0xab,0xd8,0xd8,0x73 }, + { 0x62,0x31,0x31,0x53 }, { 0x2a,0x15,0x15,0x3f }, + { 0x08,0x04,0x04,0x0c }, { 0x95,0xc7,0xc7,0x52 }, + { 0x46,0x23,0x23,0x65 }, { 0x9d,0xc3,0xc3,0x5e }, + { 0x30,0x18,0x18,0x28 }, { 0x37,0x96,0x96,0xa1 }, + { 0x0a,0x05,0x05,0x0f }, { 0x2f,0x9a,0x9a,0xb5 }, + { 0x0e,0x07,0x07,0x09 }, { 0x24,0x12,0x12,0x36 }, + { 0x1b,0x80,0x80,0x9b }, { 0xdf,0xe2,0xe2,0x3d }, + { 0xcd,0xeb,0xeb,0x26 }, { 0x4e,0x27,0x27,0x69 }, + { 0x7f,0xb2,0xb2,0xcd }, { 0xea,0x75,0x75,0x9f }, + { 0x12,0x09,0x09,0x1b }, { 0x1d,0x83,0x83,0x9e }, + { 0x58,0x2c,0x2c,0x74 }, { 0x34,0x1a,0x1a,0x2e }, + { 0x36,0x1b,0x1b,0x2d }, { 0xdc,0x6e,0x6e,0xb2 }, + { 0xb4,0x5a,0x5a,0xee }, { 0x5b,0xa0,0xa0,0xfb }, + { 0xa4,0x52,0x52,0xf6 }, { 0x76,0x3b,0x3b,0x4d }, + { 0xb7,0xd6,0xd6,0x61 }, { 0x7d,0xb3,0xb3,0xce }, + { 0x52,0x29,0x29,0x7b }, { 0xdd,0xe3,0xe3,0x3e }, + { 0x5e,0x2f,0x2f,0x71 }, { 0x13,0x84,0x84,0x97 }, + { 0xa6,0x53,0x53,0xf5 }, { 0xb9,0xd1,0xd1,0x68 }, + { 0x00,0x00,0x00,0x00 }, { 0xc1,0xed,0xed,0x2c }, + { 0x40,0x20,0x20,0x60 }, { 0xe3,0xfc,0xfc,0x1f }, + { 0x79,0xb1,0xb1,0xc8 }, { 0xb6,0x5b,0x5b,0xed }, + { 0xd4,0x6a,0x6a,0xbe }, { 0x8d,0xcb,0xcb,0x46 }, + { 0x67,0xbe,0xbe,0xd9 }, { 0x72,0x39,0x39,0x4b }, + { 0x94,0x4a,0x4a,0xde }, { 0x98,0x4c,0x4c,0xd4 }, + { 0xb0,0x58,0x58,0xe8 }, { 0x85,0xcf,0xcf,0x4a }, + { 0xbb,0xd0,0xd0,0x6b }, { 0xc5,0xef,0xef,0x2a }, + { 0x4f,0xaa,0xaa,0xe5 }, { 0xed,0xfb,0xfb,0x16 }, + { 0x86,0x43,0x43,0xc5 }, { 0x9a,0x4d,0x4d,0xd7 }, + { 0x66,0x33,0x33,0x55 }, { 0x11,0x85,0x85,0x94 }, + { 0x8a,0x45,0x45,0xcf }, { 0xe9,0xf9,0xf9,0x10 }, + { 0x04,0x02,0x02,0x06 }, { 0xfe,0x7f,0x7f,0x81 }, + { 0xa0,0x50,0x50,0xf0 }, { 0x78,0x3c,0x3c,0x44 }, + { 0x25,0x9f,0x9f,0xba }, { 0x4b,0xa8,0xa8,0xe3 }, + { 0xa2,0x51,0x51,0xf3 }, { 0x5d,0xa3,0xa3,0xfe }, + { 0x80,0x40,0x40,0xc0 }, { 0x05,0x8f,0x8f,0x8a }, + { 0x3f,0x92,0x92,0xad }, { 0x21,0x9d,0x9d,0xbc }, + { 0x70,0x38,0x38,0x48 }, { 0xf1,0xf5,0xf5,0x04 }, + { 0x63,0xbc,0xbc,0xdf }, { 0x77,0xb6,0xb6,0xc1 }, + { 0xaf,0xda,0xda,0x75 }, { 0x42,0x21,0x21,0x63 }, + { 0x20,0x10,0x10,0x30 }, { 0xe5,0xff,0xff,0x1a }, + { 0xfd,0xf3,0xf3,0x0e }, { 0xbf,0xd2,0xd2,0x6d }, + { 0x81,0xcd,0xcd,0x4c }, { 0x18,0x0c,0x0c,0x14 }, + { 0x26,0x13,0x13,0x35 }, { 0xc3,0xec,0xec,0x2f }, + { 0xbe,0x5f,0x5f,0xe1 }, { 0x35,0x97,0x97,0xa2 }, + { 0x88,0x44,0x44,0xcc }, { 0x2e,0x17,0x17,0x39 }, + { 0x93,0xc4,0xc4,0x57 }, { 0x55,0xa7,0xa7,0xf2 }, + { 0xfc,0x7e,0x7e,0x82 }, { 0x7a,0x3d,0x3d,0x47 }, + { 0xc8,0x64,0x64,0xac }, { 0xba,0x5d,0x5d,0xe7 }, + { 0x32,0x19,0x19,0x2b }, { 0xe6,0x73,0x73,0x95 }, + { 0xc0,0x60,0x60,0xa0 }, { 0x19,0x81,0x81,0x98 }, + { 0x9e,0x4f,0x4f,0xd1 }, { 0xa3,0xdc,0xdc,0x7f }, + { 0x44,0x22,0x22,0x66 }, { 0x54,0x2a,0x2a,0x7e }, + { 0x3b,0x90,0x90,0xab }, { 0x0b,0x88,0x88,0x83 }, + { 0x8c,0x46,0x46,0xca }, { 0xc7,0xee,0xee,0x29 }, + { 0x6b,0xb8,0xb8,0xd3 }, { 0x28,0x14,0x14,0x3c }, + { 0xa7,0xde,0xde,0x79 }, { 0xbc,0x5e,0x5e,0xe2 }, + { 0x16,0x0b,0x0b,0x1d }, { 0xad,0xdb,0xdb,0x76 }, + { 0xdb,0xe0,0xe0,0x3b }, { 0x64,0x32,0x32,0x56 }, + { 0x74,0x3a,0x3a,0x4e }, { 0x14,0x0a,0x0a,0x1e }, + { 0x92,0x49,0x49,0xdb }, { 0x0c,0x06,0x06,0x0a }, + { 0x48,0x24,0x24,0x6c }, { 0xb8,0x5c,0x5c,0xe4 }, + { 0x9f,0xc2,0xc2,0x5d }, { 0xbd,0xd3,0xd3,0x6e }, + { 0x43,0xac,0xac,0xef }, { 0xc4,0x62,0x62,0xa6 }, + { 0x39,0x91,0x91,0xa8 }, { 0x31,0x95,0x95,0xa4 }, + { 0xd3,0xe4,0xe4,0x37 }, { 0xf2,0x79,0x79,0x8b }, + { 0xd5,0xe7,0xe7,0x32 }, { 0x8b,0xc8,0xc8,0x43 }, + { 0x6e,0x37,0x37,0x59 }, { 0xda,0x6d,0x6d,0xb7 }, + { 0x01,0x8d,0x8d,0x8c }, { 0xb1,0xd5,0xd5,0x64 }, + { 0x9c,0x4e,0x4e,0xd2 }, { 0x49,0xa9,0xa9,0xe0 }, + { 0xd8,0x6c,0x6c,0xb4 }, { 0xac,0x56,0x56,0xfa }, + { 0xf3,0xf4,0xf4,0x07 }, { 0xcf,0xea,0xea,0x25 }, + { 0xca,0x65,0x65,0xaf }, { 0xf4,0x7a,0x7a,0x8e }, + { 0x47,0xae,0xae,0xe9 }, { 0x10,0x08,0x08,0x18 }, + { 0x6f,0xba,0xba,0xd5 }, { 0xf0,0x78,0x78,0x88 }, + { 0x4a,0x25,0x25,0x6f }, { 0x5c,0x2e,0x2e,0x72 }, + { 0x38,0x1c,0x1c,0x24 }, { 0x57,0xa6,0xa6,0xf1 }, + { 0x73,0xb4,0xb4,0xc7 }, { 0x97,0xc6,0xc6,0x51 }, + { 0xcb,0xe8,0xe8,0x23 }, { 0xa1,0xdd,0xdd,0x7c }, + { 0xe8,0x74,0x74,0x9c }, { 0x3e,0x1f,0x1f,0x21 }, + { 0x96,0x4b,0x4b,0xdd }, { 0x61,0xbd,0xbd,0xdc }, + { 0x0d,0x8b,0x8b,0x86 }, { 0x0f,0x8a,0x8a,0x85 }, + { 0xe0,0x70,0x70,0x90 }, { 0x7c,0x3e,0x3e,0x42 }, + { 0x71,0xb5,0xb5,0xc4 }, { 0xcc,0x66,0x66,0xaa }, + { 0x90,0x48,0x48,0xd8 }, { 0x06,0x03,0x03,0x05 }, + { 0xf7,0xf6,0xf6,0x01 }, { 0x1c,0x0e,0x0e,0x12 }, + { 0xc2,0x61,0x61,0xa3 }, { 0x6a,0x35,0x35,0x5f }, + { 0xae,0x57,0x57,0xf9 }, { 0x69,0xb9,0xb9,0xd0 }, + { 0x17,0x86,0x86,0x91 }, { 0x99,0xc1,0xc1,0x58 }, + { 0x3a,0x1d,0x1d,0x27 }, { 0x27,0x9e,0x9e,0xb9 }, + { 0xd9,0xe1,0xe1,0x38 }, { 0xeb,0xf8,0xf8,0x13 }, + { 0x2b,0x98,0x98,0xb3 }, { 0x22,0x11,0x11,0x33 }, + { 0xd2,0x69,0x69,0xbb }, { 0xa9,0xd9,0xd9,0x70 }, + { 0x07,0x8e,0x8e,0x89 }, { 0x33,0x94,0x94,0xa7 }, + { 0x2d,0x9b,0x9b,0xb6 }, { 0x3c,0x1e,0x1e,0x22 }, + { 0x15,0x87,0x87,0x92 }, { 0xc9,0xe9,0xe9,0x20 }, + { 0x87,0xce,0xce,0x49 }, { 0xaa,0x55,0x55,0xff }, + { 0x50,0x28,0x28,0x78 }, { 0xa5,0xdf,0xdf,0x7a }, + { 0x03,0x8c,0x8c,0x8f }, { 0x59,0xa1,0xa1,0xf8 }, + { 0x09,0x89,0x89,0x80 }, { 0x1a,0x0d,0x0d,0x17 }, + { 0x65,0xbf,0xbf,0xda }, { 0xd7,0xe6,0xe6,0x31 }, + { 0x84,0x42,0x42,0xc6 }, { 0xd0,0x68,0x68,0xb8 }, + { 0x82,0x41,0x41,0xc3 }, { 0x29,0x99,0x99,0xb0 }, + { 0x5a,0x2d,0x2d,0x77 }, { 0x1e,0x0f,0x0f,0x11 }, + { 0x7b,0xb0,0xb0,0xcb }, { 0xa8,0x54,0x54,0xfc }, + { 0x6d,0xbb,0xbb,0xd6 }, { 0x2c,0x16,0x16,0x3a } +}; + +static const byte T2[256][4] = +{ + { 0xa5,0xc6,0x63,0x63 }, { 0x84,0xf8,0x7c,0x7c }, + { 0x99,0xee,0x77,0x77 }, { 0x8d,0xf6,0x7b,0x7b }, + { 0x0d,0xff,0xf2,0xf2 }, { 0xbd,0xd6,0x6b,0x6b }, + { 0xb1,0xde,0x6f,0x6f }, { 0x54,0x91,0xc5,0xc5 }, + { 0x50,0x60,0x30,0x30 }, { 0x03,0x02,0x01,0x01 }, + { 0xa9,0xce,0x67,0x67 }, { 0x7d,0x56,0x2b,0x2b }, + { 0x19,0xe7,0xfe,0xfe }, { 0x62,0xb5,0xd7,0xd7 }, + { 0xe6,0x4d,0xab,0xab }, { 0x9a,0xec,0x76,0x76 }, + { 0x45,0x8f,0xca,0xca }, { 0x9d,0x1f,0x82,0x82 }, + { 0x40,0x89,0xc9,0xc9 }, { 0x87,0xfa,0x7d,0x7d }, + { 0x15,0xef,0xfa,0xfa }, { 0xeb,0xb2,0x59,0x59 }, + { 0xc9,0x8e,0x47,0x47 }, { 0x0b,0xfb,0xf0,0xf0 }, + { 0xec,0x41,0xad,0xad }, { 0x67,0xb3,0xd4,0xd4 }, + { 0xfd,0x5f,0xa2,0xa2 }, { 0xea,0x45,0xaf,0xaf }, + { 0xbf,0x23,0x9c,0x9c }, { 0xf7,0x53,0xa4,0xa4 }, + { 0x96,0xe4,0x72,0x72 }, { 0x5b,0x9b,0xc0,0xc0 }, + { 0xc2,0x75,0xb7,0xb7 }, { 0x1c,0xe1,0xfd,0xfd }, + { 0xae,0x3d,0x93,0x93 }, { 0x6a,0x4c,0x26,0x26 }, + { 0x5a,0x6c,0x36,0x36 }, { 0x41,0x7e,0x3f,0x3f }, + { 0x02,0xf5,0xf7,0xf7 }, { 0x4f,0x83,0xcc,0xcc }, + { 0x5c,0x68,0x34,0x34 }, { 0xf4,0x51,0xa5,0xa5 }, + { 0x34,0xd1,0xe5,0xe5 }, { 0x08,0xf9,0xf1,0xf1 }, + { 0x93,0xe2,0x71,0x71 }, { 0x73,0xab,0xd8,0xd8 }, + { 0x53,0x62,0x31,0x31 }, { 0x3f,0x2a,0x15,0x15 }, + { 0x0c,0x08,0x04,0x04 }, { 0x52,0x95,0xc7,0xc7 }, + { 0x65,0x46,0x23,0x23 }, { 0x5e,0x9d,0xc3,0xc3 }, + { 0x28,0x30,0x18,0x18 }, { 0xa1,0x37,0x96,0x96 }, + { 0x0f,0x0a,0x05,0x05 }, { 0xb5,0x2f,0x9a,0x9a }, + { 0x09,0x0e,0x07,0x07 }, { 0x36,0x24,0x12,0x12 }, + { 0x9b,0x1b,0x80,0x80 }, { 0x3d,0xdf,0xe2,0xe2 }, + { 0x26,0xcd,0xeb,0xeb }, { 0x69,0x4e,0x27,0x27 }, + { 0xcd,0x7f,0xb2,0xb2 }, { 0x9f,0xea,0x75,0x75 }, + { 0x1b,0x12,0x09,0x09 }, { 0x9e,0x1d,0x83,0x83 }, + { 0x74,0x58,0x2c,0x2c }, { 0x2e,0x34,0x1a,0x1a }, + { 0x2d,0x36,0x1b,0x1b }, { 0xb2,0xdc,0x6e,0x6e }, + { 0xee,0xb4,0x5a,0x5a }, { 0xfb,0x5b,0xa0,0xa0 }, + { 0xf6,0xa4,0x52,0x52 }, { 0x4d,0x76,0x3b,0x3b }, + { 0x61,0xb7,0xd6,0xd6 }, { 0xce,0x7d,0xb3,0xb3 }, + { 0x7b,0x52,0x29,0x29 }, { 0x3e,0xdd,0xe3,0xe3 }, + { 0x71,0x5e,0x2f,0x2f }, { 0x97,0x13,0x84,0x84 }, + { 0xf5,0xa6,0x53,0x53 }, { 0x68,0xb9,0xd1,0xd1 }, + { 0x00,0x00,0x00,0x00 }, { 0x2c,0xc1,0xed,0xed }, + { 0x60,0x40,0x20,0x20 }, { 0x1f,0xe3,0xfc,0xfc }, + { 0xc8,0x79,0xb1,0xb1 }, { 0xed,0xb6,0x5b,0x5b }, + { 0xbe,0xd4,0x6a,0x6a }, { 0x46,0x8d,0xcb,0xcb }, + { 0xd9,0x67,0xbe,0xbe }, { 0x4b,0x72,0x39,0x39 }, + { 0xde,0x94,0x4a,0x4a }, { 0xd4,0x98,0x4c,0x4c }, + { 0xe8,0xb0,0x58,0x58 }, { 0x4a,0x85,0xcf,0xcf }, + { 0x6b,0xbb,0xd0,0xd0 }, { 0x2a,0xc5,0xef,0xef }, + { 0xe5,0x4f,0xaa,0xaa }, { 0x16,0xed,0xfb,0xfb }, + { 0xc5,0x86,0x43,0x43 }, { 0xd7,0x9a,0x4d,0x4d }, + { 0x55,0x66,0x33,0x33 }, { 0x94,0x11,0x85,0x85 }, + { 0xcf,0x8a,0x45,0x45 }, { 0x10,0xe9,0xf9,0xf9 }, + { 0x06,0x04,0x02,0x02 }, { 0x81,0xfe,0x7f,0x7f }, + { 0xf0,0xa0,0x50,0x50 }, { 0x44,0x78,0x3c,0x3c }, + { 0xba,0x25,0x9f,0x9f }, { 0xe3,0x4b,0xa8,0xa8 }, + { 0xf3,0xa2,0x51,0x51 }, { 0xfe,0x5d,0xa3,0xa3 }, + { 0xc0,0x80,0x40,0x40 }, { 0x8a,0x05,0x8f,0x8f }, + { 0xad,0x3f,0x92,0x92 }, { 0xbc,0x21,0x9d,0x9d }, + { 0x48,0x70,0x38,0x38 }, { 0x04,0xf1,0xf5,0xf5 }, + { 0xdf,0x63,0xbc,0xbc }, { 0xc1,0x77,0xb6,0xb6 }, + { 0x75,0xaf,0xda,0xda }, { 0x63,0x42,0x21,0x21 }, + { 0x30,0x20,0x10,0x10 }, { 0x1a,0xe5,0xff,0xff }, + { 0x0e,0xfd,0xf3,0xf3 }, { 0x6d,0xbf,0xd2,0xd2 }, + { 0x4c,0x81,0xcd,0xcd }, { 0x14,0x18,0x0c,0x0c }, + { 0x35,0x26,0x13,0x13 }, { 0x2f,0xc3,0xec,0xec }, + { 0xe1,0xbe,0x5f,0x5f }, { 0xa2,0x35,0x97,0x97 }, + { 0xcc,0x88,0x44,0x44 }, { 0x39,0x2e,0x17,0x17 }, + { 0x57,0x93,0xc4,0xc4 }, { 0xf2,0x55,0xa7,0xa7 }, + { 0x82,0xfc,0x7e,0x7e }, { 0x47,0x7a,0x3d,0x3d }, + { 0xac,0xc8,0x64,0x64 }, { 0xe7,0xba,0x5d,0x5d }, + { 0x2b,0x32,0x19,0x19 }, { 0x95,0xe6,0x73,0x73 }, + { 0xa0,0xc0,0x60,0x60 }, { 0x98,0x19,0x81,0x81 }, + { 0xd1,0x9e,0x4f,0x4f }, { 0x7f,0xa3,0xdc,0xdc }, + { 0x66,0x44,0x22,0x22 }, { 0x7e,0x54,0x2a,0x2a }, + { 0xab,0x3b,0x90,0x90 }, { 0x83,0x0b,0x88,0x88 }, + { 0xca,0x8c,0x46,0x46 }, { 0x29,0xc7,0xee,0xee }, + { 0xd3,0x6b,0xb8,0xb8 }, { 0x3c,0x28,0x14,0x14 }, + { 0x79,0xa7,0xde,0xde }, { 0xe2,0xbc,0x5e,0x5e }, + { 0x1d,0x16,0x0b,0x0b }, { 0x76,0xad,0xdb,0xdb }, + { 0x3b,0xdb,0xe0,0xe0 }, { 0x56,0x64,0x32,0x32 }, + { 0x4e,0x74,0x3a,0x3a }, { 0x1e,0x14,0x0a,0x0a }, + { 0xdb,0x92,0x49,0x49 }, { 0x0a,0x0c,0x06,0x06 }, + { 0x6c,0x48,0x24,0x24 }, { 0xe4,0xb8,0x5c,0x5c }, + { 0x5d,0x9f,0xc2,0xc2 }, { 0x6e,0xbd,0xd3,0xd3 }, + { 0xef,0x43,0xac,0xac }, { 0xa6,0xc4,0x62,0x62 }, + { 0xa8,0x39,0x91,0x91 }, { 0xa4,0x31,0x95,0x95 }, + { 0x37,0xd3,0xe4,0xe4 }, { 0x8b,0xf2,0x79,0x79 }, + { 0x32,0xd5,0xe7,0xe7 }, { 0x43,0x8b,0xc8,0xc8 }, + { 0x59,0x6e,0x37,0x37 }, { 0xb7,0xda,0x6d,0x6d }, + { 0x8c,0x01,0x8d,0x8d }, { 0x64,0xb1,0xd5,0xd5 }, + { 0xd2,0x9c,0x4e,0x4e }, { 0xe0,0x49,0xa9,0xa9 }, + { 0xb4,0xd8,0x6c,0x6c }, { 0xfa,0xac,0x56,0x56 }, + { 0x07,0xf3,0xf4,0xf4 }, { 0x25,0xcf,0xea,0xea }, + { 0xaf,0xca,0x65,0x65 }, { 0x8e,0xf4,0x7a,0x7a }, + { 0xe9,0x47,0xae,0xae }, { 0x18,0x10,0x08,0x08 }, + { 0xd5,0x6f,0xba,0xba }, { 0x88,0xf0,0x78,0x78 }, + { 0x6f,0x4a,0x25,0x25 }, { 0x72,0x5c,0x2e,0x2e }, + { 0x24,0x38,0x1c,0x1c }, { 0xf1,0x57,0xa6,0xa6 }, + { 0xc7,0x73,0xb4,0xb4 }, { 0x51,0x97,0xc6,0xc6 }, + { 0x23,0xcb,0xe8,0xe8 }, { 0x7c,0xa1,0xdd,0xdd }, + { 0x9c,0xe8,0x74,0x74 }, { 0x21,0x3e,0x1f,0x1f }, + { 0xdd,0x96,0x4b,0x4b }, { 0xdc,0x61,0xbd,0xbd }, + { 0x86,0x0d,0x8b,0x8b }, { 0x85,0x0f,0x8a,0x8a }, + { 0x90,0xe0,0x70,0x70 }, { 0x42,0x7c,0x3e,0x3e }, + { 0xc4,0x71,0xb5,0xb5 }, { 0xaa,0xcc,0x66,0x66 }, + { 0xd8,0x90,0x48,0x48 }, { 0x05,0x06,0x03,0x03 }, + { 0x01,0xf7,0xf6,0xf6 }, { 0x12,0x1c,0x0e,0x0e }, + { 0xa3,0xc2,0x61,0x61 }, { 0x5f,0x6a,0x35,0x35 }, + { 0xf9,0xae,0x57,0x57 }, { 0xd0,0x69,0xb9,0xb9 }, + { 0x91,0x17,0x86,0x86 }, { 0x58,0x99,0xc1,0xc1 }, + { 0x27,0x3a,0x1d,0x1d }, { 0xb9,0x27,0x9e,0x9e }, + { 0x38,0xd9,0xe1,0xe1 }, { 0x13,0xeb,0xf8,0xf8 }, + { 0xb3,0x2b,0x98,0x98 }, { 0x33,0x22,0x11,0x11 }, + { 0xbb,0xd2,0x69,0x69 }, { 0x70,0xa9,0xd9,0xd9 }, + { 0x89,0x07,0x8e,0x8e }, { 0xa7,0x33,0x94,0x94 }, + { 0xb6,0x2d,0x9b,0x9b }, { 0x22,0x3c,0x1e,0x1e }, + { 0x92,0x15,0x87,0x87 }, { 0x20,0xc9,0xe9,0xe9 }, + { 0x49,0x87,0xce,0xce }, { 0xff,0xaa,0x55,0x55 }, + { 0x78,0x50,0x28,0x28 }, { 0x7a,0xa5,0xdf,0xdf }, + { 0x8f,0x03,0x8c,0x8c }, { 0xf8,0x59,0xa1,0xa1 }, + { 0x80,0x09,0x89,0x89 }, { 0x17,0x1a,0x0d,0x0d }, + { 0xda,0x65,0xbf,0xbf }, { 0x31,0xd7,0xe6,0xe6 }, + { 0xc6,0x84,0x42,0x42 }, { 0xb8,0xd0,0x68,0x68 }, + { 0xc3,0x82,0x41,0x41 }, { 0xb0,0x29,0x99,0x99 }, + { 0x77,0x5a,0x2d,0x2d }, { 0x11,0x1e,0x0f,0x0f }, + { 0xcb,0x7b,0xb0,0xb0 }, { 0xfc,0xa8,0x54,0x54 }, + { 0xd6,0x6d,0xbb,0xbb }, { 0x3a,0x2c,0x16,0x16 } +}; + +static const byte T3[256][4] = +{ + { 0x63,0xa5,0xc6,0x63 }, { 0x7c,0x84,0xf8,0x7c }, + { 0x77,0x99,0xee,0x77 }, { 0x7b,0x8d,0xf6,0x7b }, + { 0xf2,0x0d,0xff,0xf2 }, { 0x6b,0xbd,0xd6,0x6b }, + { 0x6f,0xb1,0xde,0x6f }, { 0xc5,0x54,0x91,0xc5 }, + { 0x30,0x50,0x60,0x30 }, { 0x01,0x03,0x02,0x01 }, + { 0x67,0xa9,0xce,0x67 }, { 0x2b,0x7d,0x56,0x2b }, + { 0xfe,0x19,0xe7,0xfe }, { 0xd7,0x62,0xb5,0xd7 }, + { 0xab,0xe6,0x4d,0xab }, { 0x76,0x9a,0xec,0x76 }, + { 0xca,0x45,0x8f,0xca }, { 0x82,0x9d,0x1f,0x82 }, + { 0xc9,0x40,0x89,0xc9 }, { 0x7d,0x87,0xfa,0x7d }, + { 0xfa,0x15,0xef,0xfa }, { 0x59,0xeb,0xb2,0x59 }, + { 0x47,0xc9,0x8e,0x47 }, { 0xf0,0x0b,0xfb,0xf0 }, + { 0xad,0xec,0x41,0xad }, { 0xd4,0x67,0xb3,0xd4 }, + { 0xa2,0xfd,0x5f,0xa2 }, { 0xaf,0xea,0x45,0xaf }, + { 0x9c,0xbf,0x23,0x9c }, { 0xa4,0xf7,0x53,0xa4 }, + { 0x72,0x96,0xe4,0x72 }, { 0xc0,0x5b,0x9b,0xc0 }, + { 0xb7,0xc2,0x75,0xb7 }, { 0xfd,0x1c,0xe1,0xfd }, + { 0x93,0xae,0x3d,0x93 }, { 0x26,0x6a,0x4c,0x26 }, + { 0x36,0x5a,0x6c,0x36 }, { 0x3f,0x41,0x7e,0x3f }, + { 0xf7,0x02,0xf5,0xf7 }, { 0xcc,0x4f,0x83,0xcc }, + { 0x34,0x5c,0x68,0x34 }, { 0xa5,0xf4,0x51,0xa5 }, + { 0xe5,0x34,0xd1,0xe5 }, { 0xf1,0x08,0xf9,0xf1 }, + { 0x71,0x93,0xe2,0x71 }, { 0xd8,0x73,0xab,0xd8 }, + { 0x31,0x53,0x62,0x31 }, { 0x15,0x3f,0x2a,0x15 }, + { 0x04,0x0c,0x08,0x04 }, { 0xc7,0x52,0x95,0xc7 }, + { 0x23,0x65,0x46,0x23 }, { 0xc3,0x5e,0x9d,0xc3 }, + { 0x18,0x28,0x30,0x18 }, { 0x96,0xa1,0x37,0x96 }, + { 0x05,0x0f,0x0a,0x05 }, { 0x9a,0xb5,0x2f,0x9a }, + { 0x07,0x09,0x0e,0x07 }, { 0x12,0x36,0x24,0x12 }, + { 0x80,0x9b,0x1b,0x80 }, { 0xe2,0x3d,0xdf,0xe2 }, + { 0xeb,0x26,0xcd,0xeb }, { 0x27,0x69,0x4e,0x27 }, + { 0xb2,0xcd,0x7f,0xb2 }, { 0x75,0x9f,0xea,0x75 }, + { 0x09,0x1b,0x12,0x09 }, { 0x83,0x9e,0x1d,0x83 }, + { 0x2c,0x74,0x58,0x2c }, { 0x1a,0x2e,0x34,0x1a }, + { 0x1b,0x2d,0x36,0x1b }, { 0x6e,0xb2,0xdc,0x6e }, + { 0x5a,0xee,0xb4,0x5a }, { 0xa0,0xfb,0x5b,0xa0 }, + { 0x52,0xf6,0xa4,0x52 }, { 0x3b,0x4d,0x76,0x3b }, + { 0xd6,0x61,0xb7,0xd6 }, { 0xb3,0xce,0x7d,0xb3 }, + { 0x29,0x7b,0x52,0x29 }, { 0xe3,0x3e,0xdd,0xe3 }, + { 0x2f,0x71,0x5e,0x2f }, { 0x84,0x97,0x13,0x84 }, + { 0x53,0xf5,0xa6,0x53 }, { 0xd1,0x68,0xb9,0xd1 }, + { 0x00,0x00,0x00,0x00 }, { 0xed,0x2c,0xc1,0xed }, + { 0x20,0x60,0x40,0x20 }, { 0xfc,0x1f,0xe3,0xfc }, + { 0xb1,0xc8,0x79,0xb1 }, { 0x5b,0xed,0xb6,0x5b }, + { 0x6a,0xbe,0xd4,0x6a }, { 0xcb,0x46,0x8d,0xcb }, + { 0xbe,0xd9,0x67,0xbe }, { 0x39,0x4b,0x72,0x39 }, + { 0x4a,0xde,0x94,0x4a }, { 0x4c,0xd4,0x98,0x4c }, + { 0x58,0xe8,0xb0,0x58 }, { 0xcf,0x4a,0x85,0xcf }, + { 0xd0,0x6b,0xbb,0xd0 }, { 0xef,0x2a,0xc5,0xef }, + { 0xaa,0xe5,0x4f,0xaa }, { 0xfb,0x16,0xed,0xfb }, + { 0x43,0xc5,0x86,0x43 }, { 0x4d,0xd7,0x9a,0x4d }, + { 0x33,0x55,0x66,0x33 }, { 0x85,0x94,0x11,0x85 }, + { 0x45,0xcf,0x8a,0x45 }, { 0xf9,0x10,0xe9,0xf9 }, + { 0x02,0x06,0x04,0x02 }, { 0x7f,0x81,0xfe,0x7f }, + { 0x50,0xf0,0xa0,0x50 }, { 0x3c,0x44,0x78,0x3c }, + { 0x9f,0xba,0x25,0x9f }, { 0xa8,0xe3,0x4b,0xa8 }, + { 0x51,0xf3,0xa2,0x51 }, { 0xa3,0xfe,0x5d,0xa3 }, + { 0x40,0xc0,0x80,0x40 }, { 0x8f,0x8a,0x05,0x8f }, + { 0x92,0xad,0x3f,0x92 }, { 0x9d,0xbc,0x21,0x9d }, + { 0x38,0x48,0x70,0x38 }, { 0xf5,0x04,0xf1,0xf5 }, + { 0xbc,0xdf,0x63,0xbc }, { 0xb6,0xc1,0x77,0xb6 }, + { 0xda,0x75,0xaf,0xda }, { 0x21,0x63,0x42,0x21 }, + { 0x10,0x30,0x20,0x10 }, { 0xff,0x1a,0xe5,0xff }, + { 0xf3,0x0e,0xfd,0xf3 }, { 0xd2,0x6d,0xbf,0xd2 }, + { 0xcd,0x4c,0x81,0xcd }, { 0x0c,0x14,0x18,0x0c }, + { 0x13,0x35,0x26,0x13 }, { 0xec,0x2f,0xc3,0xec }, + { 0x5f,0xe1,0xbe,0x5f }, { 0x97,0xa2,0x35,0x97 }, + { 0x44,0xcc,0x88,0x44 }, { 0x17,0x39,0x2e,0x17 }, + { 0xc4,0x57,0x93,0xc4 }, { 0xa7,0xf2,0x55,0xa7 }, + { 0x7e,0x82,0xfc,0x7e }, { 0x3d,0x47,0x7a,0x3d }, + { 0x64,0xac,0xc8,0x64 }, { 0x5d,0xe7,0xba,0x5d }, + { 0x19,0x2b,0x32,0x19 }, { 0x73,0x95,0xe6,0x73 }, + { 0x60,0xa0,0xc0,0x60 }, { 0x81,0x98,0x19,0x81 }, + { 0x4f,0xd1,0x9e,0x4f }, { 0xdc,0x7f,0xa3,0xdc }, + { 0x22,0x66,0x44,0x22 }, { 0x2a,0x7e,0x54,0x2a }, + { 0x90,0xab,0x3b,0x90 }, { 0x88,0x83,0x0b,0x88 }, + { 0x46,0xca,0x8c,0x46 }, { 0xee,0x29,0xc7,0xee }, + { 0xb8,0xd3,0x6b,0xb8 }, { 0x14,0x3c,0x28,0x14 }, + { 0xde,0x79,0xa7,0xde }, { 0x5e,0xe2,0xbc,0x5e }, + { 0x0b,0x1d,0x16,0x0b }, { 0xdb,0x76,0xad,0xdb }, + { 0xe0,0x3b,0xdb,0xe0 }, { 0x32,0x56,0x64,0x32 }, + { 0x3a,0x4e,0x74,0x3a }, { 0x0a,0x1e,0x14,0x0a }, + { 0x49,0xdb,0x92,0x49 }, { 0x06,0x0a,0x0c,0x06 }, + { 0x24,0x6c,0x48,0x24 }, { 0x5c,0xe4,0xb8,0x5c }, + { 0xc2,0x5d,0x9f,0xc2 }, { 0xd3,0x6e,0xbd,0xd3 }, + { 0xac,0xef,0x43,0xac }, { 0x62,0xa6,0xc4,0x62 }, + { 0x91,0xa8,0x39,0x91 }, { 0x95,0xa4,0x31,0x95 }, + { 0xe4,0x37,0xd3,0xe4 }, { 0x79,0x8b,0xf2,0x79 }, + { 0xe7,0x32,0xd5,0xe7 }, { 0xc8,0x43,0x8b,0xc8 }, + { 0x37,0x59,0x6e,0x37 }, { 0x6d,0xb7,0xda,0x6d }, + { 0x8d,0x8c,0x01,0x8d }, { 0xd5,0x64,0xb1,0xd5 }, + { 0x4e,0xd2,0x9c,0x4e }, { 0xa9,0xe0,0x49,0xa9 }, + { 0x6c,0xb4,0xd8,0x6c }, { 0x56,0xfa,0xac,0x56 }, + { 0xf4,0x07,0xf3,0xf4 }, { 0xea,0x25,0xcf,0xea }, + { 0x65,0xaf,0xca,0x65 }, { 0x7a,0x8e,0xf4,0x7a }, + { 0xae,0xe9,0x47,0xae }, { 0x08,0x18,0x10,0x08 }, + { 0xba,0xd5,0x6f,0xba }, { 0x78,0x88,0xf0,0x78 }, + { 0x25,0x6f,0x4a,0x25 }, { 0x2e,0x72,0x5c,0x2e }, + { 0x1c,0x24,0x38,0x1c }, { 0xa6,0xf1,0x57,0xa6 }, + { 0xb4,0xc7,0x73,0xb4 }, { 0xc6,0x51,0x97,0xc6 }, + { 0xe8,0x23,0xcb,0xe8 }, { 0xdd,0x7c,0xa1,0xdd }, + { 0x74,0x9c,0xe8,0x74 }, { 0x1f,0x21,0x3e,0x1f }, + { 0x4b,0xdd,0x96,0x4b }, { 0xbd,0xdc,0x61,0xbd }, + { 0x8b,0x86,0x0d,0x8b }, { 0x8a,0x85,0x0f,0x8a }, + { 0x70,0x90,0xe0,0x70 }, { 0x3e,0x42,0x7c,0x3e }, + { 0xb5,0xc4,0x71,0xb5 }, { 0x66,0xaa,0xcc,0x66 }, + { 0x48,0xd8,0x90,0x48 }, { 0x03,0x05,0x06,0x03 }, + { 0xf6,0x01,0xf7,0xf6 }, { 0x0e,0x12,0x1c,0x0e }, + { 0x61,0xa3,0xc2,0x61 }, { 0x35,0x5f,0x6a,0x35 }, + { 0x57,0xf9,0xae,0x57 }, { 0xb9,0xd0,0x69,0xb9 }, + { 0x86,0x91,0x17,0x86 }, { 0xc1,0x58,0x99,0xc1 }, + { 0x1d,0x27,0x3a,0x1d }, { 0x9e,0xb9,0x27,0x9e }, + { 0xe1,0x38,0xd9,0xe1 }, { 0xf8,0x13,0xeb,0xf8 }, + { 0x98,0xb3,0x2b,0x98 }, { 0x11,0x33,0x22,0x11 }, + { 0x69,0xbb,0xd2,0x69 }, { 0xd9,0x70,0xa9,0xd9 }, + { 0x8e,0x89,0x07,0x8e }, { 0x94,0xa7,0x33,0x94 }, + { 0x9b,0xb6,0x2d,0x9b }, { 0x1e,0x22,0x3c,0x1e }, + { 0x87,0x92,0x15,0x87 }, { 0xe9,0x20,0xc9,0xe9 }, + { 0xce,0x49,0x87,0xce }, { 0x55,0xff,0xaa,0x55 }, + { 0x28,0x78,0x50,0x28 }, { 0xdf,0x7a,0xa5,0xdf }, + { 0x8c,0x8f,0x03,0x8c }, { 0xa1,0xf8,0x59,0xa1 }, + { 0x89,0x80,0x09,0x89 }, { 0x0d,0x17,0x1a,0x0d }, + { 0xbf,0xda,0x65,0xbf }, { 0xe6,0x31,0xd7,0xe6 }, + { 0x42,0xc6,0x84,0x42 }, { 0x68,0xb8,0xd0,0x68 }, + { 0x41,0xc3,0x82,0x41 }, { 0x99,0xb0,0x29,0x99 }, + { 0x2d,0x77,0x5a,0x2d }, { 0x0f,0x11,0x1e,0x0f }, + { 0xb0,0xcb,0x7b,0xb0 }, { 0x54,0xfc,0xa8,0x54 }, + { 0xbb,0xd6,0x6d,0xbb }, { 0x16,0x3a,0x2c,0x16 } +}; + +static const byte T4[256][4] = +{ + { 0x63,0x63,0xa5,0xc6 }, { 0x7c,0x7c,0x84,0xf8 }, + { 0x77,0x77,0x99,0xee }, { 0x7b,0x7b,0x8d,0xf6 }, + { 0xf2,0xf2,0x0d,0xff }, { 0x6b,0x6b,0xbd,0xd6 }, + { 0x6f,0x6f,0xb1,0xde }, { 0xc5,0xc5,0x54,0x91 }, + { 0x30,0x30,0x50,0x60 }, { 0x01,0x01,0x03,0x02 }, + { 0x67,0x67,0xa9,0xce }, { 0x2b,0x2b,0x7d,0x56 }, + { 0xfe,0xfe,0x19,0xe7 }, { 0xd7,0xd7,0x62,0xb5 }, + { 0xab,0xab,0xe6,0x4d }, { 0x76,0x76,0x9a,0xec }, + { 0xca,0xca,0x45,0x8f }, { 0x82,0x82,0x9d,0x1f }, + { 0xc9,0xc9,0x40,0x89 }, { 0x7d,0x7d,0x87,0xfa }, + { 0xfa,0xfa,0x15,0xef }, { 0x59,0x59,0xeb,0xb2 }, + { 0x47,0x47,0xc9,0x8e }, { 0xf0,0xf0,0x0b,0xfb }, + { 0xad,0xad,0xec,0x41 }, { 0xd4,0xd4,0x67,0xb3 }, + { 0xa2,0xa2,0xfd,0x5f }, { 0xaf,0xaf,0xea,0x45 }, + { 0x9c,0x9c,0xbf,0x23 }, { 0xa4,0xa4,0xf7,0x53 }, + { 0x72,0x72,0x96,0xe4 }, { 0xc0,0xc0,0x5b,0x9b }, + { 0xb7,0xb7,0xc2,0x75 }, { 0xfd,0xfd,0x1c,0xe1 }, + { 0x93,0x93,0xae,0x3d }, { 0x26,0x26,0x6a,0x4c }, + { 0x36,0x36,0x5a,0x6c }, { 0x3f,0x3f,0x41,0x7e }, + { 0xf7,0xf7,0x02,0xf5 }, { 0xcc,0xcc,0x4f,0x83 }, + { 0x34,0x34,0x5c,0x68 }, { 0xa5,0xa5,0xf4,0x51 }, + { 0xe5,0xe5,0x34,0xd1 }, { 0xf1,0xf1,0x08,0xf9 }, + { 0x71,0x71,0x93,0xe2 }, { 0xd8,0xd8,0x73,0xab }, + { 0x31,0x31,0x53,0x62 }, { 0x15,0x15,0x3f,0x2a }, + { 0x04,0x04,0x0c,0x08 }, { 0xc7,0xc7,0x52,0x95 }, + { 0x23,0x23,0x65,0x46 }, { 0xc3,0xc3,0x5e,0x9d }, + { 0x18,0x18,0x28,0x30 }, { 0x96,0x96,0xa1,0x37 }, + { 0x05,0x05,0x0f,0x0a }, { 0x9a,0x9a,0xb5,0x2f }, + { 0x07,0x07,0x09,0x0e }, { 0x12,0x12,0x36,0x24 }, + { 0x80,0x80,0x9b,0x1b }, { 0xe2,0xe2,0x3d,0xdf }, + { 0xeb,0xeb,0x26,0xcd }, { 0x27,0x27,0x69,0x4e }, + { 0xb2,0xb2,0xcd,0x7f }, { 0x75,0x75,0x9f,0xea }, + { 0x09,0x09,0x1b,0x12 }, { 0x83,0x83,0x9e,0x1d }, + { 0x2c,0x2c,0x74,0x58 }, { 0x1a,0x1a,0x2e,0x34 }, + { 0x1b,0x1b,0x2d,0x36 }, { 0x6e,0x6e,0xb2,0xdc }, + { 0x5a,0x5a,0xee,0xb4 }, { 0xa0,0xa0,0xfb,0x5b }, + { 0x52,0x52,0xf6,0xa4 }, { 0x3b,0x3b,0x4d,0x76 }, + { 0xd6,0xd6,0x61,0xb7 }, { 0xb3,0xb3,0xce,0x7d }, + { 0x29,0x29,0x7b,0x52 }, { 0xe3,0xe3,0x3e,0xdd }, + { 0x2f,0x2f,0x71,0x5e }, { 0x84,0x84,0x97,0x13 }, + { 0x53,0x53,0xf5,0xa6 }, { 0xd1,0xd1,0x68,0xb9 }, + { 0x00,0x00,0x00,0x00 }, { 0xed,0xed,0x2c,0xc1 }, + { 0x20,0x20,0x60,0x40 }, { 0xfc,0xfc,0x1f,0xe3 }, + { 0xb1,0xb1,0xc8,0x79 }, { 0x5b,0x5b,0xed,0xb6 }, + { 0x6a,0x6a,0xbe,0xd4 }, { 0xcb,0xcb,0x46,0x8d }, + { 0xbe,0xbe,0xd9,0x67 }, { 0x39,0x39,0x4b,0x72 }, + { 0x4a,0x4a,0xde,0x94 }, { 0x4c,0x4c,0xd4,0x98 }, + { 0x58,0x58,0xe8,0xb0 }, { 0xcf,0xcf,0x4a,0x85 }, + { 0xd0,0xd0,0x6b,0xbb }, { 0xef,0xef,0x2a,0xc5 }, + { 0xaa,0xaa,0xe5,0x4f }, { 0xfb,0xfb,0x16,0xed }, + { 0x43,0x43,0xc5,0x86 }, { 0x4d,0x4d,0xd7,0x9a }, + { 0x33,0x33,0x55,0x66 }, { 0x85,0x85,0x94,0x11 }, + { 0x45,0x45,0xcf,0x8a }, { 0xf9,0xf9,0x10,0xe9 }, + { 0x02,0x02,0x06,0x04 }, { 0x7f,0x7f,0x81,0xfe }, + { 0x50,0x50,0xf0,0xa0 }, { 0x3c,0x3c,0x44,0x78 }, + { 0x9f,0x9f,0xba,0x25 }, { 0xa8,0xa8,0xe3,0x4b }, + { 0x51,0x51,0xf3,0xa2 }, { 0xa3,0xa3,0xfe,0x5d }, + { 0x40,0x40,0xc0,0x80 }, { 0x8f,0x8f,0x8a,0x05 }, + { 0x92,0x92,0xad,0x3f }, { 0x9d,0x9d,0xbc,0x21 }, + { 0x38,0x38,0x48,0x70 }, { 0xf5,0xf5,0x04,0xf1 }, + { 0xbc,0xbc,0xdf,0x63 }, { 0xb6,0xb6,0xc1,0x77 }, + { 0xda,0xda,0x75,0xaf }, { 0x21,0x21,0x63,0x42 }, + { 0x10,0x10,0x30,0x20 }, { 0xff,0xff,0x1a,0xe5 }, + { 0xf3,0xf3,0x0e,0xfd }, { 0xd2,0xd2,0x6d,0xbf }, + { 0xcd,0xcd,0x4c,0x81 }, { 0x0c,0x0c,0x14,0x18 }, + { 0x13,0x13,0x35,0x26 }, { 0xec,0xec,0x2f,0xc3 }, + { 0x5f,0x5f,0xe1,0xbe }, { 0x97,0x97,0xa2,0x35 }, + { 0x44,0x44,0xcc,0x88 }, { 0x17,0x17,0x39,0x2e }, + { 0xc4,0xc4,0x57,0x93 }, { 0xa7,0xa7,0xf2,0x55 }, + { 0x7e,0x7e,0x82,0xfc }, { 0x3d,0x3d,0x47,0x7a }, + { 0x64,0x64,0xac,0xc8 }, { 0x5d,0x5d,0xe7,0xba }, + { 0x19,0x19,0x2b,0x32 }, { 0x73,0x73,0x95,0xe6 }, + { 0x60,0x60,0xa0,0xc0 }, { 0x81,0x81,0x98,0x19 }, + { 0x4f,0x4f,0xd1,0x9e }, { 0xdc,0xdc,0x7f,0xa3 }, + { 0x22,0x22,0x66,0x44 }, { 0x2a,0x2a,0x7e,0x54 }, + { 0x90,0x90,0xab,0x3b }, { 0x88,0x88,0x83,0x0b }, + { 0x46,0x46,0xca,0x8c }, { 0xee,0xee,0x29,0xc7 }, + { 0xb8,0xb8,0xd3,0x6b }, { 0x14,0x14,0x3c,0x28 }, + { 0xde,0xde,0x79,0xa7 }, { 0x5e,0x5e,0xe2,0xbc }, + { 0x0b,0x0b,0x1d,0x16 }, { 0xdb,0xdb,0x76,0xad }, + { 0xe0,0xe0,0x3b,0xdb }, { 0x32,0x32,0x56,0x64 }, + { 0x3a,0x3a,0x4e,0x74 }, { 0x0a,0x0a,0x1e,0x14 }, + { 0x49,0x49,0xdb,0x92 }, { 0x06,0x06,0x0a,0x0c }, + { 0x24,0x24,0x6c,0x48 }, { 0x5c,0x5c,0xe4,0xb8 }, + { 0xc2,0xc2,0x5d,0x9f }, { 0xd3,0xd3,0x6e,0xbd }, + { 0xac,0xac,0xef,0x43 }, { 0x62,0x62,0xa6,0xc4 }, + { 0x91,0x91,0xa8,0x39 }, { 0x95,0x95,0xa4,0x31 }, + { 0xe4,0xe4,0x37,0xd3 }, { 0x79,0x79,0x8b,0xf2 }, + { 0xe7,0xe7,0x32,0xd5 }, { 0xc8,0xc8,0x43,0x8b }, + { 0x37,0x37,0x59,0x6e }, { 0x6d,0x6d,0xb7,0xda }, + { 0x8d,0x8d,0x8c,0x01 }, { 0xd5,0xd5,0x64,0xb1 }, + { 0x4e,0x4e,0xd2,0x9c }, { 0xa9,0xa9,0xe0,0x49 }, + { 0x6c,0x6c,0xb4,0xd8 }, { 0x56,0x56,0xfa,0xac }, + { 0xf4,0xf4,0x07,0xf3 }, { 0xea,0xea,0x25,0xcf }, + { 0x65,0x65,0xaf,0xca }, { 0x7a,0x7a,0x8e,0xf4 }, + { 0xae,0xae,0xe9,0x47 }, { 0x08,0x08,0x18,0x10 }, + { 0xba,0xba,0xd5,0x6f }, { 0x78,0x78,0x88,0xf0 }, + { 0x25,0x25,0x6f,0x4a }, { 0x2e,0x2e,0x72,0x5c }, + { 0x1c,0x1c,0x24,0x38 }, { 0xa6,0xa6,0xf1,0x57 }, + { 0xb4,0xb4,0xc7,0x73 }, { 0xc6,0xc6,0x51,0x97 }, + { 0xe8,0xe8,0x23,0xcb }, { 0xdd,0xdd,0x7c,0xa1 }, + { 0x74,0x74,0x9c,0xe8 }, { 0x1f,0x1f,0x21,0x3e }, + { 0x4b,0x4b,0xdd,0x96 }, { 0xbd,0xbd,0xdc,0x61 }, + { 0x8b,0x8b,0x86,0x0d }, { 0x8a,0x8a,0x85,0x0f }, + { 0x70,0x70,0x90,0xe0 }, { 0x3e,0x3e,0x42,0x7c }, + { 0xb5,0xb5,0xc4,0x71 }, { 0x66,0x66,0xaa,0xcc }, + { 0x48,0x48,0xd8,0x90 }, { 0x03,0x03,0x05,0x06 }, + { 0xf6,0xf6,0x01,0xf7 }, { 0x0e,0x0e,0x12,0x1c }, + { 0x61,0x61,0xa3,0xc2 }, { 0x35,0x35,0x5f,0x6a }, + { 0x57,0x57,0xf9,0xae }, { 0xb9,0xb9,0xd0,0x69 }, + { 0x86,0x86,0x91,0x17 }, { 0xc1,0xc1,0x58,0x99 }, + { 0x1d,0x1d,0x27,0x3a }, { 0x9e,0x9e,0xb9,0x27 }, + { 0xe1,0xe1,0x38,0xd9 }, { 0xf8,0xf8,0x13,0xeb }, + { 0x98,0x98,0xb3,0x2b }, { 0x11,0x11,0x33,0x22 }, + { 0x69,0x69,0xbb,0xd2 }, { 0xd9,0xd9,0x70,0xa9 }, + { 0x8e,0x8e,0x89,0x07 }, { 0x94,0x94,0xa7,0x33 }, + { 0x9b,0x9b,0xb6,0x2d }, { 0x1e,0x1e,0x22,0x3c }, + { 0x87,0x87,0x92,0x15 }, { 0xe9,0xe9,0x20,0xc9 }, + { 0xce,0xce,0x49,0x87 }, { 0x55,0x55,0xff,0xaa }, + { 0x28,0x28,0x78,0x50 }, { 0xdf,0xdf,0x7a,0xa5 }, + { 0x8c,0x8c,0x8f,0x03 }, { 0xa1,0xa1,0xf8,0x59 }, + { 0x89,0x89,0x80,0x09 }, { 0x0d,0x0d,0x17,0x1a }, + { 0xbf,0xbf,0xda,0x65 }, { 0xe6,0xe6,0x31,0xd7 }, + { 0x42,0x42,0xc6,0x84 }, { 0x68,0x68,0xb8,0xd0 }, + { 0x41,0x41,0xc3,0x82 }, { 0x99,0x99,0xb0,0x29 }, + { 0x2d,0x2d,0x77,0x5a }, { 0x0f,0x0f,0x11,0x1e }, + { 0xb0,0xb0,0xcb,0x7b }, { 0x54,0x54,0xfc,0xa8 }, + { 0xbb,0xbb,0xd6,0x6d }, { 0x16,0x16,0x3a,0x2c } +}; + +static const uint32_t rcon[30] = +{ + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, + 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 +}; + +static char *AES_SelfTest(void); + +/* Perform the key setup. + */ +static boolean AES_SetKey(RIJNDAEL_context *ctx, const byte *key, + const unsigned keylen) +{ + int ROUNDS; + byte k[MAXKC][4]; + int i,j, r, t, rconpointer = 0; + byte tk[MAXKC][4]; + int KC; + + if( keylen == 128/8 ) + { + ROUNDS = 10; + KC = 4; + } + else if ( keylen == 192/8 ) + { + ROUNDS = 12; + KC = 6; + } + else if ( keylen == 256/8 ) + { + ROUNDS = 14; + KC = 8; + } + else + { + return false; + } + + ctx->ROUNDS = ROUNDS; + + for (i = 0; i < keylen; i++) + { + k[i >> 2][i & 3] = key[i]; + } +#define W (ctx->keySched) + + for (j = KC-1; j >= 0; j--) + { + *((uint32_t*)tk[j]) = *((uint32_t*)k[j]); + } + r = 0; + t = 0; + /* copy values into round key array */ + for (j = 0; (j < KC) && (r < ROUNDS + 1); ) + { + for (; (j < KC) && (t < 4); j++, t++) + { + W[r][t] = *((uint32_t*)tk[j]); + } + if (t == 4) + { + r++; + t = 0; + } + } + + while (r < ROUNDS + 1) + { + /* while not enough round key material calculated */ + /* calculate new values */ + tk[0][0] ^= S[tk[KC-1][1]]; + tk[0][1] ^= S[tk[KC-1][2]]; + tk[0][2] ^= S[tk[KC-1][3]]; + tk[0][3] ^= S[tk[KC-1][0]]; + tk[0][0] ^= rcon[rconpointer++]; + + if (KC != 8) + { + for (j = 1; j < KC; j++) + { + *((uint32_t*)tk[j]) ^= *((uint32_t*)tk[j-1]); + } + } + else + { + for (j = 1; j < KC/2; j++) + { + *((uint32_t*)tk[j]) ^= *((uint32_t*)tk[j-1]); + } + tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; + tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; + tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; + tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; + for (j = KC/2 + 1; j < KC; j++) + { + *((uint32_t*)tk[j]) ^= *((uint32_t*)tk[j-1]); + } + } + /* copy values into round key array */ + for (j = 0; (j < KC) && (r < ROUNDS + 1); ) + { + for (; (j < KC) && (t < 4); j++, t++) + { + W[r][t] = *((uint32_t*)tk[j]); + } + if (t == 4) + { + r++; + t = 0; + } + } + } + +#undef W + return true; +} + +/* Encrypt one block. A and B need to be aligned on a 4 byte + boundary. A and B may be the same. */ +static void AES_EncryptAligned(const RIJNDAEL_context *ctx, + byte *b, const byte *a) +{ +#define rk (ctx->keySched) + int ROUNDS = ctx->ROUNDS; + int r; + union + { + uint32_t u32; + byte b[4]; + } temp[4]; + + temp[0].u32 = *((uint32_t*)(a )) ^ rk[0][0]; + temp[1].u32 = *((uint32_t*)(a+ 4)) ^ rk[0][1]; + temp[2].u32 = *((uint32_t*)(a+ 8)) ^ rk[0][2]; + temp[3].u32 = *((uint32_t*)(a+12)) ^ rk[0][3]; + *((uint32_t*)(b )) = (*((uint32_t*)T1[temp[0].b[0]]) + ^ *((uint32_t*)T2[temp[1].b[1]]) + ^ *((uint32_t*)T3[temp[2].b[2]]) + ^ *((uint32_t*)T4[temp[3].b[3]])); + *((uint32_t*)(b + 4)) = (*((uint32_t*)T1[temp[1].b[0]]) + ^ *((uint32_t*)T2[temp[2].b[1]]) + ^ *((uint32_t*)T3[temp[3].b[2]]) + ^ *((uint32_t*)T4[temp[0].b[3]])); + *((uint32_t*)(b + 8)) = (*((uint32_t*)T1[temp[2].b[0]]) + ^ *((uint32_t*)T2[temp[3].b[1]]) + ^ *((uint32_t*)T3[temp[0].b[2]]) + ^ *((uint32_t*)T4[temp[1].b[3]])); + *((uint32_t*)(b +12)) = (*((uint32_t*)T1[temp[3].b[0]]) + ^ *((uint32_t*)T2[temp[0].b[1]]) + ^ *((uint32_t*)T3[temp[1].b[2]]) + ^ *((uint32_t*)T4[temp[2].b[3]])); + + for (r = 1; r < ROUNDS-1; r++) + { + temp[0].u32 = *((uint32_t*)(b )) ^ rk[r][0]; + temp[1].u32 = *((uint32_t*)(b+ 4)) ^ rk[r][1]; + temp[2].u32 = *((uint32_t*)(b+ 8)) ^ rk[r][2]; + temp[3].u32 = *((uint32_t*)(b+12)) ^ rk[r][3]; + + *((uint32_t*)(b )) = (*((uint32_t*)T1[temp[0].b[0]]) + ^ *((uint32_t*)T2[temp[1].b[1]]) + ^ *((uint32_t*)T3[temp[2].b[2]]) + ^ *((uint32_t*)T4[temp[3].b[3]])); + *((uint32_t*)(b + 4)) = (*((uint32_t*)T1[temp[1].b[0]]) + ^ *((uint32_t*)T2[temp[2].b[1]]) + ^ *((uint32_t*)T3[temp[3].b[2]]) + ^ *((uint32_t*)T4[temp[0].b[3]])); + *((uint32_t*)(b + 8)) = (*((uint32_t*)T1[temp[2].b[0]]) + ^ *((uint32_t*)T2[temp[3].b[1]]) + ^ *((uint32_t*)T3[temp[0].b[2]]) + ^ *((uint32_t*)T4[temp[1].b[3]])); + *((uint32_t*)(b +12)) = (*((uint32_t*)T1[temp[3].b[0]]) + ^ *((uint32_t*)T2[temp[0].b[1]]) + ^ *((uint32_t*)T3[temp[1].b[2]]) + ^ *((uint32_t*)T4[temp[2].b[3]])); + } + + /* Last round is special. */ + temp[0].u32 = *((uint32_t*)(b )) ^ rk[ROUNDS-1][0]; + temp[1].u32 = *((uint32_t*)(b+ 4)) ^ rk[ROUNDS-1][1]; + temp[2].u32 = *((uint32_t*)(b+ 8)) ^ rk[ROUNDS-1][2]; + temp[3].u32 = *((uint32_t*)(b+12)) ^ rk[ROUNDS-1][3]; + b[ 0] = T1[temp[0].b[0]][1]; + b[ 1] = T1[temp[1].b[1]][1]; + b[ 2] = T1[temp[2].b[2]][1]; + b[ 3] = T1[temp[3].b[3]][1]; + b[ 4] = T1[temp[1].b[0]][1]; + b[ 5] = T1[temp[2].b[1]][1]; + b[ 6] = T1[temp[3].b[2]][1]; + b[ 7] = T1[temp[0].b[3]][1]; + b[ 8] = T1[temp[2].b[0]][1]; + b[ 9] = T1[temp[3].b[1]][1]; + b[10] = T1[temp[0].b[2]][1]; + b[11] = T1[temp[1].b[3]][1]; + b[12] = T1[temp[3].b[0]][1]; + b[13] = T1[temp[0].b[1]][1]; + b[14] = T1[temp[1].b[2]][1]; + b[15] = T1[temp[2].b[3]][1]; + *((uint32_t*)(b )) ^= rk[ROUNDS][0]; + *((uint32_t*)(b+ 4)) ^= rk[ROUNDS][1]; + *((uint32_t*)(b+ 8)) ^= rk[ROUNDS][2]; + *((uint32_t*)(b+12)) ^= rk[ROUNDS][3]; +#undef rk +} + +static void AES_Encrypt(const RIJNDAEL_context *ctx, + byte *bx, const byte *ax) +{ + /* BX and AX are not necessary correctly aligned. Thus we need to + copy them here. */ + uint32_t a[4]; + uint32_t b[4]; + + memcpy(a, ax, 16); + AES_EncryptAligned(ctx, (byte *) b, (byte *) a); + memcpy(bx, b, 16); +} + +/* Test a single encryption and decryption with each key size. */ + +static char *AES_SelfTest(void) +{ + RIJNDAEL_context ctx; + byte scratch[16]; + + /* The test vectors are from the AES supplied ones; more or less + * randomly taken from ecb_tbl.txt (I=42,81,14) + */ + static const byte plaintext[16] = { + 0x01,0x4B,0xAF,0x22,0x78,0xA6,0x9D,0x33, + 0x1D,0x51,0x80,0x10,0x36,0x43,0xE9,0x9A + }; + static const byte key[16] = { + 0xE8,0xE9,0xEA,0xEB,0xED,0xEE,0xEF,0xF0, + 0xF2,0xF3,0xF4,0xF5,0xF7,0xF8,0xF9,0xFA + }; + static const byte ciphertext[16] = { + 0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2, + 0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD + }; + + static const byte plaintext_192[16] = { + 0x76,0x77,0x74,0x75,0xF1,0xF2,0xF3,0xF4, + 0xF8,0xF9,0xE6,0xE7,0x77,0x70,0x71,0x72 + }; + static const byte key_192[24] = { + 0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C, + 0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16, + 0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20 + }; + static const byte ciphertext_192[16] = { + 0x5D,0x1E,0xF2,0x0D,0xCE,0xD6,0xBC,0xBC, + 0x12,0x13,0x1A,0xC7,0xC5,0x47,0x88,0xAA + }; + + static const byte plaintext_256[16] = { + 0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F, + 0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21 + }; + static const byte key_256[32] = { + 0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10, + 0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A, + 0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24, + 0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E + }; + static const byte ciphertext_256[16] = { + 0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71, + 0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3 + }; + + AES_SetKey(&ctx, key, sizeof(key)); + AES_Encrypt(&ctx, scratch, plaintext); + if (memcmp (scratch, ciphertext, sizeof (ciphertext))) + return "Rijndael-128 test encryption failed."; + + AES_SetKey(&ctx, key_192, sizeof(key_192)); + AES_Encrypt(&ctx, scratch, plaintext_192); + if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192))) + return "Rijndael-192 test encryption failed."; + + AES_SetKey(&ctx, key_256, sizeof(key_256)); + AES_Encrypt(&ctx, scratch, plaintext_256); + if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) + return "Rijndael-256 test encryption failed."; + + return NULL; +} + +#ifndef TEST + +static boolean prng_enabled = false; +static RIJNDAEL_context prng_context; +static uint32_t prng_input_counter; +static uint32_t prng_values[4]; +static unsigned int prng_value_index = 0; + +// Initialize Pseudo-RNG using the specified 128-bit key. + +void PRNG_Start(prng_seed_t key) +{ + char *errormsg; + + errormsg = AES_SelfTest(); + + if (errormsg != NULL) + { + I_Error("Failed to initialize PRNG: %s", errormsg); + } + + AES_SetKey(&prng_context, key, sizeof(prng_seed_t)); + prng_value_index = 4; + prng_input_counter = 0; + prng_enabled = true; +} + +void PRNG_Stop(void) +{ + prng_enabled = false; +} + +// Generate a set of new PRNG values by encrypting a new block. + +static void PRNG_Generate(void) +{ + byte input[16], output[16]; + unsigned int i; + + // Input for the cipher is a consecutively increasing 32-bit counter. + + for (i = 0; i < 4; ++i) + { + input[4*i] = prng_input_counter & 0xff; + input[4*i + 1] = (prng_input_counter >> 8) & 0xff; + input[4*i + 2] = (prng_input_counter >> 16) & 0xff; + input[4*i + 3] = (prng_input_counter >> 24) & 0xff; + ++prng_input_counter; + } + + AES_Encrypt(&prng_context, output, input); + + for (i = 0; i < 4; ++i) + { + prng_values[i] = output[4*i] + | (output[4*i + 1] << 8) + | (output[4*i + 2] << 16) + | (output[4*i + 3] << 24); + } + + prng_value_index = 0; +} + +// Read a random 32-bit integer from the PRNG. + +unsigned int PRNG_Random(void) +{ + unsigned int result; + + if (!prng_enabled) + { + return 0; + } + + if (prng_value_index >= 4) + { + PRNG_Generate(); + } + + result = prng_values[prng_value_index]; + ++prng_value_index; + + return result; +} + + +#else /* #ifndef TEST */ + +int main(int argc, char *argv[]) +{ + char *errormsg; + + errormsg = AES_SelfTest(); + + if (errormsg == NULL) + { + printf("AES Self test passed.\n"); + return 0; + } + else + { + fprintf(stderr, "AES self test failed: %s\n", errormsg); + return 1; + } +} + +#endif diff --git a/src/aes_prng.h b/src/aes_prng.h new file mode 100644 index 00000000..4c06f3a3 --- /dev/null +++ b/src/aes_prng.h @@ -0,0 +1,40 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2012 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +// DESCRIPTION: +// Pseudo-random number generator for secure demos. +// +//----------------------------------------------------------------------------- + +#ifndef __AES_PRNG_H__ +#define __AES_PRNG_H__ + +#include "doomtype.h" + +// Nonce value used as random seed for secure demos. + +typedef byte prng_seed_t[16]; + +void PRNG_Start(prng_seed_t seed); +void PRNG_Stop(void); +unsigned int PRNG_Random(void); + +#endif /* #ifndef __AES_PRNG_H__ */ + diff --git a/src/d_iwad.c b/src/d_iwad.c index 8c29352b..aefb6872 100644 --- a/src/d_iwad.c +++ b/src/d_iwad.c @@ -175,6 +175,10 @@ static char *steam_install_subdirs[] = "steamapps\\common\\ultimate doom\\base", "steamapps\\common\\hexen\\base", "steamapps\\common\\heretic shadow of the serpent riders\\base" + + // From Doom 3: BFG Edition: + + "steamapps\\common\\DOOM 3 BFG Edition\\base\\wads", }; static char *GetRegistryString(registry_value_t *reg_val) @@ -219,7 +223,7 @@ static char *GetRegistryString(registry_value_t *reg_val) } // Close the key - + RegCloseKey(key); return result; diff --git a/src/deh_defs.h b/src/deh_defs.h index e7b76182..2ab65c5d 100644 --- a/src/deh_defs.h +++ b/src/deh_defs.h @@ -27,7 +27,7 @@ #ifndef DEH_DEFS_H #define DEH_DEFS_H -#include "md5.h" +#include "sha1.h" typedef struct deh_context_s deh_context_t; typedef struct deh_section_s deh_section_t; @@ -35,7 +35,7 @@ typedef void (*deh_section_init_t)(void); typedef void *(*deh_section_start_t)(deh_context_t *context, char *line); typedef void (*deh_section_end_t)(deh_context_t *context, void *tag); typedef void (*deh_line_parser_t)(deh_context_t *context, char *line, void *tag); -typedef void (*deh_md5_hash_t)(md5_context_t *context); +typedef void (*deh_sha1_hash_t)(sha1_context_t *context); struct deh_section_s { @@ -58,9 +58,9 @@ struct deh_section_s deh_section_end_t end; - // Called when generating an MD5 sum of the dehacked state + // Called when generating an SHA1 sum of the dehacked state - deh_md5_hash_t md5_hash; + deh_sha1_hash_t sha1_hash; }; #endif /* #ifndef DEH_DEFS_H */ diff --git a/src/deh_main.c b/src/deh_main.c index 39d59e8c..4bb3e383 100644 --- a/src/deh_main.c +++ b/src/deh_main.c @@ -54,22 +54,22 @@ boolean deh_allow_long_cheats = false; boolean deh_apply_cheats = true; -void DEH_Checksum(md5_digest_t digest) +void DEH_Checksum(sha1_digest_t digest) { - md5_context_t md5_context; + sha1_context_t sha1_context; unsigned int i; - MD5_Init(&md5_context); + SHA1_Init(&sha1_context); for (i=0; deh_section_types[i] != NULL; ++i) { - if (deh_section_types[i]->md5_hash != NULL) + if (deh_section_types[i]->sha1_hash != NULL) { - deh_section_types[i]->md5_hash(&md5_context); + deh_section_types[i]->sha1_hash(&sha1_context); } } - MD5_Final(digest, &md5_context); + SHA1_Final(digest, &sha1_context); } // Called on startup to call the Init functions diff --git a/src/deh_main.h b/src/deh_main.h index 9ac2c6c7..ea9e42da 100644 --- a/src/deh_main.h +++ b/src/deh_main.h @@ -29,8 +29,8 @@ #include "doomtype.h" #include "doomfeatures.h" -#include "md5.h" #include "deh_str.h" +#include "sha1.h" // These are the limits that dehacked uses (from dheinit.h in the dehacked // source). If these limits are exceeded, it does not generate an error, but @@ -46,7 +46,7 @@ int DEH_LoadLumpByName(char *name); boolean DEH_ParseAssignment(char *line, char **variable_name, char **value); -void DEH_Checksum(md5_digest_t digest); +void DEH_Checksum(sha1_digest_t digest); extern boolean deh_allow_long_strings; extern boolean deh_allow_long_cheats; diff --git a/src/deh_mapping.c b/src/deh_mapping.c index f061c298..85c675b4 100644 --- a/src/deh_mapping.c +++ b/src/deh_mapping.c @@ -163,8 +163,8 @@ boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, return true; } -void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping, - void *structptr) +void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping, + void *structptr) { int i; @@ -189,13 +189,13 @@ void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping, switch (entry->size) { case 1: - MD5_UpdateInt32(context, *((uint8_t *) location)); + SHA1_UpdateInt32(context, *((uint8_t *) location)); break; case 2: - MD5_UpdateInt32(context, *((uint16_t *) location)); + SHA1_UpdateInt32(context, *((uint16_t *) location)); break; case 4: - MD5_UpdateInt32(context, *((uint32_t *) location)); + SHA1_UpdateInt32(context, *((uint32_t *) location)); break; default: I_Error("Unknown dehacked mapping field type for '%s' (BUG)", diff --git a/src/deh_mapping.h b/src/deh_mapping.h index 129ddcfd..91e34323 100644 --- a/src/deh_mapping.h +++ b/src/deh_mapping.h @@ -31,7 +31,7 @@ #include "doomtype.h" #include "deh_io.h" -#include "md5.h" +#include "sha1.h" #define DEH_BEGIN_MAPPING(mapping_name, structname) \ static structname deh_mapping_base; \ @@ -95,8 +95,8 @@ boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping, void *structptr, char *name, int value); boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping, void *structptr, char *name, char *value); -void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping, - void *structptr); +void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping, + void *structptr); #endif /* #ifndef DEH_MAPPING_H */ diff --git a/src/doom/d_main.c b/src/doom/d_main.c index d91649a8..0746a579 100644 --- a/src/doom/d_main.c +++ b/src/doom/d_main.c @@ -123,9 +123,10 @@ int startloadgame; boolean advancedemo; // Store demo, do not accept any inputs - boolean storedemo; +// "BFG Edition" version of doom2.wad does not include TITLEPIC. +boolean bfgedition; char wadfile[1024]; // primary wad file char mapdir[1024]; // directory of development maps @@ -566,6 +567,13 @@ void D_DoAdvanceDemo (void) G_DeferedPlayDemo(DEH_String("demo4")); break; } + + // The Doom 3: BFG Edition version of doom2.wad does not have a + // TITLETPIC lump. Use INTERPIC instead as a workaround. + if (bfgedition && !strcasecmp(pagename, "TITLEPIC")) + { + pagename = "INTERPIC"; + } } @@ -1539,13 +1547,27 @@ void D_DoomMain (void) DEH_printf("ST_Init: Init status bar.\n"); ST_Init (); - // If Doom II without a MAP01 lump, this is a store demo. + // If Doom II without a MAP01 lump, this is a store demo. // Moved this here so that MAP01 isn't constantly looked up // in the main loop. if (gamemode == commercial && W_CheckNumForName("map01") < 0) storedemo = true; + // Doom 3: BFG Edition includes modified versions of the classic + // IWADs. The modified version of doom2.wad does not have a + // TITLEPIC lump, so detect this so we can apply a workaround. + // We specifically check for TITLEPIC here, after PWADs have been + // loaded - this means that we can play with the BFG Edition with + // PWADs that change the title screen and still see the modified + // titles. + + if (gamemode == commercial && W_CheckNumForName("titlepic") < 0) + { + printf("BFG Edition: Using INTERPIC instead of TITLEPIC.\n"); + bfgedition = true; + } + if (M_CheckParmWithArgs("-statdump", 1)) { I_AtExit(StatDump, true); diff --git a/src/doom/d_net.c b/src/doom/d_net.c index 74893724..4ab61425 100644 --- a/src/doom/d_net.c +++ b/src/doom/d_net.c @@ -215,8 +215,8 @@ static void SaveGameSettings(net_gamesettings_t *settings, // Read checksums of our WAD directory and dehacked information - W_Checksum(connect_data->wad_md5sum); - DEH_Checksum(connect_data->deh_md5sum); + W_Checksum(connect_data->wad_sha1sum); + DEH_Checksum(connect_data->deh_sha1sum); // Are we playing with the Freedoom IWAD? diff --git a/src/doom/deh_ammo.c b/src/doom/deh_ammo.c index 2c6a9022..952d8df3 100644 --- a/src/doom/deh_ammo.c +++ b/src/doom/deh_ammo.c @@ -89,14 +89,14 @@ static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_AmmoMD5Hash(md5_context_t *context) +static void DEH_AmmoSHA1Hash(sha1_context_t *context) { int i; for (i=0; i<NUMAMMO; ++i) { - MD5_UpdateInt32(context, clipammo[i]); - MD5_UpdateInt32(context, maxammo[i]); + SHA1_UpdateInt32(context, clipammo[i]); + SHA1_UpdateInt32(context, maxammo[i]); } } @@ -107,6 +107,6 @@ deh_section_t deh_section_ammo = DEH_AmmoStart, DEH_AmmoParseLine, NULL, - DEH_AmmoMD5Hash, + DEH_AmmoSHA1Hash, }; diff --git a/src/doom/deh_frame.c b/src/doom/deh_frame.c index e59f09f4..8fc01803 100644 --- a/src/doom/deh_frame.c +++ b/src/doom/deh_frame.c @@ -148,13 +148,13 @@ static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_FrameMD5Sum(md5_context_t *context) +static void DEH_FrameSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMSTATES; ++i) { - DEH_StructMD5Sum(context, &state_mapping, &states[i]); + DEH_StructSHA1Sum(context, &state_mapping, &states[i]); } } @@ -165,6 +165,6 @@ deh_section_t deh_section_frame = DEH_FrameStart, DEH_FrameParseLine, NULL, - DEH_FrameMD5Sum, + DEH_FrameSHA1Sum, }; diff --git a/src/doom/deh_misc.c b/src/doom/deh_misc.c index b57d0ef0..eb5acece 100644 --- a/src/doom/deh_misc.c +++ b/src/doom/deh_misc.c @@ -215,13 +215,13 @@ static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag) DEH_Warning(context, "Unknown Misc variable '%s'", variable_name); } -static void DEH_MiscMD5Sum(md5_context_t *context) +static void DEH_MiscSHA1Sum(sha1_context_t *context) { unsigned int i; for (i=0; i<arrlen(misc_settings); ++i) { - MD5_UpdateInt32(context, *misc_settings[i].value); + SHA1_UpdateInt32(context, *misc_settings[i].value); } } @@ -232,6 +232,6 @@ deh_section_t deh_section_misc = DEH_MiscStart, DEH_MiscParseLine, NULL, - DEH_MiscMD5Sum, + DEH_MiscSHA1Sum, }; diff --git a/src/doom/deh_ptr.c b/src/doom/deh_ptr.c index d757a178..0d1764c9 100644 --- a/src/doom/deh_ptr.c +++ b/src/doom/deh_ptr.c @@ -129,13 +129,13 @@ static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_PointerMD5Sum(md5_context_t *context) +static void DEH_PointerSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMSTATES; ++i) { - MD5_UpdateInt32(context, CodePointerIndex(&states[i].action)); + SHA1_UpdateInt32(context, CodePointerIndex(&states[i].action)); } } @@ -146,6 +146,6 @@ deh_section_t deh_section_pointer = DEH_PointerStart, DEH_PointerParseLine, NULL, - DEH_PointerMD5Sum, + DEH_PointerSHA1Sum, }; diff --git a/src/doom/deh_thing.c b/src/doom/deh_thing.c index 5400ae60..d4e05f01 100644 --- a/src/doom/deh_thing.c +++ b/src/doom/deh_thing.c @@ -118,13 +118,13 @@ static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); } -static void DEH_ThingMD5Sum(md5_context_t *context) +static void DEH_ThingSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMMOBJTYPES; ++i) { - DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]); + DEH_StructSHA1Sum(context, &thing_mapping, &mobjinfo[i]); } } @@ -135,6 +135,6 @@ deh_section_t deh_section_thing = DEH_ThingStart, DEH_ThingParseLine, NULL, - DEH_ThingMD5Sum, + DEH_ThingSHA1Sum, }; diff --git a/src/doom/deh_weapon.c b/src/doom/deh_weapon.c index b0c2400c..5c590fe8 100644 --- a/src/doom/deh_weapon.c +++ b/src/doom/deh_weapon.c @@ -88,13 +88,13 @@ static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); } -static void DEH_WeaponMD5Sum(md5_context_t *context) +static void DEH_WeaponSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMWEAPONS ;++i) { - DEH_StructMD5Sum(context, &weapon_mapping, &weaponinfo[i]); + DEH_StructSHA1Sum(context, &weapon_mapping, &weaponinfo[i]); } } @@ -105,6 +105,6 @@ deh_section_t deh_section_weapon = DEH_WeaponStart, DEH_WeaponParseLine, NULL, - DEH_WeaponMD5Sum, + DEH_WeaponSHA1Sum, }; diff --git a/src/doom/g_game.c b/src/doom/g_game.c index 92577ff4..4ffddb41 100644 --- a/src/doom/g_game.c +++ b/src/doom/g_game.c @@ -257,6 +257,14 @@ static boolean WeaponSelectable(weapontype_t weapon) return false; } + // These weapons aren't available in shareware. + + if ((weapon == wp_plasma || weapon == wp_bfg) + && gamemission == doom && gamemode == shareware) + { + return false; + } + // Can't select a weapon if we don't own it. if (!players[consoleplayer].weaponowned[weapon]) diff --git a/src/doom/hu_stuff.c b/src/doom/hu_stuff.c index 9b67a1a5..3aaa5a33 100644 --- a/src/doom/hu_stuff.c +++ b/src/doom/hu_stuff.c @@ -595,11 +595,10 @@ boolean HU_Responder(event_t *ev) } else { - c = ev->data2; // send a macro if (altdown) { - c = c - '0'; + c = ev->data1 - '0'; if (c > 9) return false; // fprintf(stderr, "got here\n"); @@ -621,6 +620,8 @@ boolean HU_Responder(event_t *ev) } else { + c = ev->data2; + eatkey = HUlib_keyInIText(&w_chat, c); if (eatkey) { diff --git a/src/doom/m_menu.c b/src/doom/m_menu.c index e54ac7ff..b0eeee06 100644 --- a/src/doom/m_menu.c +++ b/src/doom/m_menu.c @@ -132,6 +132,7 @@ char savegamestrings[10][SAVESTRINGSIZE]; char endstring[160]; +static boolean opldev; // // MENU TYPEDEFS @@ -1887,6 +1888,39 @@ void M_StartControlPanel (void) itemOn = currentMenu->lastOn; // JDC } +// Display OPL debug messages - hack for GENMIDI development. + +static void M_DrawOPLDev(void) +{ + extern void I_OPL_DevMessages(char *); + char debug[1024]; + char *curr, *p; + int line; + + I_OPL_DevMessages(debug); + curr = debug; + line = 0; + + for (;;) + { + p = strchr(curr, '\n'); + + if (p != NULL) + { + *p = '\0'; + } + + M_WriteText(0, line * 8, curr); + ++line; + + if (p == NULL) + { + break; + } + + curr = p + 1; + } +} // // M_Drawer @@ -1938,6 +1972,11 @@ void M_Drawer (void) return; } + if (opldev) + { + M_DrawOPLDev(); + } + if (!menuactive) return; @@ -1965,7 +2004,6 @@ void M_Drawer (void) V_DrawPatchDirect(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT, W_CacheLumpName(DEH_String(skullName[whichSkull]), PU_CACHE)); - } @@ -2046,6 +2084,7 @@ void M_Init (void) default: break; } - + + opldev = M_CheckParm("-opldev") > 0; } diff --git a/src/doom/p_spec.c b/src/doom/p_spec.c index 90d0bb7c..68f986dc 100644 --- a/src/doom/p_spec.c +++ b/src/doom/p_spec.c @@ -1474,6 +1474,11 @@ void P_SpawnSpecials (void) switch(lines[i].special) { case 48: + if (numlinespecials >= MAXLINEANIMS) + { + I_Error("Too many scrolling wall linedefs! " + "(Vanilla limit is 64)"); + } // EFFECT FIRSTCOL SCROLL+ linespeciallist[numlinespecials] = &lines[i]; numlinespecials++; diff --git a/src/heretic/d_net.c b/src/heretic/d_net.c index 6a6a8abb..73a09ec6 100644 --- a/src/heretic/d_net.c +++ b/src/heretic/d_net.c @@ -177,8 +177,8 @@ static void SaveGameSettings(net_gamesettings_t *settings, // Read checksums of our WAD directory and dehacked information - W_Checksum(connect_data->wad_md5sum); - DEH_Checksum(connect_data->deh_md5sum); + W_Checksum(connect_data->wad_sha1sum); + DEH_Checksum(connect_data->deh_sha1sum); connect_data->is_freedoom = 0; } diff --git a/src/heretic/deh_ammo.c b/src/heretic/deh_ammo.c index fe86c757..08241863 100644 --- a/src/heretic/deh_ammo.c +++ b/src/heretic/deh_ammo.c @@ -95,18 +95,18 @@ static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_AmmoMD5Hash(md5_context_t *context) +static void DEH_AmmoSHA1Hash(sha1_context_t *context) { int i; for (i=0; i<NUMAMMO; ++i) { - MD5_UpdateInt32(context, maxammo[i]); + SHA1_UpdateInt32(context, maxammo[i]); } for (i=0; i<NUMWEAPONS; ++i) { - MD5_UpdateInt32(context, GetWeaponAmmo[i]); + SHA1_UpdateInt32(context, GetWeaponAmmo[i]); } } @@ -117,6 +117,6 @@ deh_section_t deh_section_ammo = DEH_AmmoStart, DEH_AmmoParseLine, NULL, - DEH_AmmoMD5Hash, + DEH_AmmoSHA1Hash, }; diff --git a/src/heretic/deh_frame.c b/src/heretic/deh_frame.c index 8623ab0c..4a1581a7 100644 --- a/src/heretic/deh_frame.c +++ b/src/heretic/deh_frame.c @@ -322,13 +322,13 @@ static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_FrameMD5Sum(md5_context_t *context) +static void DEH_FrameSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMSTATES; ++i) { - DEH_StructMD5Sum(context, &state_mapping, &states[i]); + DEH_StructSHA1Sum(context, &state_mapping, &states[i]); } } @@ -339,6 +339,6 @@ deh_section_t deh_section_frame = DEH_FrameStart, DEH_FrameParseLine, NULL, - DEH_FrameMD5Sum, + DEH_FrameSHA1Sum, }; diff --git a/src/heretic/deh_thing.c b/src/heretic/deh_thing.c index ffededf2..dbb239e4 100644 --- a/src/heretic/deh_thing.c +++ b/src/heretic/deh_thing.c @@ -128,13 +128,13 @@ static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); } -static void DEH_ThingMD5Sum(md5_context_t *context) +static void DEH_ThingSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMMOBJTYPES; ++i) { - DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]); + DEH_StructSHA1Sum(context, &thing_mapping, &mobjinfo[i]); } } @@ -145,6 +145,6 @@ deh_section_t deh_section_thing = DEH_ThingStart, DEH_ThingParseLine, NULL, - DEH_ThingMD5Sum, + DEH_ThingSHA1Sum, }; diff --git a/src/heretic/deh_weapon.c b/src/heretic/deh_weapon.c index 28a90c68..0c417e2b 100644 --- a/src/heretic/deh_weapon.c +++ b/src/heretic/deh_weapon.c @@ -108,14 +108,14 @@ static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); } -static void DEH_WeaponMD5Sum(md5_context_t *context) +static void DEH_WeaponSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMWEAPONS ;++i) { - DEH_StructMD5Sum(context, &weapon_mapping, &wpnlev1info[i]); - DEH_StructMD5Sum(context, &weapon_mapping, &wpnlev2info[i]); + DEH_StructSHA1Sum(context, &weapon_mapping, &wpnlev1info[i]); + DEH_StructSHA1Sum(context, &weapon_mapping, &wpnlev2info[i]); } } @@ -126,6 +126,6 @@ deh_section_t deh_section_weapon = DEH_WeaponStart, DEH_WeaponParseLine, NULL, - DEH_WeaponMD5Sum, + DEH_WeaponSHA1Sum, }; diff --git a/src/hexen/d_net.c b/src/hexen/d_net.c index 0fe5ed1e..7d663154 100644 --- a/src/hexen/d_net.c +++ b/src/hexen/d_net.c @@ -207,8 +207,8 @@ static void SaveGameSettings(net_gamesettings_t *settings, // Read checksums of our WAD directory and dehacked information - W_Checksum(connect_data->wad_md5sum); - memset(connect_data->deh_md5sum, 0, sizeof(md5_digest_t)); + W_Checksum(connect_data->wad_sha1sum); + memset(connect_data->deh_sha1sum, 0, sizeof(sha1_digest_t)); connect_data->is_freedoom = 0; } diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c index dd35ce5e..3d309715 100644 --- a/src/i_oplmusic.c +++ b/src/i_oplmusic.c @@ -46,11 +46,14 @@ #define MAXMIDLENGTH (96 * 1024) #define GENMIDI_NUM_INSTRS 128 +#define GENMIDI_NUM_PERCUSSION 47 #define GENMIDI_HEADER "#OPL_II#" #define GENMIDI_FLAG_FIXED 0x0001 /* fixed pitch */ #define GENMIDI_FLAG_2VOICE 0x0004 /* double voice (OPL3) */ +#define PERCUSSION_LOG_LEN 16 + typedef struct { byte tremolo; @@ -313,6 +316,8 @@ static int current_music_volume; static genmidi_instr_t *main_instrs; static genmidi_instr_t *percussion_instrs; +static char (*main_instr_names)[32]; +static char (*percussion_names)[32]; // Voices: @@ -327,6 +332,11 @@ static unsigned int num_tracks = 0; static unsigned int running_tracks = 0; static boolean song_looping; +// Mini-log of recently played percussion instruments: + +static uint8_t last_perc[PERCUSSION_LOG_LEN]; +static unsigned int last_perc_count; + // Configuration file variable, containing the port number for the // adlib chip. @@ -351,6 +361,8 @@ static boolean LoadInstrumentTable(void) main_instrs = (genmidi_instr_t *) (lump + strlen(GENMIDI_HEADER)); percussion_instrs = main_instrs + GENMIDI_NUM_INSTRS; + main_instr_names = (char (*)[32]) (percussion_instrs + GENMIDI_NUM_PERCUSSION); + percussion_names = main_instr_names + GENMIDI_NUM_INSTRS; return true; } @@ -893,6 +905,9 @@ static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event) } instrument = &percussion_instrs[key - 35]; + + last_perc[last_perc_count] = key; + last_perc_count = (last_perc_count + 1) % PERCUSSION_LOG_LEN; } else { @@ -1467,3 +1482,95 @@ music_module_t music_opl_module = I_OPL_MusicIsPlaying, }; +//---------------------------------------------------------------------- +// +// Development / debug message generation, to help developing GENMIDI +// lumps. +// +//---------------------------------------------------------------------- + +static int NumActiveChannels(void) +{ + int i; + + for (i = MIDI_CHANNELS_PER_TRACK - 1; i >= 0; --i) + { + if (tracks[0].channels[i].instrument != &main_instrs[0]) + { + return i + 1; + } + } + + return 0; +} + +static int ChannelInUse(opl_channel_data_t *channel) +{ + opl_voice_t *voice; + + for (voice = voice_alloced_list; voice != NULL; voice = voice->next) + { + if (voice->channel == channel) + { + return 1; + } + } + + return 0; +} + +void I_OPL_DevMessages(char *result) +{ + int instr_num; + int lines; + int i; + + if (num_tracks == 0) + { + sprintf(result, "No OPL track!"); + return; + } + + sprintf(result, "Tracks:\n"); + lines = 1; + + for (i = 0; i < NumActiveChannels(); ++i) + { + if (tracks[0].channels[i].instrument == NULL) + { + continue; + } + + instr_num = tracks[0].channels[i].instrument - main_instrs; + + sprintf(result + strlen(result), + "chan %i: %c i#%i (%s)\n", + i, + ChannelInUse(&tracks[0].channels[i]) ? '\'' : ' ', + instr_num + 1, + main_instr_names[instr_num]); + ++lines; + } + + sprintf(result + strlen(result), "\nLast percussion:\n"); + lines += 2; + + i = (last_perc_count + PERCUSSION_LOG_LEN - 1) % PERCUSSION_LOG_LEN; + + do { + if (last_perc[i] == 0) + { + break; + } + + sprintf(result + strlen(result), + "%cp#%i (%s)\n", + i == 0 ? '\'' : ' ', + last_perc[i], + percussion_names[last_perc[i] - 35]); + ++lines; + + i = (i + PERCUSSION_LOG_LEN - 1) % PERCUSSION_LOG_LEN; + } while (lines < 25 && i != last_perc_count); +} + diff --git a/src/i_video.c b/src/i_video.c index 7ba4c8cd..959a1472 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -378,6 +378,37 @@ static void UpdateFocus(void) screenvisible = (state & SDL_APPACTIVE) != 0; } +// Show or hide the mouse cursor. We have to use different techniques +// depending on the OS. + +static void ShowCursor(boolean show) +{ + // On Windows, using SDL_ShowCursor() adds lag to the mouse input, + // so work around this by setting an invisible cursor instead. On + // other systems, it isn't possible to change the cursor, so this + // hack has to be Windows-only. (Thanks to entryway for this) + +#ifdef _WIN32 + if (show) + { + SDL_SetCursor(cursors[1]); + } + else + { + SDL_SetCursor(cursors[0]); + } +#else + SDL_ShowCursor(show); +#endif + + // When the cursor is hidden, grab the input. + + if (!screensaver_mode) + { + SDL_WM_GrabInput(!show); + } +} + void I_EnableLoadingDisk(void) { patch_t *disk; @@ -532,12 +563,10 @@ void I_ShutdownGraphics(void) { if (initialized) { - SDL_SetCursor(cursors[1]); - SDL_ShowCursor(1); - SDL_WM_GrabInput(SDL_GRAB_OFF); + ShowCursor(true); SDL_QuitSubSystem(SDL_INIT_VIDEO); - + initialized = false; } } @@ -895,17 +924,15 @@ static void UpdateGrab(void) { // Hide the cursor in screensaver mode - SDL_SetCursor(cursors[0]); + ShowCursor(false); } else if (grab && !currently_grabbed) { - SDL_SetCursor(cursors[0]); - SDL_WM_GrabInput(SDL_GRAB_ON); + ShowCursor(false); } else if (!grab && currently_grabbed) { - SDL_SetCursor(cursors[1]); - SDL_WM_GrabInput(SDL_GRAB_OFF); + ShowCursor(true); } currently_grabbed = grab; diff --git a/src/m_misc.c b/src/m_misc.c index e14436a3..47aea8b9 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -32,9 +32,9 @@ #include <ctype.h> #include <errno.h> -// for mkdir: - #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> #include <io.h> #ifdef _MSC_VER #include <direct.h> @@ -296,3 +296,22 @@ char *M_StrCaseStr(char *haystack, char *needle) return NULL; } +#ifdef _WIN32 + +char *M_OEMToUTF8(const char *oem) +{ + unsigned int len = strlen(oem) + 1; + wchar_t *tmp; + char *result; + + tmp = malloc(len * sizeof(wchar_t)); + MultiByteToWideChar(CP_OEMCP, 0, oem, len, tmp, len); + result = malloc(len * 4); + WideCharToMultiByte(CP_UTF8, 0, tmp, len, result, len * 4, NULL, NULL); + free(tmp); + + return result; +} + +#endif + diff --git a/src/m_misc.h b/src/m_misc.h index c6be6ccb..ac5b5164 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -43,6 +43,7 @@ boolean M_StrToInt(const char *str, int *result); void M_ExtractFileBase(char *path, char *dest); void M_ForceUppercase(char *text); char *M_StrCaseStr(char *haystack, char *needle); +char *M_OEMToUTF8(const char *ansi); #endif diff --git a/src/md5.c b/src/md5.c deleted file mode 100644 index 2b184f98..00000000 --- a/src/md5.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5_Init, call MD5_Update as - * needed on buffers full of bytes, and then call MD5_Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' header - * definitions; now uses stuff from dpkg's config.h. - * - Ian Jackson <ian@chiark.greenend.org.uk>. - * Still in the public domain. - */ - -#include "i_swap.h" - -#include <string.h> /* for memcpy() */ -#include <sys/types.h> /* for stupid systems */ - -#include "md5.h" - -#ifdef SYS_LITTLE_ENDIAN - -// Little endian system - no byte swapping required - -#define ByteSwapBlock(x, y) - -#else - -void ByteSwapBlock(uint32_t *buf, unsigned words) -{ - byte *p = (byte *)buf; - - do { - *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 | - ((unsigned)p[1] << 8 | p[0]); - p += 4; - } while (--words); -} - -#endif /* #ifndef SYS_LITTLE_ENDIAN */ - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void -MD5_Init(md5_context_t *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bytes[0] = 0; - ctx->bytes[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void -MD5_Update(md5_context_t *ctx, byte const *buf, unsigned len) -{ - uint32_t t; - - /* Update byte count */ - - t = ctx->bytes[0]; - if ((ctx->bytes[0] = t + len) < t) - ctx->bytes[1]++; /* Carry from low to high */ - - t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ - if (t > len) { - memcpy((byte *)ctx->in + 64 - t, buf, len); - return; - } - /* First chunk is an odd size */ - memcpy((byte *)ctx->in + 64 - t, buf, t); - ByteSwapBlock(ctx->in, 16); - MD5_Transform(ctx->buf, ctx->in); - buf += t; - len -= t; - - /* Process data in 64-byte chunks */ - while (len >= 64) { - memcpy(ctx->in, buf, 64); - ByteSwapBlock(ctx->in, 16); - MD5_Transform(ctx->buf, ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - memcpy(ctx->in, buf, len); -} - -void MD5_UpdateInt32(md5_context_t *context, unsigned int val) -{ - byte buf[4]; - - buf[0] = (val >> 24) & 0xff; - buf[1] = (val >> 16) & 0xff; - buf[2] = (val >> 8) & 0xff; - buf[3] = val & 0xff; - - MD5_Update(context, buf, 4); -} - -void MD5_UpdateString(md5_context_t *context, char *str) -{ - MD5_Update(context, (byte *) str, strlen(str) + 1); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void -MD5_Final(byte digest[16], md5_context_t *ctx) -{ - int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ - byte *p = (byte *)ctx->in + count; - - /* Set the first char of padding to 0x80. There is always room. */ - *p++ = 0x80; - - /* Bytes of padding needed to make 56 bytes (-8..55) */ - count = 56 - 1 - count; - - if (count < 0) { /* Padding forces an extra block */ - memset(p, 0, count + 8); - ByteSwapBlock(ctx->in, 16); - MD5_Transform(ctx->buf, ctx->in); - p = (byte *)ctx->in; - count = 56; - } - memset(p, 0, count); - ByteSwapBlock(ctx->in, 14); - - /* Append length in bits and transform */ - ctx->in[14] = ctx->bytes[0] << 3; - ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; - MD5_Transform(ctx->buf, ctx->in); - - ByteSwapBlock(ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f,w,x,y,z,in,s) \ - (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5_Update blocks - * the data and converts bytes into longwords for this routine. - */ -void -MD5_Transform(uint32_t buf[4], uint32_t const in[16]) -{ - register uint32_t a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#endif - diff --git a/src/md5.h b/src/md5.h deleted file mode 100644 index 5df7f686..00000000 --- a/src/md5.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This is the header file for the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * md5_context_s structure, pass it to MD5_Init, call MD5_Update as - * needed on buffers full of bytes, and then call MD5_Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' - * header definitions; now uses stuff from dpkg's config.h - * - Ian Jackson <ian@chiark.greenend.org.uk>. - * Still in the public domain. - */ - -#ifndef MD5_H -#define MD5_H - -#include "doomtype.h" - -typedef struct md5_context_s md5_context_t; -typedef byte md5_digest_t[16]; - -struct md5_context_s { - uint32_t buf[4]; - uint32_t bytes[2]; - uint32_t in[16]; -}; - -void MD5_Init(md5_context_t *context); -void MD5_Update(md5_context_t *context, byte const *buf, unsigned len); -void MD5_UpdateInt32(md5_context_t *context, unsigned int val); -void MD5_UpdateString(md5_context_t *context, char *str); -void MD5_Final(unsigned char digest[16], md5_context_t *context); -void MD5_Transform(uint32_t buf[4], uint32_t const in[16]); - -#endif /* !MD5_H */ - diff --git a/src/net_client.c b/src/net_client.c index 083dca8b..abd94145 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -154,8 +154,8 @@ static unsigned int gamedata_recv_time; // Hash checksums of our wad directory and dehacked data. -md5_digest_t net_local_wad_md5sum; -md5_digest_t net_local_deh_md5sum; +sha1_digest_t net_local_wad_sha1sum; +sha1_digest_t net_local_deh_sha1sum; // Are we playing with the freedoom IWAD? @@ -905,8 +905,8 @@ boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data) server_addr = addr; - memcpy(net_local_wad_md5sum, data->wad_md5sum, sizeof(md5_digest_t)); - memcpy(net_local_deh_md5sum, data->deh_md5sum, sizeof(md5_digest_t)); + memcpy(net_local_wad_sha1sum, data->wad_sha1sum, sizeof(sha1_digest_t)); + memcpy(net_local_deh_sha1sum, data->deh_sha1sum, sizeof(sha1_digest_t)); net_local_is_freedoom = data->is_freedoom; // create a new network I/O context and add just the @@ -1049,6 +1049,17 @@ void NET_CL_Init(void) net_player_name = getenv("USER"); if (net_player_name == NULL) net_player_name = getenv("USERNAME"); + + // On Windows, environment variables are in OEM codepage + // encoding, so convert to UTF8: + +#ifdef _WIN32 + if (net_player_name != NULL) + { + net_player_name = M_OEMToUTF8(net_player_name); + } +#endif + if (net_player_name == NULL) net_player_name = "Player"; } diff --git a/src/net_client.h b/src/net_client.h index 242bf958..3914849d 100644 --- a/src/net_client.h +++ b/src/net_client.h @@ -26,7 +26,7 @@ #include "doomtype.h" #include "d_ticcmd.h" -#include "md5.h" +#include "sha1.h" #include "net_defs.h" boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data); @@ -46,11 +46,11 @@ extern net_waitdata_t net_client_wait_data; extern boolean net_waiting_for_start; extern char *net_player_name; -extern md5_digest_t net_server_wad_md5sum; -extern md5_digest_t net_server_deh_md5sum; +extern sha1_digest_t net_server_wad_sha1sum; +extern sha1_digest_t net_server_deh_sha1sum; extern unsigned int net_server_is_freedoom; -extern md5_digest_t net_local_wad_md5sum; -extern md5_digest_t net_local_deh_md5sum; +extern sha1_digest_t net_local_wad_sha1sum; +extern sha1_digest_t net_local_deh_sha1sum; extern unsigned int net_local_is_freedoom; extern boolean drone; diff --git a/src/net_defs.h b/src/net_defs.h index aa7b6f6e..ba50f48e 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -30,7 +30,7 @@ #include "doomtype.h" #include "d_ticcmd.h" -#include "md5.h" +#include "sha1.h" // Absolute maximum number of "nodes" in the game. This is different to // NET_MAXPLAYERS, as there may be observers that are not participating @@ -140,7 +140,13 @@ typedef enum NET_MASTER_PACKET_TYPE_ADD, NET_MASTER_PACKET_TYPE_ADD_RESPONSE, NET_MASTER_PACKET_TYPE_QUERY, - NET_MASTER_PACKET_TYPE_QUERY_RESPONSE + NET_MASTER_PACKET_TYPE_QUERY_RESPONSE, + NET_MASTER_PACKET_TYPE_GET_METADATA, + NET_MASTER_PACKET_TYPE_GET_METADATA_RESPONSE, + NET_MASTER_PACKET_TYPE_SIGN_START, + NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, + NET_MASTER_PACKET_TYPE_SIGN_END, + NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, } net_master_packet_type_t; // Settings specified when the client connects to the server. @@ -153,8 +159,8 @@ typedef struct int drone; int max_players; int is_freedoom; - md5_digest_t wad_md5sum; - md5_digest_t deh_md5sum; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; int player_class; } net_connect_data_t; @@ -239,8 +245,8 @@ typedef struct int consoleplayer; char player_names[NET_MAXPLAYERS][MAXPLAYERNAME]; char player_addrs[NET_MAXPLAYERS][MAXPLAYERNAME]; - md5_digest_t wad_md5sum; - md5_digest_t deh_md5sum; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; int is_freedoom; } net_waitdata_t; diff --git a/src/net_gui.c b/src/net_gui.c index 7fff33f6..14d0d943 100644 --- a/src/net_gui.c +++ b/src/net_gui.c @@ -184,13 +184,13 @@ static void UpdateGUI(net_gamesettings_t *settings) TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, startgame); } -static void PrintMD5Digest(char *s, byte *digest) +static void PrintSHA1Digest(char *s, byte *digest) { unsigned int i; printf("%s: ", s); - for (i=0; i<sizeof(md5_digest_t); ++i) + for (i=0; i<sizeof(sha1_digest_t); ++i) { printf("%02x", digest[i]); } @@ -198,7 +198,7 @@ static void PrintMD5Digest(char *s, byte *digest) printf("\n"); } -static void CheckMD5Sums(void) +static void CheckSHA1Sums(void) { boolean correct_wad, correct_deh; boolean same_freedoom; @@ -209,12 +209,12 @@ static void CheckMD5Sums(void) return; } - correct_wad = memcmp(net_local_wad_md5sum, - net_client_wait_data.wad_md5sum, - sizeof(md5_digest_t)) == 0; - correct_deh = memcmp(net_local_deh_md5sum, - net_client_wait_data.deh_md5sum, - sizeof(md5_digest_t)) == 0; + correct_wad = memcmp(net_local_wad_sha1sum, + net_client_wait_data.wad_sha1sum, + sizeof(sha1_digest_t)) == 0; + correct_deh = memcmp(net_local_deh_sha1sum, + net_client_wait_data.deh_sha1sum, + sizeof(sha1_digest_t)) == 0; same_freedoom = net_client_wait_data.is_freedoom == net_local_is_freedoom; if (correct_wad && correct_deh && same_freedoom) @@ -224,9 +224,9 @@ static void CheckMD5Sums(void) if (!correct_wad) { - printf("Warning: WAD MD5 does not match server:\n"); - PrintMD5Digest("Local", net_local_wad_md5sum); - PrintMD5Digest("Server", net_client_wait_data.wad_md5sum); + printf("Warning: WAD SHA1 does not match server:\n"); + PrintSHA1Digest("Local", net_local_wad_sha1sum); + PrintSHA1Digest("Server", net_client_wait_data.wad_sha1sum); } if (!same_freedoom) @@ -239,9 +239,9 @@ static void CheckMD5Sums(void) if (!correct_deh) { - printf("Warning: Dehacked MD5 does not match server:\n"); - PrintMD5Digest("Local", net_local_deh_md5sum); - PrintMD5Digest("Server", net_client_wait_data.deh_md5sum); + printf("Warning: Dehacked SHA1 does not match server:\n"); + PrintSHA1Digest("Local", net_local_deh_sha1sum); + PrintSHA1Digest("Server", net_client_wait_data.deh_sha1sum); } window = TXT_NewWindow("WARNING"); @@ -308,7 +308,7 @@ void NET_WaitForStart(net_gamesettings_t *settings) while (net_waiting_for_start) { UpdateGUI(settings); - CheckMD5Sums(); + CheckSHA1Sums(); TXT_DispatchEvents(); TXT_DrawDesktop(); diff --git a/src/net_query.c b/src/net_query.c index 26bcf26a..392ee022 100644 --- a/src/net_query.c +++ b/src/net_query.c @@ -46,6 +46,10 @@ #define QUERY_TIMEOUT_SECS 2 +// Time to wait for secure demo signatures before declaring a timeout. + +#define SIGNATURE_TIMEOUT_SECS 5 + // Number of query attempts to make before giving up on a server. #define QUERY_MAX_ATTEMPTS 3 @@ -89,6 +93,8 @@ static boolean query_loop_running = false; static boolean printed_header = false; static int last_query_time = 0; +static char *securedemo_start_message = NULL; + // Resolve the master server address. net_addr_t *NET_Query_ResolveMaster(net_context_t *context) @@ -815,3 +821,124 @@ net_addr_t *NET_FindLANServer(void) } } +// Block until a packet of the given type is received from the given +// address. + +static net_packet_t *BlockForPacket(net_addr_t *addr, unsigned int packet_type, + unsigned int timeout_ms) +{ + net_packet_t *packet; + net_addr_t *packet_src; + unsigned int read_packet_type; + unsigned int start_time; + + start_time = I_GetTimeMS(); + + while (I_GetTimeMS() < start_time + timeout_ms) + { + if (!NET_RecvPacket(query_context, &packet_src, &packet)) + { + I_Sleep(20); + continue; + } + + if (packet_src == addr + && NET_ReadInt16(packet, &read_packet_type) + && packet_type == read_packet_type) + { + return packet; + } + + NET_FreePacket(packet); + } + + // Timeout - no response. + + return NULL; +} + +// Query master server for secure demo start seed value. + +boolean NET_StartSecureDemo(prng_seed_t seed) +{ + net_packet_t *request, *response; + net_addr_t *master_addr; + char *signature; + boolean result; + + NET_Query_Init(); + master_addr = NET_Query_ResolveMaster(query_context); + + // Send request packet to master server. + + request = NET_NewPacket(10); + NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_START); + NET_SendPacket(master_addr, request); + NET_FreePacket(request); + + // Block for response and read contents. + // The signed start message will be saved for later. + + response = BlockForPacket(master_addr, + NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE, + SIGNATURE_TIMEOUT_SECS * 1000); + + result = false; + + if (response != NULL) + { + if (NET_ReadPRNGSeed(response, seed)) + { + signature = NET_ReadString(response); + + if (signature != NULL) + { + securedemo_start_message = strdup(signature); + result = true; + } + } + + NET_FreePacket(response); + } + + return result; +} + +// Query master server for secure demo end signature. + +char *NET_EndSecureDemo(sha1_digest_t demo_hash) +{ + net_packet_t *request, *response; + net_addr_t *master_addr; + char *signature; + + master_addr = NET_Query_ResolveMaster(query_context); + + // Construct end request and send to master server. + + request = NET_NewPacket(10); + NET_WriteInt16(request, NET_MASTER_PACKET_TYPE_SIGN_END); + NET_WriteSHA1Sum(request, demo_hash); + NET_WriteString(request, securedemo_start_message); + NET_SendPacket(master_addr, request); + NET_FreePacket(request); + + // Block for response. The response packet simply contains a string + // with the ASCII signature. + + response = BlockForPacket(master_addr, + NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE, + SIGNATURE_TIMEOUT_SECS * 1000); + + if (response == NULL) + { + return NULL; + } + + signature = NET_ReadString(response); + + NET_FreePacket(response); + + return signature; +} + diff --git a/src/net_sdl.c b/src/net_sdl.c index 6a4f24dc..de86172f 100644 --- a/src/net_sdl.c +++ b/src/net_sdl.c @@ -44,6 +44,7 @@ #define DEFAULT_PORT 2342 +static boolean initted = false; static int port = DEFAULT_PORT; static UDPsocket udpsocket; static UDPpacket *recvpacket; @@ -162,6 +163,9 @@ static boolean NET_SDL_InitClient(void) { int p; + if (initted) + return true; + //! // @category net // @arg <n> @@ -189,13 +193,18 @@ static boolean NET_SDL_InitClient(void) srand(time(NULL)); #endif + initted = true; + return true; } static boolean NET_SDL_InitServer(void) { int p; - + + if (initted) + return true; + p = M_CheckParmWithArgs("-port", 1); if (p > 0) port = atoi(myargv[p+1]); @@ -214,6 +223,8 @@ static boolean NET_SDL_InitServer(void) srand(time(NULL)); #endif + initted = true; + return true; } diff --git a/src/net_server.c b/src/net_server.c index b837bd70..585f0eac 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -50,6 +50,10 @@ #define MASTER_REFRESH_PERIOD 20 * 60 /* 20 minutes */ +// How often to re-resolve the address of the master server? + +#define MASTER_RESOLVE_PERIOD 8 * 60 * 60 /* 8 hours */ + typedef enum { // waiting for the game to start @@ -101,10 +105,10 @@ typedef struct boolean drone; - // MD5 hash sums of the client's WAD directory and dehacked data + // SHA1 hash sums of the client's WAD directory and dehacked data - md5_digest_t wad_md5sum; - md5_digest_t deh_md5sum; + sha1_digest_t wad_sha1sum; + sha1_digest_t deh_sha1sum; // Is this client is playing with the Freedoom IWAD? @@ -150,6 +154,7 @@ static net_gamesettings_t sv_settings; static net_addr_t *master_server = NULL; static unsigned int master_refresh_time; +static unsigned int master_resolve_time; // receive window @@ -646,10 +651,10 @@ static void NET_SV_ParseSYN(net_packet_t *packet, sv_gamemission = data.gamemission; } - // Save the MD5 checksums + // Save the SHA1 checksums - memcpy(client->wad_md5sum, data.wad_md5sum, sizeof(md5_digest_t)); - memcpy(client->deh_md5sum, data.deh_md5sum, sizeof(md5_digest_t)); + memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t)); + memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t)); client->is_freedoom = data.is_freedoom; client->max_players = data.max_players; @@ -1287,10 +1292,10 @@ static void NET_SV_SendWaitingData(net_client_t *client) controller = client; } - memcpy(&wait_data.wad_md5sum, &controller->wad_md5sum, - sizeof(md5_digest_t)); - memcpy(&wait_data.deh_md5sum, &controller->deh_md5sum, - sizeof(md5_digest_t)); + memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum, + sizeof(sha1_digest_t)); + memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum, + sizeof(sha1_digest_t)); wait_data.is_freedoom = controller->is_freedoom; // set name and address of each player: @@ -1605,6 +1610,42 @@ void NET_SV_Init(void) server_initialized = true; } +static void UpdateMasterServer(void) +{ + unsigned int now; + + now = I_GetTimeMS(); + + // The address of the master server can change. Periodically + // re-resolve the master server to update. + + if (now - master_resolve_time > MASTER_RESOLVE_PERIOD * 1000) + { + net_addr_t *new_addr; + printf("Re-resolve master server\n"); + + new_addr = NET_Query_ResolveMaster(server_context); + + // Has the master server changed address? + + if (new_addr != NULL && new_addr != master_server) + { + NET_FreeAddress(master_server); + master_server = new_addr; + } + + master_resolve_time = now; + } + + // Possibly refresh our registration with the master server. + + if (now - master_refresh_time > MASTER_REFRESH_PERIOD * 1000) + { + NET_Query_AddToMaster(master_server); + master_refresh_time = now; + } +} + void NET_SV_RegisterWithMaster(void) { //! @@ -1629,6 +1670,7 @@ void NET_SV_RegisterWithMaster(void) { NET_Query_AddToMaster(master_server); master_refresh_time = I_GetTimeMS(); + master_resolve_time = master_refresh_time; } } @@ -1652,13 +1694,9 @@ void NET_SV_Run(void) NET_FreePacket(packet); } - // Possibly refresh our registration with the master server. - - if (master_server != NULL - && I_GetTimeMS() - master_refresh_time > MASTER_REFRESH_PERIOD * 1000) + if (master_server != NULL) { - NET_Query_AddToMaster(master_server); - master_refresh_time = I_GetTimeMS(); + UpdateMasterServer(); } // "Run" any clients that may have things to do, independent of responses diff --git a/src/net_structrw.c b/src/net_structrw.c index f68a6130..8f6f8d57 100644 --- a/src/net_structrw.c +++ b/src/net_structrw.c @@ -39,8 +39,8 @@ void NET_WriteConnectData(net_packet_t *packet, net_connect_data_t *data) NET_WriteInt8(packet, data->drone); NET_WriteInt8(packet, data->max_players); NET_WriteInt8(packet, data->is_freedoom); - NET_WriteMD5Sum(packet, data->wad_md5sum); - NET_WriteMD5Sum(packet, data->deh_md5sum); + NET_WriteSHA1Sum(packet, data->wad_sha1sum); + NET_WriteSHA1Sum(packet, data->deh_sha1sum); NET_WriteInt8(packet, data->player_class); } @@ -52,8 +52,8 @@ boolean NET_ReadConnectData(net_packet_t *packet, net_connect_data_t *data) && NET_ReadInt8(packet, (unsigned int *) &data->drone) && NET_ReadInt8(packet, (unsigned int *) &data->max_players) && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom) - && NET_ReadMD5Sum(packet, data->wad_md5sum) - && NET_ReadMD5Sum(packet, data->deh_md5sum) + && NET_ReadSHA1Sum(packet, data->wad_sha1sum) + && NET_ReadSHA1Sum(packet, data->deh_sha1sum) && NET_ReadInt8(packet, (unsigned int *) &data->player_class); } @@ -461,8 +461,8 @@ void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data) NET_WriteString(packet, data->player_addrs[i]); } - NET_WriteMD5Sum(packet, data->wad_md5sum); - NET_WriteMD5Sum(packet, data->deh_md5sum); + NET_WriteSHA1Sum(packet, data->wad_sha1sum); + NET_WriteSHA1Sum(packet, data->deh_sha1sum); NET_WriteInt8(packet, data->is_freedoom); } @@ -501,39 +501,59 @@ boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data) strcpy(data->player_addrs[i], s); } - return NET_ReadMD5Sum(packet, data->wad_md5sum) - && NET_ReadMD5Sum(packet, data->deh_md5sum) + return NET_ReadSHA1Sum(packet, data->wad_sha1sum) + && NET_ReadSHA1Sum(packet, data->deh_sha1sum) && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom); } -boolean NET_ReadMD5Sum(net_packet_t *packet, md5_digest_t digest) +static boolean NET_ReadBlob(net_packet_t *packet, uint8_t *buf, size_t len) { unsigned int b; int i; - for (i=0; i<16; ++i) + for (i=0; i<len; ++i) { if (!NET_ReadInt8(packet, &b)) { return false; } - digest[i] = b; + buf[i] = b; } return true; } -void NET_WriteMD5Sum(net_packet_t *packet, md5_digest_t digest) +static void NET_WriteBlob(net_packet_t *packet, uint8_t *buf, size_t len) { int i; - for (i=0; i<16; ++i) + for (i=0; i<len; ++i) { - NET_WriteInt8(packet, digest[i]); + NET_WriteInt8(packet, buf[i]); } } +boolean NET_ReadSHA1Sum(net_packet_t *packet, sha1_digest_t digest) +{ + return NET_ReadBlob(packet, digest, sizeof(sha1_digest_t)); +} + +void NET_WriteSHA1Sum(net_packet_t *packet, sha1_digest_t digest) +{ + NET_WriteBlob(packet, digest, sizeof(sha1_digest_t)); +} + +boolean NET_ReadPRNGSeed(net_packet_t *packet, prng_seed_t seed) +{ + return NET_ReadBlob(packet, seed, sizeof(prng_seed_t)); +} + +void NET_WritePRNGSeed(net_packet_t *packet, prng_seed_t seed) +{ + NET_WriteBlob(packet, seed, sizeof(prng_seed_t)); +} + // "Safe" version of puts, for displaying messages received from the // network. diff --git a/src/net_structrw.h b/src/net_structrw.h index e894e170..3d446841 100644 --- a/src/net_structrw.h +++ b/src/net_structrw.h @@ -22,7 +22,8 @@ #ifndef NET_STRUCTRW_H #define NET_STRUCTRW_H -#include "md5.h" +#include "aes_prng.h" +#include "sha1.h" #include "net_defs.h" #include "net_packet.h" @@ -43,12 +44,15 @@ extern void NET_TiccmdPatch(ticcmd_t *src, net_ticdiff_t *diff, ticcmd_t *dest); boolean NET_ReadFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn); void NET_WriteFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn); -boolean NET_ReadMD5Sum(net_packet_t *packet, md5_digest_t digest); -void NET_WriteMD5Sum(net_packet_t *packet, md5_digest_t digest); +boolean NET_ReadSHA1Sum(net_packet_t *packet, sha1_digest_t digest); +void NET_WriteSHA1Sum(net_packet_t *packet, sha1_digest_t digest); void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data); boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data); void NET_SafePuts(char *msg); +boolean NET_ReadPRNGSeed(net_packet_t *packet, prng_seed_t seed); +void NET_WritePRNGSeed(net_packet_t *packet, prng_seed_t seed); + #endif /* #ifndef NET_STRUCTRW_H */ diff --git a/src/setup/Makefile.am b/src/setup/Makefile.am index 7fe051ee..f58c6294 100644 --- a/src/setup/Makefile.am +++ b/src/setup/Makefile.am @@ -31,7 +31,7 @@ appdir = $(prefix)/share/applications app_DATA = @PROGRAM_PREFIX@setup.desktop @PROGRAM_PREFIX@setup.desktop : setup.desktop - cp $^ $@ + cp setup.desktop $@ if HAVE_PYTHON diff --git a/src/setup/multiplayer.c b/src/setup/multiplayer.c index d9bda1fe..dc0643e3 100644 --- a/src/setup/multiplayer.c +++ b/src/setup/multiplayer.c @@ -978,6 +978,7 @@ void SetChatMacroDefaults(void) int i; char *defaults[] = { + HUSTR_CHATMACRO0, HUSTR_CHATMACRO1, HUSTR_CHATMACRO2, HUSTR_CHATMACRO3, @@ -987,7 +988,6 @@ void SetChatMacroDefaults(void) HUSTR_CHATMACRO7, HUSTR_CHATMACRO8, HUSTR_CHATMACRO9, - HUSTR_CHATMACRO0, }; // If the chat macros have not been set, initialize with defaults. @@ -1001,6 +1001,28 @@ void SetChatMacroDefaults(void) } } +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +char *M_OEMToUTF8(const char *oem) +{ + unsigned int len = strlen(oem) + 1; + wchar_t *tmp; + char *result; + + tmp = malloc(len * sizeof(wchar_t)); + MultiByteToWideChar(CP_OEMCP, 0, oem, len, tmp, len); + result = malloc(len * 4); + WideCharToMultiByte(CP_UTF8, 0, tmp, len, result, len * 4, NULL, NULL); + free(tmp); + + return result; +} + +#endif + void SetPlayerNameDefault(void) { if (net_player_name == NULL) @@ -1013,6 +1035,16 @@ void SetPlayerNameDefault(void) net_player_name = strdup(getenv("USERNAME")); } + // On Windows, environment variables are in OEM codepage + // encoding, so convert to UTF8: + +#ifdef _WIN32 + if (net_player_name != NULL) + { + net_player_name = M_OEMToUTF8(net_player_name); + } +#endif + if (net_player_name == NULL) { net_player_name = strdup("player"); diff --git a/src/sha1.c b/src/sha1.c new file mode 100644 index 00000000..06ab40ad --- /dev/null +++ b/src/sha1.c @@ -0,0 +1,319 @@ +/* sha1.c - SHA1 hash function + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * Please see below for more legal information! + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + + +/* Test vectors: + * + * "abc" + * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D + * + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "i_swap.h" +#include "sha1.h" + +void SHA1_Init(sha1_context_t *hd) +{ + hd->h0 = 0x67452301; + hd->h1 = 0xefcdab89; + hd->h2 = 0x98badcfe; + hd->h3 = 0x10325476; + hd->h4 = 0xc3d2e1f0; + hd->nblocks = 0; + hd->count = 0; +} + + +/**************** + * Transform the message X which consists of 16 32-bit-words + */ +static void Transform(sha1_context_t *hd, byte *data) +{ + uint32_t a,b,c,d,e,tm; + uint32_t x[16]; + + /* get values from the chaining vars */ + a = hd->h0; + b = hd->h1; + c = hd->h2; + d = hd->h3; + e = hd->h4; + +#ifdef SYS_BIG_ENDIAN + memcpy(x, data, 64); +#else + { + int i; + byte *p2; + for(i=0, p2=(byte*)x; i < 16; i++, p2 += 4 ) + { + p2[3] = *data++; + p2[2] = *data++; + p2[1] = *data++; + p2[0] = *data++; + } + } +#endif + + +#define K1 0x5A827999L +#define K2 0x6ED9EBA1L +#define K3 0x8F1BBCDCL +#define K4 0xCA62C1D6L +#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) +#define F2(x,y,z) ( x ^ y ^ z ) +#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) +#define F4(x,y,z) ( x ^ y ^ z ) + +#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) + +#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \ + ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \ + , (x[i&0x0f] = rol(tm,1)) ) + +#define R(a,b,c,d,e,f,k,m) do { e += rol( a, 5 ) \ + + f( b, c, d ) \ + + k \ + + m; \ + b = rol( b, 30 ); \ + } while(0) + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + /* update chainig vars */ + hd->h0 += a; + hd->h1 += b; + hd->h2 += c; + hd->h3 += d; + hd->h4 += e; +} + + +/* Update the message digest with the contents + * of INBUF with length INLEN. + */ +void SHA1_Update(sha1_context_t *hd, byte *inbuf, size_t inlen) +{ + if (hd->count == 64) + { + /* flush the buffer */ + Transform(hd, hd->buf); + hd->count = 0; + hd->nblocks++; + } + if (!inbuf) + return; + if (hd->count) + { + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; + SHA1_Update(hd, NULL, 0); + if (!inlen) + return; + } + + while (inlen >= 64) + { + Transform(hd, inbuf); + hd->count = 0; + hd->nblocks++; + inlen -= 64; + inbuf += 64; + } + for (; inlen && hd->count < 64; inlen--) + hd->buf[hd->count++] = *inbuf++; +} + + +/* The routine final terminates the computation and + * returns the digest. + * The handle is prepared for a new cycle, but adding bytes to the + * handle will the destroy the returned buffer. + * Returns: 20 bytes representing the digest. + */ + +void SHA1_Final(sha1_digest_t digest, sha1_context_t *hd) +{ + uint32_t t, msb, lsb; + byte *p; + + SHA1_Update(hd, NULL, 0); /* flush */; + + t = hd->nblocks; + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = t >> 26; + /* add the count */ + t = lsb; + if ((lsb += hd->count) < t) + msb++; + /* multiply by 8 to make a bit count */ + t = lsb; + lsb <<= 3; + msb <<= 3; + msb |= t >> 29; + + if (hd->count < 56) + { + /* enough room */ + hd->buf[hd->count++] = 0x80; /* pad */ + while (hd->count < 56) + hd->buf[hd->count++] = 0; /* pad */ + } + else + { + /* need one extra block */ + hd->buf[hd->count++] = 0x80; /* pad character */ + while (hd->count < 64) + hd->buf[hd->count++] = 0; + SHA1_Update(hd, NULL, 0); /* flush */; + memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ + } + /* append the 64 bit count */ + hd->buf[56] = msb >> 24; + hd->buf[57] = msb >> 16; + hd->buf[58] = msb >> 8; + hd->buf[59] = msb ; + hd->buf[60] = lsb >> 24; + hd->buf[61] = lsb >> 16; + hd->buf[62] = lsb >> 8; + hd->buf[63] = lsb ; + Transform(hd, hd->buf); + + p = hd->buf; +#ifdef SYS_BIG_ENDIAN +#define X(a) do { *(uint32_t*)p = hd->h##a ; p += 4; } while(0) +#else /* little endian */ +#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \ + *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0) +#endif + X(0); + X(1); + X(2); + X(3); + X(4); +#undef X + + memcpy(digest, hd->buf, sizeof(sha1_digest_t)); +} + +void SHA1_UpdateInt32(sha1_context_t *context, unsigned int val) +{ + byte buf[4]; + + buf[0] = (val >> 24) & 0xff; + buf[1] = (val >> 16) & 0xff; + buf[2] = (val >> 8) & 0xff; + buf[3] = val & 0xff; + + SHA1_Update(context, buf, 4); +} + +void SHA1_UpdateString(sha1_context_t *context, char *str) +{ + SHA1_Update(context, (byte *) str, strlen(str) + 1); +} + diff --git a/src/sha1.h b/src/sha1.h new file mode 100644 index 00000000..a3b86395 --- /dev/null +++ b/src/sha1.h @@ -0,0 +1,48 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2012 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +// DESCRIPTION: +// SHA-1 digest. +// +//----------------------------------------------------------------------------- + +#ifndef __SHA1_H__ +#define __SHA1_H__ + +#include "doomtype.h" + +typedef struct sha1_context_s sha1_context_t; +typedef byte sha1_digest_t[20]; + +struct sha1_context_s { + uint32_t h0,h1,h2,h3,h4; + uint32_t nblocks; + byte buf[64]; + int count; +}; + +void SHA1_Init(sha1_context_t *context); +void SHA1_Update(sha1_context_t *context, byte *buf, size_t len); +void SHA1_Final(sha1_digest_t digest, sha1_context_t *context); +void SHA1_UpdateInt32(sha1_context_t *context, unsigned int val); +void SHA1_UpdateString(sha1_context_t *context, char *str); + +#endif /* #ifndef __SHA1_H__ */ + diff --git a/src/strife/d_net.c b/src/strife/d_net.c index cd0a5e66..a3f5513c 100644 --- a/src/strife/d_net.c +++ b/src/strife/d_net.c @@ -220,8 +220,8 @@ static void SaveGameSettings(net_gamesettings_t *settings, // Read checksums of our WAD directory and dehacked information - W_Checksum(connect_data->wad_md5sum); - DEH_Checksum(connect_data->deh_md5sum); + W_Checksum(connect_data->wad_sha1sum); + DEH_Checksum(connect_data->deh_sha1sum); connect_data->is_freedoom = 0; } diff --git a/src/strife/deh_ammo.c b/src/strife/deh_ammo.c index 2c6a9022..952d8df3 100644 --- a/src/strife/deh_ammo.c +++ b/src/strife/deh_ammo.c @@ -89,14 +89,14 @@ static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_AmmoMD5Hash(md5_context_t *context) +static void DEH_AmmoSHA1Hash(sha1_context_t *context) { int i; for (i=0; i<NUMAMMO; ++i) { - MD5_UpdateInt32(context, clipammo[i]); - MD5_UpdateInt32(context, maxammo[i]); + SHA1_UpdateInt32(context, clipammo[i]); + SHA1_UpdateInt32(context, maxammo[i]); } } @@ -107,6 +107,6 @@ deh_section_t deh_section_ammo = DEH_AmmoStart, DEH_AmmoParseLine, NULL, - DEH_AmmoMD5Hash, + DEH_AmmoSHA1Hash, }; diff --git a/src/strife/deh_frame.c b/src/strife/deh_frame.c index 9383b94f..dc68fde5 100644 --- a/src/strife/deh_frame.c +++ b/src/strife/deh_frame.c @@ -146,13 +146,13 @@ static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_FrameMD5Sum(md5_context_t *context) +static void DEH_FrameSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMSTATES; ++i) { - DEH_StructMD5Sum(context, &state_mapping, &states[i]); + DEH_StructSHA1Sum(context, &state_mapping, &states[i]); } } @@ -163,6 +163,6 @@ deh_section_t deh_section_frame = DEH_FrameStart, DEH_FrameParseLine, NULL, - DEH_FrameMD5Sum, + DEH_FrameSHA1Sum, }; diff --git a/src/strife/deh_misc.c b/src/strife/deh_misc.c index e3f2606c..aaebbadd 100644 --- a/src/strife/deh_misc.c +++ b/src/strife/deh_misc.c @@ -215,13 +215,13 @@ static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag) DEH_Warning(context, "Unknown Misc variable '%s'", variable_name); } -static void DEH_MiscMD5Sum(md5_context_t *context) +static void DEH_MiscSHA1Sum(sha1_context_t *context) { unsigned int i; for (i=0; i<arrlen(misc_settings); ++i) { - MD5_UpdateInt32(context, *misc_settings[i].value); + SHA1_UpdateInt32(context, *misc_settings[i].value); } } @@ -232,6 +232,6 @@ deh_section_t deh_section_misc = DEH_MiscStart, DEH_MiscParseLine, NULL, - DEH_MiscMD5Sum, + DEH_MiscSHA1Sum, }; diff --git a/src/strife/deh_ptr.c b/src/strife/deh_ptr.c index d757a178..0d1764c9 100644 --- a/src/strife/deh_ptr.c +++ b/src/strife/deh_ptr.c @@ -129,13 +129,13 @@ static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag) } } -static void DEH_PointerMD5Sum(md5_context_t *context) +static void DEH_PointerSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMSTATES; ++i) { - MD5_UpdateInt32(context, CodePointerIndex(&states[i].action)); + SHA1_UpdateInt32(context, CodePointerIndex(&states[i].action)); } } @@ -146,6 +146,6 @@ deh_section_t deh_section_pointer = DEH_PointerStart, DEH_PointerParseLine, NULL, - DEH_PointerMD5Sum, + DEH_PointerSHA1Sum, }; diff --git a/src/strife/deh_thing.c b/src/strife/deh_thing.c index 14b23b0a..a1c1f94d 100644 --- a/src/strife/deh_thing.c +++ b/src/strife/deh_thing.c @@ -119,13 +119,13 @@ static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag) DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue); } -static void DEH_ThingMD5Sum(md5_context_t *context) +static void DEH_ThingSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMMOBJTYPES; ++i) { - DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]); + DEH_StructSHA1Sum(context, &thing_mapping, &mobjinfo[i]); } } @@ -136,6 +136,6 @@ deh_section_t deh_section_thing = DEH_ThingStart, DEH_ThingParseLine, NULL, - DEH_ThingMD5Sum, + DEH_ThingSHA1Sum, }; diff --git a/src/strife/deh_weapon.c b/src/strife/deh_weapon.c index 8e89b93e..67cbe5b6 100644 --- a/src/strife/deh_weapon.c +++ b/src/strife/deh_weapon.c @@ -89,13 +89,13 @@ static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag) DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue); } -static void DEH_WeaponMD5Sum(md5_context_t *context) +static void DEH_WeaponSHA1Sum(sha1_context_t *context) { int i; for (i=0; i<NUMWEAPONS ;++i) { - DEH_StructMD5Sum(context, &weapon_mapping, &weaponinfo[i]); + DEH_StructSHA1Sum(context, &weapon_mapping, &weaponinfo[i]); } } @@ -106,6 +106,6 @@ deh_section_t deh_section_weapon = DEH_WeaponStart, DEH_WeaponParseLine, NULL, - DEH_WeaponMD5Sum, + DEH_WeaponSHA1Sum, }; diff --git a/src/w_checksum.c b/src/w_checksum.c index ceda95d8..28451fda 100644 --- a/src/w_checksum.c +++ b/src/w_checksum.c @@ -27,7 +27,7 @@ #include <stdlib.h> #include <string.h> -#include "md5.h" +#include "sha1.h" #include "w_checksum.h" #include "w_wad.h" @@ -60,35 +60,35 @@ static int GetFileNumber(wad_file_t *handle) return result; } -static void ChecksumAddLump(md5_context_t *md5_context, lumpinfo_t *lump) +static void ChecksumAddLump(sha1_context_t *sha1_context, lumpinfo_t *lump) { char buf[9]; strncpy(buf, lump->name, 8); buf[8] = '\0'; - MD5_UpdateString(md5_context, buf); - MD5_UpdateInt32(md5_context, GetFileNumber(lump->wad_file)); - MD5_UpdateInt32(md5_context, lump->position); - MD5_UpdateInt32(md5_context, lump->size); + SHA1_UpdateString(sha1_context, buf); + SHA1_UpdateInt32(sha1_context, GetFileNumber(lump->wad_file)); + SHA1_UpdateInt32(sha1_context, lump->position); + SHA1_UpdateInt32(sha1_context, lump->size); } -void W_Checksum(md5_digest_t digest) +void W_Checksum(sha1_digest_t digest) { - md5_context_t md5_context; + sha1_context_t sha1_context; unsigned int i; - MD5_Init(&md5_context); + SHA1_Init(&sha1_context); num_open_wadfiles = 0; // Go through each entry in the WAD directory, adding information - // about each entry to the MD5 hash. + // about each entry to the SHA1 hash. for (i=0; i<numlumps; ++i) { - ChecksumAddLump(&md5_context, &lumpinfo[i]); + ChecksumAddLump(&sha1_context, &lumpinfo[i]); } - MD5_Final(digest, &md5_context); + SHA1_Final(digest, &sha1_context); } diff --git a/src/w_checksum.h b/src/w_checksum.h index b762e9b6..23bcfefa 100644 --- a/src/w_checksum.h +++ b/src/w_checksum.h @@ -28,7 +28,7 @@ #include "doomtype.h" -extern void W_Checksum(md5_digest_t digest); +extern void W_Checksum(sha1_digest_t digest); #endif /* #ifndef W_CHECKSUM_H */ |