Added system to block malware or illegal plugins (bug 5289, r=dvander).
1.1 --- a/configs/core.cfg Tue Aug 07 18:04:10 2012 +0100
1.2 +++ b/configs/core.cfg Thu Aug 09 01:54:43 2012 +0100
1.3 @@ -115,4 +115,14 @@
1.4 * In general, this option should be set to "yes" to increase the security of your server.
1.5 */
1.6 "SteamAuthstringValidation" "yes"
1.7 +
1.8 + /**
1.9 + * Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
1.10 + * It is STRONGLY advised that this is left enabled, there have been cases in the past with plugins that
1.11 + * allow anyone to delete files on the server, gain full rcon control, etc.
1.12 + *
1.13 + * "yes" - Block malware or illegal plugins from loading (default)
1.14 + * "no" - Warn about malware or illegal plugins loading
1.15 + */
1.16 + "BlockBadPlugins" "yes"
1.17 }
2.1 --- a/core/PluginSys.cpp Tue Aug 07 18:04:10 2012 +0100
2.2 +++ b/core/PluginSys.cpp Thu Aug 09 01:54:43 2012 +0100
2.3 @@ -789,6 +789,8 @@
2.4 m_AllPluginsLoaded = false;
2.5 m_MyIdent = NULL;
2.6 m_LoadingLocked = false;
2.7 +
2.8 + m_bBlockBadPlugins = true;
2.9 }
2.10
2.11 CPluginManager::~CPluginManager()
2.12 @@ -1030,6 +1032,41 @@
2.13 }
2.14 }
2.15 }
2.16 +
2.17 + if (pPlugin->GetStatus() == Plugin_Created)
2.18 + {
2.19 + unsigned char *pCodeHash = pPlugin->m_pRuntime->GetCodeHash();
2.20 +
2.21 + char codeHashBuf[40];
2.22 + UTIL_Format(codeHashBuf, 40, "plugin_");
2.23 + for (int i = 0; i < 16; i++)
2.24 + UTIL_Format(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]);
2.25 +
2.26 + const char *bulletinUrl = g_pGameConf->GetKeyValue(codeHashBuf);
2.27 + if (bulletinUrl != NULL)
2.28 + {
2.29 + if (m_bBlockBadPlugins)
2.30 + {
2.31 + if (error)
2.32 + {
2.33 + if (bulletinUrl[0] != '\0')
2.34 + {
2.35 + UTIL_Format(error, maxlength, "Known malware detected and blocked. See %s for more info", bulletinUrl);
2.36 + } else {
2.37 + UTIL_Format(error, maxlength, "Possible malware or illegal plugin detected and blocked");
2.38 + }
2.39 + }
2.40 + pPlugin->m_status = Plugin_BadLoad;
2.41 + } else {
2.42 + if (bulletinUrl[0] != '\0')
2.43 + {
2.44 + g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
2.45 + } else {
2.46 + g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
2.47 + }
2.48 + }
2.49 + }
2.50 + }
2.51
2.52 LoadRes loadFailure = LoadRes_Failure;
2.53 /* Get the status */
2.54 @@ -1129,7 +1166,7 @@
2.55
2.56 if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
2.57 {
2.58 - g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s", plugin, error);
2.59 + g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error);
2.60 pl->SetErrorState(
2.61 pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(),
2.62 "%s",
2.63 @@ -1889,6 +1926,27 @@
2.64 g_ShareSys.DestroyIdentity(m_MyIdent);
2.65 }
2.66
2.67 +ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key,
2.68 + const char *value,
2.69 + ConfigSource source,
2.70 + char *error,
2.71 + size_t maxlength)
2.72 +{
2.73 + if (strcmp(key, "BlockBadPlugins") == 0) {
2.74 + if (strcasecmp(value, "yes") == 0)
2.75 + {
2.76 + m_bBlockBadPlugins = true;
2.77 + } else if (strcasecmp(value, "no") == 0) {
2.78 + m_bBlockBadPlugins = false;
2.79 + } else {
2.80 + UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
2.81 + return ConfigResult_Reject;
2.82 + }
2.83 + return ConfigResult_Accept;
2.84 + }
2.85 + return ConfigResult_Ignore;
2.86 +}
2.87 +
2.88 void CPluginManager::OnHandleDestroy(HandleType_t type, void *object)
2.89 {
2.90 /* We don't care about the internal object, actually */
2.91 @@ -2269,6 +2327,15 @@
2.92 {
2.93 g_RootMenu.ConsolePrint(" Timestamp: %s", pl->m_DateTime);
2.94 }
2.95 +
2.96 + unsigned char *pCodeHash = pl->m_pRuntime->GetCodeHash();
2.97 + unsigned char *pDataHash = pl->m_pRuntime->GetDataHash();
2.98 +
2.99 + char combinedHash[33];
2.100 + for (int i = 0; i < 16; i++)
2.101 + UTIL_Format(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]);
2.102 +
2.103 + g_RootMenu.ConsolePrint(" Hash: %s", combinedHash);
2.104 }
2.105 else
2.106 {
3.1 --- a/core/PluginSys.h Tue Aug 07 18:04:10 2012 +0100
3.2 +++ b/core/PluginSys.h Thu Aug 09 01:54:43 2012 +0100
3.3 @@ -57,6 +57,7 @@
3.4 #include "convar_sm.h"
3.5 #endif
3.6 #include "ITranslator.h"
3.7 +#include "IGameConfigs.h"
3.8 #include "NativeOwner.h"
3.9 #include "ShareSys.h"
3.10
3.11 @@ -326,6 +327,7 @@
3.12 public: //SMGlobalClass
3.13 void OnSourceModAllInitialized();
3.14 void OnSourceModShutdown();
3.15 + ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
3.16 void OnSourceModMaxPlayersChanged(int newvalue);
3.17 public: //IHandleTypeDispatch
3.18 void OnHandleDestroy(HandleType_t type, void *object);
3.19 @@ -470,6 +472,9 @@
3.20 List<FakeNative *> m_Natives;
3.21
3.22 bool m_LoadingLocked;
3.23 +
3.24 + // Config
3.25 + bool m_bBlockBadPlugins;
3.26 };
3.27
3.28 extern CPluginManager g_PluginSys;
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/gamedata/core.games/blacklist.plugins.txt Thu Aug 09 01:54:43 2012 +0100
4.3 @@ -0,0 +1,16 @@
4.4 +/**
4.5 + * Do not edit this file. Any changes will be overwritten by the gamedata
4.6 + * updater or by upgrading your SourceMod install.
4.7 + *
4.8 + * For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(SourceMod)
4.9 + */
4.10 +
4.11 +"Games"
4.12 +{
4.13 + "#default"
4.14 + {
4.15 + "Keys"
4.16 + {
4.17 + }
4.18 + }
4.19 +}
5.1 --- a/gamedata/core.games/master.games.txt Tue Aug 07 18:04:10 2012 +0100
5.2 +++ b/gamedata/core.games/master.games.txt Thu Aug 09 01:54:43 2012 +0100
5.3 @@ -65,4 +65,7 @@
5.4 "engine" "csgo"
5.5 }
5.6
5.7 + "blacklist.plugins.txt"
5.8 + {
5.9 + }
5.10 }
6.1 --- a/public/sourcepawn/sp_vm_api.h Tue Aug 07 18:04:10 2012 +0100
6.2 +++ b/public/sourcepawn/sp_vm_api.h Thu Aug 09 01:54:43 2012 +0100
6.3 @@ -40,7 +40,7 @@
6.4
6.5 /** SourcePawn Engine API Version */
6.6 #define SOURCEPAWN_ENGINE_API_VERSION 4
6.7 -#define SOURCEPAWN_ENGINE2_API_VERSION 3
6.8 +#define SOURCEPAWN_ENGINE2_API_VERSION 4
6.9
6.10 #if !defined SOURCEMOD_BUILD
6.11 #define SOURCEMOD_BUILD
6.12 @@ -479,6 +479,20 @@
6.13 * @return Memory usage, in bytes.
6.14 */
6.15 virtual size_t GetMemUsage() =0;
6.16 +
6.17 + /**
6.18 + * @brief Returns the MD5 hash of the plugin's P-Code.
6.19 + *
6.20 + * @return 16-byte buffer with MD5 hash of the plugin's P-Code.
6.21 + */
6.22 + virtual unsigned char *GetCodeHash() =0;
6.23 +
6.24 + /**
6.25 + * @brief Returns the MD5 hash of the plugin's Data.
6.26 + *
6.27 + * @return 16-byte buffer with MD5 hash of the plugin's Data.
6.28 + */
6.29 + virtual unsigned char *GetDataHash() =0;
6.30 };
6.31
6.32 /**
7.1 --- a/sourcepawn/jit/AMBuilder Tue Aug 07 18:04:10 2012 +0100
7.2 +++ b/sourcepawn/jit/AMBuilder Thu Aug 09 01:54:43 2012 +0100
7.3 @@ -36,6 +36,7 @@
7.4 'zlib/trees.c',
7.5 'zlib/uncompr.c',
7.6 'zlib/zutil.c',
7.7 + 'md5/md5.cpp',
7.8 '../../knight/shared/KeCodeAllocator.cpp'
7.9 ])
7.10 SM.AutoVersion('sourcepawn/jit', binary)
8.1 --- a/sourcepawn/jit/BaseRuntime.cpp Tue Aug 07 18:04:10 2012 +0100
8.2 +++ b/sourcepawn/jit/BaseRuntime.cpp Thu Aug 09 01:54:43 2012 +0100
8.3 @@ -8,6 +8,8 @@
8.4 #include "sp_vm_basecontext.h"
8.5 #include "engine2.h"
8.6
8.7 +#include "md5/md5.h"
8.8 +
8.9 using namespace SourcePawn;
8.10
8.11 BaseRuntime::BaseRuntime() : m_Debug(&m_plugin), m_pPlugin(&m_plugin), m_pCtx(NULL),
8.12 @@ -18,6 +20,9 @@
8.13 m_FuncCache = NULL;
8.14 m_MaxFuncs = 0;
8.15 m_NumFuncs = 0;
8.16 +
8.17 + memset(m_CodeHash, 0, sizeof(m_CodeHash));
8.18 + memset(m_DataHash, 0, sizeof(m_DataHash));
8.19 }
8.20
8.21 BaseRuntime::~BaseRuntime()
8.22 @@ -227,6 +232,16 @@
8.23 memset(m_PubJitFuncs, 0, sizeof(JitFunction *) * m_pPlugin->num_publics);
8.24 }
8.25
8.26 + MD5 md5_pcode;
8.27 + md5_pcode.update(plugin->pcode, plugin->pcode_size);
8.28 + md5_pcode.finalize();
8.29 + md5_pcode.raw_digest(m_CodeHash);
8.30 +
8.31 + MD5 md5_data;
8.32 + md5_data.update(plugin->data, plugin->data_size);
8.33 + md5_data.finalize();
8.34 + md5_data.raw_digest(m_DataHash);
8.35 +
8.36 m_pPlugin->profiler = g_engine2.GetProfiler();
8.37 m_pCtx = new BaseContext(this);
8.38 m_pCo = g_Jit.StartCompilation(this);
8.39 @@ -483,6 +498,16 @@
8.40 return mem;
8.41 }
8.42
8.43 +unsigned char *BaseRuntime::GetCodeHash()
8.44 +{
8.45 + return m_CodeHash;
8.46 +}
8.47 +
8.48 +unsigned char *BaseRuntime::GetDataHash()
8.49 +{
8.50 + return m_DataHash;
8.51 +}
8.52 +
8.53 BaseContext *BaseRuntime::GetBaseContext()
8.54 {
8.55 return m_pCtx;
9.1 --- a/sourcepawn/jit/BaseRuntime.h Tue Aug 07 18:04:10 2012 +0100
9.2 +++ b/sourcepawn/jit/BaseRuntime.h Thu Aug 09 01:54:43 2012 +0100
9.3 @@ -48,6 +48,8 @@
9.4 virtual void SetPauseState(bool paused);
9.5 virtual bool IsPaused();
9.6 virtual size_t GetMemUsage();
9.7 + virtual unsigned char *GetCodeHash();
9.8 + virtual unsigned char *GetDataHash();
9.9 JitFunction *GetJittedFunction(uint32_t idx);
9.10 uint32_t AddJittedFunction(JitFunction *fn);
9.11 public:
9.12 @@ -65,6 +67,9 @@
9.13 JitFunction **m_PubJitFuncs;
9.14 ICompilation *m_pCo;
9.15 unsigned int m_CompSerial;
9.16 +
9.17 + unsigned char m_CodeHash[16];
9.18 + unsigned char m_DataHash[16];
9.19 };
9.20
9.21 #endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/sourcepawn/jit/md5/md5.cpp Thu Aug 09 01:54:43 2012 +0100
10.3 @@ -0,0 +1,476 @@
10.4 +// MD5.CC - source code for the C++/object oriented translation and
10.5 +// modification of MD5.
10.6 +
10.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug
10.8 +
10.9 +// This translation/ modification is provided "as is," without express or
10.10 +// implied warranty of any kind.
10.11 +
10.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think
10.13 +// it does; (2) that this translation/ modification is accurate; or (3) that
10.14 +// this software is "merchantible." (Language for this disclaimer partially
10.15 +// copied from the disclaimer below).
10.16 +
10.17 +/* based on:
10.18 +
10.19 + MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
10.20 + MDDRIVER.C - test driver for MD2, MD4 and MD5
10.21 +
10.22 +
10.23 + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
10.24 +rights reserved.
10.25 +
10.26 +License to copy and use this software is granted provided that it
10.27 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
10.28 +Algorithm" in all material mentioning or referencing this software
10.29 +or this function.
10.30 +
10.31 +License is also granted to make and use derivative works provided
10.32 +that such works are identified as "derived from the RSA Data
10.33 +Security, Inc. MD5 Message-Digest Algorithm" in all material
10.34 +mentioning or referencing the derived work.
10.35 +
10.36 +RSA Data Security, Inc. makes no representations concerning either
10.37 +the merchantability of this software or the suitability of this
10.38 +software for any particular purpose. It is provided "as is"
10.39 +without express or implied warranty of any kind.
10.40 +
10.41 +These notices must be retained in any copies of any part of this
10.42 +documentation and/or software.
10.43 +
10.44 + */
10.45 +
10.46 +#include "md5.h"
10.47 +
10.48 +#include <assert.h>
10.49 +#include <string.h>
10.50 +
10.51 +// MD5 simple initialization method
10.52 +
10.53 +MD5::MD5(){
10.54 +
10.55 + init();
10.56 +
10.57 +}
10.58 +
10.59 +
10.60 +// MD5 block update operation. Continues an MD5 message-digest
10.61 +// operation, processing another message block, and updating the
10.62 +// context.
10.63 +
10.64 +void MD5::update (uint1 *input, uint4 input_length) {
10.65 +
10.66 + uint4 input_index, buffer_index;
10.67 + uint4 buffer_space; // how much space is left in buffer
10.68 +
10.69 + if (finalized){ // so we can't update!
10.70 + /*cerr << "MD5::update: Can't update a finalized digest!" << endl;*/
10.71 + return;
10.72 + }
10.73 +
10.74 + // Compute number of bytes mod 64
10.75 + buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
10.76 +
10.77 + // Update number of bits
10.78 + if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
10.79 + count[1]++;
10.80 +
10.81 + count[1] += ((uint4)input_length >> 29);
10.82 +
10.83 +
10.84 + buffer_space = 64 - buffer_index; // how much space is left in buffer
10.85 +
10.86 + // Transform as many times as possible.
10.87 + if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
10.88 + // fill the rest of the buffer and transform
10.89 + memcpy (buffer + buffer_index, input, buffer_space);
10.90 + transform (buffer);
10.91 +
10.92 + // now, transform each 64-byte piece of the input, bypassing the buffer
10.93 + for (input_index = buffer_space; input_index + 63 < input_length;
10.94 + input_index += 64)
10.95 + transform (input+input_index);
10.96 +
10.97 + buffer_index = 0; // so we can buffer remaining
10.98 + }
10.99 + else
10.100 + input_index=0; // so we can buffer the whole input
10.101 +
10.102 +
10.103 + // and here we do the buffering:
10.104 + memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
10.105 +}
10.106 +
10.107 +
10.108 +
10.109 +// MD5 update for files.
10.110 +// Like above, except that it works on files (and uses above as a primitive.)
10.111 +
10.112 +void MD5::update(FILE *file){
10.113 +
10.114 + unsigned char buffer[1024];
10.115 + int len;
10.116 +
10.117 + while ((len=fread(buffer, 1, 1024, file)))
10.118 + update(buffer, len);
10.119 +
10.120 + fclose (file);
10.121 +
10.122 +}
10.123 +
10.124 +
10.125 +// MD5 finalization. Ends an MD5 message-digest operation, writing the
10.126 +// the message digest and zeroizing the context.
10.127 +
10.128 +
10.129 +void MD5::finalize (){
10.130 +
10.131 + unsigned char bits[8];
10.132 + unsigned int index, padLen;
10.133 + static uint1 PADDING[64]={
10.134 + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10.135 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10.136 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
10.137 + };
10.138 +
10.139 + if (finalized){
10.140 + /* cerr << "MD5::finalize: Already finalized this digest!" << endl;*/
10.141 + return;
10.142 + }
10.143 +
10.144 + // Save number of bits
10.145 + encode (bits, count, 8);
10.146 +
10.147 + // Pad out to 56 mod 64.
10.148 + index = (uint4) ((count[0] >> 3) & 0x3f);
10.149 + padLen = (index < 56) ? (56 - index) : (120 - index);
10.150 + update (PADDING, padLen);
10.151 +
10.152 + // Append length (before padding)
10.153 + update (bits, 8);
10.154 +
10.155 + // Store state in digest
10.156 + encode (digest, state, 16);
10.157 +
10.158 + // Zeroize sensitive information
10.159 + memset (buffer, 0, sizeof(*buffer));
10.160 +
10.161 + finalized=1;
10.162 +
10.163 +}
10.164 +
10.165 +
10.166 +
10.167 +
10.168 +MD5::MD5(FILE *file){
10.169 +
10.170 + init(); // must be called be all constructors
10.171 + update(file);
10.172 + finalize ();
10.173 +}
10.174 +
10.175 +unsigned char *MD5::raw_digest(){
10.176 +
10.177 + uint1 *s = new uint1[16];
10.178 +
10.179 + if (!finalized){
10.180 +/* cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
10.181 + "finalized the digest!" <<endl;*/
10.182 + return ( (unsigned char*) "");
10.183 + }
10.184 +
10.185 + memcpy(s, digest, 16);
10.186 + return s;
10.187 +}
10.188 +
10.189 +unsigned char *MD5::raw_digest(unsigned char buffer[16])
10.190 +{
10.191 + if (!finalized)
10.192 + {
10.193 + return ( (unsigned char*) "");
10.194 + }
10.195 +
10.196 + memcpy(buffer, digest, 16);
10.197 + return buffer;
10.198 +}
10.199 +
10.200 +
10.201 +
10.202 +char *MD5::hex_digest(){
10.203 +
10.204 + int i;
10.205 + char *s= new char[33];
10.206 +
10.207 + assert(finalized);
10.208 +
10.209 + for (i=0; i<16; i++)
10.210 + sprintf(s+i*2, "%02x", digest[i]);
10.211 +
10.212 + s[32]='\0';
10.213 +
10.214 + return s;
10.215 +}
10.216 +
10.217 +
10.218 +char *MD5::hex_digest(char buffer[33]){
10.219 +
10.220 + int i;
10.221 +
10.222 + assert(finalized);
10.223 +
10.224 + for (i=0; i<16; i++)
10.225 + sprintf(buffer+i*2, "%02x", digest[i]);
10.226 +
10.227 + buffer[32]='\0';
10.228 +
10.229 + return buffer;
10.230 +}
10.231 +
10.232 +
10.233 +// PRIVATE METHODS:
10.234 +
10.235 +
10.236 +
10.237 +void MD5::init(){
10.238 + finalized=0; // we just started!
10.239 +
10.240 + // Nothing counted, so count=0
10.241 + count[0] = 0;
10.242 + count[1] = 0;
10.243 +
10.244 + // Load magic initialization constants.
10.245 + state[0] = 0x67452301;
10.246 + state[1] = 0xefcdab89;
10.247 + state[2] = 0x98badcfe;
10.248 + state[3] = 0x10325476;
10.249 +}
10.250 +
10.251 +
10.252 +
10.253 +// Constants for MD5Transform routine.
10.254 +// Although we could use C++ style constants, defines are actually better,
10.255 +// since they let us easily evade scope clashes.
10.256 +
10.257 +#define S11 7
10.258 +#define S12 12
10.259 +#define S13 17
10.260 +#define S14 22
10.261 +#define S21 5
10.262 +#define S22 9
10.263 +#define S23 14
10.264 +#define S24 20
10.265 +#define S31 4
10.266 +#define S32 11
10.267 +#define S33 16
10.268 +#define S34 23
10.269 +#define S41 6
10.270 +#define S42 10
10.271 +#define S43 15
10.272 +#define S44 21
10.273 +
10.274 +
10.275 +
10.276 +
10.277 +// MD5 basic transformation. Transforms state based on block.
10.278 +void MD5::transform (uint1 block[64]){
10.279 +
10.280 + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
10.281 +
10.282 + decode (x, block, 64);
10.283 +
10.284 + assert(!finalized); // not just a user error, since the method is private
10.285 +
10.286 + /* Round 1 */
10.287 + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
10.288 + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
10.289 + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
10.290 + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
10.291 + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
10.292 + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
10.293 + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
10.294 + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
10.295 + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
10.296 + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
10.297 + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
10.298 + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
10.299 + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
10.300 + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
10.301 + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
10.302 + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
10.303 +
10.304 + /* Round 2 */
10.305 + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
10.306 + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
10.307 + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
10.308 + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
10.309 + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
10.310 + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
10.311 + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
10.312 + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
10.313 + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
10.314 + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
10.315 + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
10.316 + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
10.317 + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
10.318 + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
10.319 + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
10.320 + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
10.321 +
10.322 + /* Round 3 */
10.323 + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
10.324 + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
10.325 + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
10.326 + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
10.327 + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
10.328 + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
10.329 + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
10.330 + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
10.331 + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
10.332 + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
10.333 + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
10.334 + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
10.335 + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
10.336 + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
10.337 + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
10.338 + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
10.339 +
10.340 + /* Round 4 */
10.341 + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
10.342 + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
10.343 + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
10.344 + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
10.345 + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
10.346 + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
10.347 + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
10.348 + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
10.349 + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
10.350 + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
10.351 + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
10.352 + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
10.353 + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
10.354 + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
10.355 + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
10.356 + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
10.357 +
10.358 + state[0] += a;
10.359 + state[1] += b;
10.360 + state[2] += c;
10.361 + state[3] += d;
10.362 +
10.363 + // Zeroize sensitive information.
10.364 + memset ( (uint1 *) x, 0, sizeof(x));
10.365 +
10.366 +}
10.367 +
10.368 +
10.369 +
10.370 +// Encodes input (UINT4) into output (unsigned char). Assumes len is
10.371 +// a multiple of 4.
10.372 +void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
10.373 +
10.374 + unsigned int i, j;
10.375 +
10.376 + for (i = 0, j = 0; j < len; i++, j += 4) {
10.377 + output[j] = (uint1) (input[i] & 0xff);
10.378 + output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
10.379 + output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
10.380 + output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
10.381 + }
10.382 +}
10.383 +
10.384 +
10.385 +
10.386 +
10.387 +// Decodes input (unsigned char) into output (UINT4). Assumes len is
10.388 +// a multiple of 4.
10.389 +void MD5::decode (uint4 *output, uint1 *input, uint4 len){
10.390 +
10.391 + unsigned int i, j;
10.392 +
10.393 + for (i = 0, j = 0; j < len; i++, j += 4)
10.394 + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
10.395 + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
10.396 +}
10.397 +
10.398 +
10.399 +
10.400 +
10.401 +
10.402 +// Note: Replace "for loop" with standard memcpy if possible.
10.403 +void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){
10.404 +
10.405 + unsigned int i;
10.406 +
10.407 + for (i = 0; i < len; i++)
10.408 + output[i] = input[i];
10.409 +}
10.410 +
10.411 +
10.412 +
10.413 +// Note: Replace "for loop" with standard memset if possible.
10.414 +void MD5::memset (uint1 *output, uint1 value, uint4 len){
10.415 +
10.416 + unsigned int i;
10.417 +
10.418 + for (i = 0; i < len; i++)
10.419 + output[i] = value;
10.420 +}
10.421 +
10.422 +
10.423 +
10.424 +// ROTATE_LEFT rotates x left n bits.
10.425 +
10.426 +inline unsigned int MD5::rotate_left (uint4 x, uint4 n){
10.427 + return (x << n) | (x >> (32-n)) ;
10.428 +}
10.429 +
10.430 +
10.431 +
10.432 +
10.433 +// F, G, H and I are basic MD5 functions.
10.434 +
10.435 +inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
10.436 + return (x & y) | (~x & z);
10.437 +}
10.438 +
10.439 +inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
10.440 + return (x & z) | (y & ~z);
10.441 +}
10.442 +
10.443 +inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
10.444 + return x ^ y ^ z;
10.445 +}
10.446 +
10.447 +inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){
10.448 + return y ^ (x | ~z);
10.449 +}
10.450 +
10.451 +
10.452 +
10.453 +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
10.454 +// Rotation is separate from addition to prevent recomputation.
10.455 +
10.456 +
10.457 +inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
10.458 + uint4 s, uint4 ac){
10.459 + a += F(b, c, d) + x + ac;
10.460 + a = rotate_left (a, s) +b;
10.461 +}
10.462 +
10.463 +inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
10.464 + uint4 s, uint4 ac){
10.465 + a += G(b, c, d) + x + ac;
10.466 + a = rotate_left (a, s) +b;
10.467 +}
10.468 +
10.469 +inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
10.470 + uint4 s, uint4 ac){
10.471 + a += H(b, c, d) + x + ac;
10.472 + a = rotate_left (a, s) +b;
10.473 +}
10.474 +
10.475 +inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
10.476 + uint4 s, uint4 ac){
10.477 + a += I(b, c, d) + x + ac;
10.478 + a = rotate_left (a, s) +b;
10.479 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/sourcepawn/jit/md5/md5.h Thu Aug 09 01:54:43 2012 +0100
11.3 @@ -0,0 +1,106 @@
11.4 +// MD5.CC - source code for the C++/object oriented translation and
11.5 +// modification of MD5.
11.6 +
11.7 +// Translation and modification (c) 1995 by Mordechai T. Abzug
11.8 +
11.9 +// This translation/ modification is provided "as is," without express or
11.10 +// implied warranty of any kind.
11.11 +
11.12 +// The translator/ modifier does not claim (1) that MD5 will do what you think
11.13 +// it does; (2) that this translation/ modification is accurate; or (3) that
11.14 +// this software is "merchantible." (Language for this disclaimer partially
11.15 +// copied from the disclaimer below).
11.16 +
11.17 +/* based on:
11.18 +
11.19 + MD5.H - header file for MD5C.C
11.20 + MDDRIVER.C - test driver for MD2, MD4 and MD5
11.21 +
11.22 + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11.23 +rights reserved.
11.24 +
11.25 +License to copy and use this software is granted provided that it
11.26 +is identified as the "RSA Data Security, Inc. MD5 Message-Digest
11.27 +Algorithm" in all material mentioning or referencing this software
11.28 +or this function.
11.29 +
11.30 +License is also granted to make and use derivative works provided
11.31 +that such works are identified as "derived from the RSA Data
11.32 +Security, Inc. MD5 Message-Digest Algorithm" in all material
11.33 +mentioning or referencing the derived work.
11.34 +
11.35 +RSA Data Security, Inc. makes no representations concerning either
11.36 +the merchantability of this software or the suitability of this
11.37 +software for any particular purpose. It is provided "as is"
11.38 +without express or implied warranty of any kind.
11.39 +
11.40 +These notices must be retained in any copies of any part of this
11.41 +documentation and/or software.
11.42 +
11.43 +*/
11.44 +
11.45 +#include <stdio.h>
11.46 +//#include <fstream.h>
11.47 +//#include <iostream.h>
11.48 +
11.49 +class MD5 {
11.50 +
11.51 +public:
11.52 +// methods for controlled operation:
11.53 + MD5 (); // simple initializer
11.54 + void update (unsigned char *input, unsigned int input_length);
11.55 + void update (FILE *file);
11.56 + void finalize ();
11.57 +
11.58 +// constructors for special circumstances. All these constructors finalize
11.59 +// the MD5 context.
11.60 + MD5 (unsigned char *string); // digest string, finalize
11.61 + MD5 (FILE *file); // digest file, close, finalize
11.62 +
11.63 +// methods to acquire finalized result
11.64 + unsigned char *raw_digest (); // digest as a 16-byte binary array
11.65 + unsigned char *raw_digest(unsigned char buffer[16]);
11.66 + char * hex_digest (); // digest as a 33-byte ascii-hex string
11.67 + char * hex_digest (char buffer[33]); //same as above, passing buffer
11.68 +
11.69 +
11.70 +
11.71 +private:
11.72 +
11.73 +// first, some types:
11.74 + typedef unsigned int uint4; // assumes integer is 4 words long
11.75 + typedef unsigned short int uint2; // assumes short integer is 2 words long
11.76 + typedef unsigned char uint1; // assumes char is 1 word long
11.77 +
11.78 +// next, the private data:
11.79 + uint4 state[4];
11.80 + uint4 count[2]; // number of *bits*, mod 2^64
11.81 + uint1 buffer[64]; // input buffer
11.82 + uint1 digest[16];
11.83 + uint1 finalized;
11.84 +
11.85 +// last, the private methods, mostly static:
11.86 + void init (); // called by all constructors
11.87 + void transform (uint1 *buffer); // does the real update work. Note
11.88 + // that length is implied to be 64.
11.89 +
11.90 + static void encode (uint1 *dest, uint4 *src, uint4 length);
11.91 + static void decode (uint4 *dest, uint1 *src, uint4 length);
11.92 + static void memcpy (uint1 *dest, uint1 *src, uint4 length);
11.93 + static void memset (uint1 *start, uint1 val, uint4 length);
11.94 +
11.95 + static inline uint4 rotate_left (uint4 x, uint4 n);
11.96 + static inline uint4 F (uint4 x, uint4 y, uint4 z);
11.97 + static inline uint4 G (uint4 x, uint4 y, uint4 z);
11.98 + static inline uint4 H (uint4 x, uint4 y, uint4 z);
11.99 + static inline uint4 I (uint4 x, uint4 y, uint4 z);
11.100 + static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
11.101 + uint4 s, uint4 ac);
11.102 + static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
11.103 + uint4 s, uint4 ac);
11.104 + static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
11.105 + uint4 s, uint4 ac);
11.106 + static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
11.107 + uint4 s, uint4 ac);
11.108 +
11.109 +};