diff --git a/build/premake/extern_libs4.lua b/build/premake/extern_libs4.lua index 7ec313099a..ca83a6b492 100644 --- a/build/premake/extern_libs4.lua +++ b/build/premake/extern_libs4.lua @@ -444,6 +444,22 @@ extern_lib_defs = { }) end, }, + libsodium = { + compile_settings = function() + if os.is("windows") or os.is("macosx") then + add_default_include_paths("libsodium") + end + end, + link_settings = function() + if os.is("windows") or os.is("macosx") then + add_default_lib_paths("libsodium") + end + add_default_links({ + win_names = { "libsodium" }, + unix_names = { "sodium" }, + }) + end, + }, libxml2 = { compile_settings = function() if os.is("windows") then diff --git a/build/premake/extern_libs5.lua b/build/premake/extern_libs5.lua index bf87dc1a0a..54924e4516 100644 --- a/build/premake/extern_libs5.lua +++ b/build/premake/extern_libs5.lua @@ -393,6 +393,22 @@ extern_lib_defs = { }) end, }, + libsodium = { + compile_settings = function() + if os.istarget("windows") or os.istarget("macosx") then + add_default_include_paths("libsodium") + end + end, + link_settings = function() + if os.istarget("windows") or os.istarget("macosx") then + add_default_lib_paths("libsodium") + end + add_default_links({ + win_names = { "libsodium" }, + unix_names = { "sodium" }, + }) + end, + }, libxml2 = { compile_settings = function() if os.istarget("windows") then diff --git a/build/premake/premake4.lua b/build/premake/premake4.lua index 73c45dc824..1073f0d1d0 100644 --- a/build/premake/premake4.lua +++ b/build/premake/premake4.lua @@ -627,6 +627,7 @@ function setup_all_libs () "gloox", "icu", "iconv", + "libsodium", "tinygettext" } setup_static_lib_project("lobby", source_dirs, extern_libs, {}) @@ -655,7 +656,8 @@ function setup_all_libs () } extern_libs = { "spidermonkey", - "boost" + "boost", + "libsodium" } setup_static_lib_project("lobby", source_dirs, extern_libs, {}) files { source_root.."lobby/Globals.cpp" } @@ -904,6 +906,7 @@ used_extern_libs = { "tinygettext", "icu", "iconv", + "libsodium", "valgrind", } diff --git a/build/premake/premake5.lua b/build/premake/premake5.lua index 221317b65c..64aa464351 100644 --- a/build/premake/premake5.lua +++ b/build/premake/premake5.lua @@ -627,6 +627,7 @@ function setup_all_libs () "gloox", "icu", "iconv", + "libsodium", "tinygettext" } setup_static_lib_project("lobby", source_dirs, extern_libs, {}) @@ -655,7 +656,8 @@ function setup_all_libs () } extern_libs = { "spidermonkey", - "boost" + "boost", + "libsodium" } setup_static_lib_project("lobby", source_dirs, extern_libs, {}) files { source_root.."lobby/Globals.cpp" } @@ -912,6 +914,7 @@ used_extern_libs = { "tinygettext", "icu", "iconv", + "libsodium", "valgrind", } diff --git a/libraries/osx/build-osx-libs.sh b/libraries/osx/build-osx-libs.sh index 093ce2bfd0..f160b32b2d 100755 --- a/libraries/osx/build-osx-libs.sh +++ b/libraries/osx/build-osx-libs.sh @@ -42,6 +42,7 @@ NSPR_VERSION="4.15" ICU_VERSION="icu4c-59_1" ENET_VERSION="enet-1.3.13" MINIUPNPC_VERSION="miniupnpc-2.0.20180222" +SODIUM_VERSION="libsodium-1.0.16" # -------------------------------------------------------------- # Bundled with the game: # * SpiderMonkey 38 @@ -621,6 +622,36 @@ else fi popd > /dev/null +# -------------------------------------------------------------- +echo -e "Building libsodium..." + +LIB_VERSION="${SODIUM_VERSION}" +LIB_ARCHIVE="$SODIUM_VERSION.tar.gz" +LIB_DIRECTORY="$LIB_VERSION" +LIB_URL="https://download.libsodium.org/libsodium/releases/" + +mkdir -p libsodium +pushd libsodium > /dev/null + +if [[ "$force_rebuild" = "true" ]] || [[ ! -e .already-built ]] || [[ .already-built -ot $LIB_DIRECTORY ]] +then + INSTALL_DIR="$(pwd)" + + rm -f .already-built + download_lib $LIB_URL $LIB_ARCHIVE + + rm -rf $LIB_DIRECTORY include lib + tar -xf $LIB_ARCHIVE + pushd $LIB_DIRECTORY + + (./configure CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" --prefix=${INSTALL_DIR} && make clean && CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS make ${JOBS} && make check && INSTALLPREFIX="$INSTALL_DIR" make install) || die "libsodium build failed" + popd + touch .already-built +else + already_built +fi +popd > /dev/null + # -------------------------------------------------------------------- # The following libraries are shared on different OSes and may # be customized, so we build and install them from bundled sources diff --git a/source/lobby/scripting/JSInterface_Lobby.cpp b/source/lobby/scripting/JSInterface_Lobby.cpp index df9c6d2c9c..ee21b4d812 100644 --- a/source/lobby/scripting/JSInterface_Lobby.cpp +++ b/source/lobby/scripting/JSInterface_Lobby.cpp @@ -24,8 +24,8 @@ #include "lobby/IXmppClient.h" #include "ps/Profile.h" #include "scriptinterface/ScriptInterface.h" + #include "third_party/encryption/pkcs5_pbkdf2.h" -#include "third_party/encryption/sha.h" void JSI_Lobby::RegisterScriptFunctions(const ScriptInterface& scriptInterface) { @@ -320,21 +320,39 @@ std::wstring JSI_Lobby::LobbyGetPlayerRole(ScriptInterface::CxPrivate* UNUSED(pC } // Non-public secure PBKDF2 hash function with salting and 1,337 iterations +// +// TODO: We should use libsodium's crypto_pwhash instead of this. The first reason is that +// libsodium doesn't propose a bare PBKDF2 hash in its API and it's too bad to rely on custom +// code when we have a fully-fledged library available; the second reason is that Argon2 (the +// default algorithm for crypto_pwhash) is better than what we use (and it's the default one +// in the lib for a reason). +// However changing the hashing method should be planned carefully, by trying to login with a +// password hashed the old way, and, if successful, updating the password in the database using +// the new hashing method. Dropping the old hashing code can only be done either by giving users +// a way to reset their password, or by keeping track of successful password updates and dropping +// old unused accounts after some time. std::string JSI_Lobby::EncryptPassword(const std::string& password, const std::string& username) { - const int DIGESTSIZE = SHA_DIGEST_SIZE; + ENSURE(sodium_init() >= 0); + + const int DIGESTSIZE = crypto_hash_sha256_BYTES; const int ITERATIONS = 1337; + cassert(DIGESTSIZE == 32); + static const unsigned char salt_base[DIGESTSIZE] = { 244, 243, 249, 244, 32, 33, 34, 35, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 32, 33, 244, 224, 127, 129, 130, 140, 153, 133, 123, 234, 123 }; // initialize the salt buffer unsigned char salt_buffer[DIGESTSIZE] = {0}; - SHA256 hash; - hash.update(salt_base, sizeof(salt_base)); - hash.update(username.c_str(), username.length()); - hash.finish(salt_buffer); + crypto_hash_sha256_state state; + crypto_hash_sha256_init(&state); + + crypto_hash_sha256_update(&state, salt_base, sizeof(salt_base)); + crypto_hash_sha256_update(&state, (unsigned char*)username.c_str(), username.length()); + + crypto_hash_sha256_final(&state, salt_buffer); // PBKDF2 to create the buffer unsigned char encrypted[DIGESTSIZE]; diff --git a/source/third_party/encryption/pkcs5_pbkdf2.cpp b/source/third_party/encryption/pkcs5_pbkdf2.cpp index 6851eb9559..e321a06dae 100644 --- a/source/third_party/encryption/pkcs5_pbkdf2.cpp +++ b/source/third_party/encryption/pkcs5_pbkdf2.cpp @@ -18,60 +18,62 @@ #include "precompiled.h" #include "pkcs5_pbkdf2.h" -#include "sha.h" -static void hmac_sha256(unsigned char (&digest)[SHA_DIGEST_SIZE], +// This does not match libsodium crypto_auth_hmacsha256, which has a constant key_len. +static void hmac_sha256(unsigned char (&digest)[crypto_hash_sha256_BYTES], const unsigned char* text, size_t text_len, const unsigned char* key, size_t key_len) { - SHA256 hash; - unsigned char tk[SHA_DIGEST_SIZE]; // temporary key incase we need to pad the key with zero unsigned chars - if (key_len > SHA_DIGEST_SIZE) + crypto_hash_sha256_state state; + crypto_hash_sha256_init(&state); + + unsigned char tk[crypto_hash_sha256_BYTES]; // temporary key in case we need to pad the key with zero unsigned chars + if (key_len > crypto_hash_sha256_BYTES) { - hash.update(key, key_len); - hash.finish(tk); + crypto_hash_sha256_update(&state, key, key_len); + crypto_hash_sha256_final(&state, tk); key = tk; - key_len = SHA_DIGEST_SIZE; + key_len = crypto_hash_sha256_BYTES; } - - unsigned char k_pad[SHA_DIGEST_SIZE]; - + + unsigned char k_pad[crypto_hash_sha256_BYTES]; + memset(k_pad, 0, sizeof k_pad); memcpy(k_pad, key, key_len); - for (int i = 0; i < SHA_DIGEST_SIZE; ++i) + for (unsigned int i = 0; i < crypto_hash_sha256_BYTES; ++i) k_pad[i] ^= 0x36; - hash.init(); - hash.update(k_pad, SHA_DIGEST_SIZE); - hash.update(text, text_len); - hash.finish(digest); - - + crypto_hash_sha256_init(&state); + crypto_hash_sha256_update(&state, k_pad, crypto_hash_sha256_BYTES); + crypto_hash_sha256_update(&state, text, text_len); + crypto_hash_sha256_final(&state, digest); + + memset(k_pad, 0, sizeof k_pad); memcpy(k_pad, key, key_len); - for (int i = 0; i < SHA_DIGEST_SIZE; ++i) + for (unsigned int i = 0; i < crypto_hash_sha256_BYTES; ++i) k_pad[i] ^= 0x5c; - - hash.init(); - hash.update(k_pad, SHA_DIGEST_SIZE); - hash.update(digest, SHA_DIGEST_SIZE); - hash.finish(digest); + + crypto_hash_sha256_init(&state); + crypto_hash_sha256_update(&state, k_pad, crypto_hash_sha256_BYTES); + crypto_hash_sha256_update(&state, digest, crypto_hash_sha256_BYTES); + crypto_hash_sha256_final(&state, digest); } - - -int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], + + +int pbkdf2(unsigned char (&output)[crypto_hash_sha256_BYTES], const unsigned char* key, size_t key_len, const unsigned char* salt, size_t salt_len, unsigned rounds) { - unsigned char asalt[SHA_DIGEST_SIZE + 4], obuf[SHA_DIGEST_SIZE], d1[SHA_DIGEST_SIZE], d2[SHA_DIGEST_SIZE]; - + unsigned char asalt[crypto_hash_sha256_BYTES + 4], obuf[crypto_hash_sha256_BYTES], d1[crypto_hash_sha256_BYTES], d2[crypto_hash_sha256_BYTES]; + if (rounds < 1 || key_len == 0 || salt_len == 0) return -1; - - if (salt_len > SHA_DIGEST_SIZE) salt_len = SHA_DIGEST_SIZE; // length cap for the salt + + if (salt_len > crypto_hash_sha256_BYTES) salt_len = crypto_hash_sha256_BYTES; // length cap for the salt memset(asalt, 0, salt_len); memcpy(asalt, salt, salt_len); - + for (unsigned count = 1; ; ++count) { asalt[salt_len + 0] = (count >> 24) & 0xff; @@ -79,21 +81,21 @@ int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], asalt[salt_len + 2] = (count >> 8) & 0xff; asalt[salt_len + 3] = count & 0xff; hmac_sha256(d1, asalt, salt_len + 4, key, key_len); - memcpy(obuf, d1, SHA_DIGEST_SIZE); - + memcpy(obuf, d1, crypto_hash_sha256_BYTES); + for (unsigned i = 1; i < rounds; i++) { - hmac_sha256(d2, d1, SHA_DIGEST_SIZE, key, key_len); - memcpy(d1, d2, SHA_DIGEST_SIZE); - for (unsigned j = 0; j < SHA_DIGEST_SIZE; j++) + hmac_sha256(d2, d1, crypto_hash_sha256_BYTES, key, key_len); + memcpy(d1, d2, crypto_hash_sha256_BYTES); + for (unsigned j = 0; j < crypto_hash_sha256_BYTES; j++) obuf[j] ^= d1[j]; } - - memcpy(output, obuf, SHA_DIGEST_SIZE); - key += SHA_DIGEST_SIZE; - if (key_len < SHA_DIGEST_SIZE) + + memcpy(output, obuf, crypto_hash_sha256_BYTES); + key += crypto_hash_sha256_BYTES; + if (key_len < crypto_hash_sha256_BYTES) break; - key_len -= SHA_DIGEST_SIZE; + key_len -= crypto_hash_sha256_BYTES; }; return 0; } diff --git a/source/third_party/encryption/pkcs5_pbkdf2.h b/source/third_party/encryption/pkcs5_pbkdf2.h index eda39061a2..107b353af5 100644 --- a/source/third_party/encryption/pkcs5_pbkdf2.h +++ b/source/third_party/encryption/pkcs5_pbkdf2.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -23,8 +23,7 @@ #ifndef PKCS5_PBKD2_INCLUDED #define PKCS5_PBKD2_INCLUDED -// We need to know SHA_DIGEST_SIZE. -#include "third_party/encryption/sha.h" +#include /** * Simple PBKDF2 implementation for hard to crack passwords @@ -36,7 +35,7 @@ * @param iterations Number of salting iterations * @return 0 on success, -1 on error */ -int pbkdf2(unsigned char (&output)[SHA_DIGEST_SIZE], +int pbkdf2(unsigned char (&output)[crypto_hash_sha256_BYTES], const unsigned char* key, size_t key_len, const unsigned char* salt, size_t salt_len, unsigned iterations); diff --git a/source/third_party/encryption/sha.cpp b/source/third_party/encryption/sha.cpp deleted file mode 100644 index 819a693497..0000000000 --- a/source/third_party/encryption/sha.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/** - * FIPS-180-2 compliant SHA-256 implementation - * - * Copyright (C) 2001-2003 Christophe Devine - * - * 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 - */ - -#include "precompiled.h" - -#include "sha.h" - -#define GET_uint32(n,b,i) \ -{ \ - (n) = ( (unsigned int) (b)[(i) ] << 24 ) \ - | ( (unsigned int) (b)[(i) + 1] << 16 ) \ - | ( (unsigned int) (b)[(i) + 2] << 8 ) \ - | ( (unsigned int) (b)[(i) + 3] ); \ -} - -#define PUT_uint32(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ((n) >> 24) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ((n) >> 16) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ((n) >> 8) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ((n) ) & 0xFF ); \ -} - -SHA256::SHA256() -{ - init(); -} -void SHA256::init() -{ - total[0] = 0; - total[1] = 0; - - state[0] = 0x6A09E667; - state[1] = 0xBB67AE85; - state[2] = 0x3C6EF372; - state[3] = 0xA54FF53A; - state[4] = 0x510E527F; - state[5] = 0x9B05688C; - state[6] = 0x1F83D9AB; - state[7] = 0x5BE0CD19; -} - -void SHA256::transform(unsigned char (&data)[64]) -{ - unsigned int temp1, temp2, W[64]; - unsigned int A, B, C, D, E, F, G, H; - - GET_uint32( W[0], data, 0 ); - GET_uint32( W[1], data, 4 ); - GET_uint32( W[2], data, 8 ); - GET_uint32( W[3], data, 12 ); - GET_uint32( W[4], data, 16 ); - GET_uint32( W[5], data, 20 ); - GET_uint32( W[6], data, 24 ); - GET_uint32( W[7], data, 28 ); - GET_uint32( W[8], data, 32 ); - GET_uint32( W[9], data, 36 ); - GET_uint32( W[10], data, 40 ); - GET_uint32( W[11], data, 44 ); - GET_uint32( W[12], data, 48 ); - GET_uint32( W[13], data, 52 ); - GET_uint32( W[14], data, 56 ); - GET_uint32( W[15], data, 60 ); - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - A = state[0]; - B = state[1]; - C = state[2]; - D = state[3]; - E = state[4]; - F = state[5]; - G = state[6]; - H = state[7]; - - P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); - P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); - P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); - P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); - P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); - P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); - P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); - P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); - P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); - P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); - P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); - P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); - P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); - P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); - P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); - P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); - P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); - P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); - P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); - P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); - P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); - P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); - P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); - P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); - P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); - P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); - P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); - P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); - P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); - P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); - P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); - P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); - P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); - P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); - P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); - P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); - P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); - P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); - P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); - P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); - P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); - P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); - P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); - P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); - P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); - P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); - P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); - P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); - P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); - P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); - P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); - P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); - P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); - P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); - P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); - P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); - P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); - P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); - P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); - P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); - P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); - P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); - P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); - P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); - - state[0] += A; - state[1] += B; - state[2] += C; - state[3] += D; - state[4] += E; - state[5] += F; - state[6] += G; - state[7] += H; -} - -void SHA256::update(const void* input, unsigned int length ) -{ - unsigned int left, fill; - - if( ! length ) return; - - left = total[0] & 0x3F; - fill = 64 - left; - - total[0] += length; - total[0] &= 0xFFFFFFFF; - - if( total[0] < length ) - total[1]++; - - if( left && length >= fill ) - { - memcpy( (void *) (buffer + left), - (void *) input, fill ); - transform(buffer); - length -= fill; - input = (unsigned char*)input + fill; - left = 0; - } - - while( length >= 64 ) - { - transform((unsigned char(&)[64])input); - length -= 64; - input = (unsigned char*)input + 64; - } - - if( length ) - { - memcpy( (void *) (buffer + left), - (void *) input, length ); - } -} - -static unsigned char sha256_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -void SHA256::finish(unsigned char (&digest)[32] ) -{ - unsigned int last, padn; - unsigned int high, low; - unsigned char msglen[8]; - - high = ( total[0] >> 29 ) - | ( total[1] << 3 ); - low = ( total[0] << 3 ); - - PUT_uint32( high, msglen, 0 ); - PUT_uint32( low, msglen, 4 ); - - last = total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - update(sha256_padding, padn); - update(msglen, 8); - - PUT_uint32( state[0], digest, 0 ); - PUT_uint32( state[1], digest, 4 ); - PUT_uint32( state[2], digest, 8 ); - PUT_uint32( state[3], digest, 12 ); - PUT_uint32( state[4], digest, 16 ); - PUT_uint32( state[5], digest, 20 ); - PUT_uint32( state[6], digest, 24 ); - PUT_uint32( state[7], digest, 28 ); -} - diff --git a/source/third_party/encryption/sha.h b/source/third_party/encryption/sha.h deleted file mode 100644 index 3c46604019..0000000000 --- a/source/third_party/encryption/sha.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2013 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#ifndef SHA_INCLUDED -#define SHA_INCLUDED - -#define SHA_DIGEST_SIZE 32 - -/** - * Structure for performing SHA256 encryption on arbitrary data - */ -struct SHA256 -{ - unsigned int total[2]; - unsigned int state[8]; - unsigned char buffer[64]; - - SHA256(); - void init(); - void transform(unsigned char (&data)[64]); - void update(const void* input, unsigned int len); - void finish(unsigned char (&digest)[32]); -}; - -#endif // SHA_INCLUDED diff --git a/source/third_party/encryption/tests/test_pkcs5_pbkdf5.h b/source/third_party/encryption/tests/test_pkcs5_pbkdf5.h index da5a8d3626..f4b097fb1e 100644 --- a/source/third_party/encryption/tests/test_pkcs5_pbkdf5.h +++ b/source/third_party/encryption/tests/test_pkcs5_pbkdf5.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 Wildfire Games. +/* Copyright (C) 2018 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ public: void test_pkcs5_pbkd2() { // Mock salt. - const unsigned char salt_buffer[SHA_DIGEST_SIZE] = { + const unsigned char salt_buffer[crypto_hash_sha256_BYTES] = { 244, 243, 249, 244, 32, 33, 34, 35, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 32, 33, 244, 224, 127, 129, 130, 140, 153, 133, 123, 234, 123 }; // Mock passwords. @@ -33,9 +33,9 @@ public: const char password2[] = "0adIsAws0me"; // Run twice with the same input. - unsigned char encrypted1A[SHA_DIGEST_SIZE], encrypted1B[SHA_DIGEST_SIZE]; - pbkdf2(encrypted1A, (unsigned char*)password1, sizeof(password1), salt_buffer, SHA_DIGEST_SIZE, 50); - pbkdf2(encrypted1B, (unsigned char*)password1, sizeof(password1), salt_buffer, SHA_DIGEST_SIZE, 50); + unsigned char encrypted1A[crypto_hash_sha256_BYTES], encrypted1B[crypto_hash_sha256_BYTES]; + pbkdf2(encrypted1A, (unsigned char*)password1, sizeof(password1), salt_buffer, crypto_hash_sha256_BYTES, 50); + pbkdf2(encrypted1B, (unsigned char*)password1, sizeof(password1), salt_buffer, crypto_hash_sha256_BYTES, 50); // Test that the result does not equal input. TS_ASSERT_DIFFERS(*password1, *encrypted1A); @@ -45,9 +45,9 @@ public: TS_ASSERT_EQUALS(*encrypted1A, *encrypted1B); // Run twice again with more iterations. - unsigned char encrypted2A[SHA_DIGEST_SIZE], encrypted2B[SHA_DIGEST_SIZE]; - pbkdf2(encrypted2A, (unsigned char*)password1, sizeof(password1), salt_buffer, SHA_DIGEST_SIZE, 100); - pbkdf2(encrypted2B, (unsigned char*)password1, sizeof(password1), salt_buffer, SHA_DIGEST_SIZE, 100); + unsigned char encrypted2A[crypto_hash_sha256_BYTES], encrypted2B[crypto_hash_sha256_BYTES]; + pbkdf2(encrypted2A, (unsigned char*)password1, sizeof(password1), salt_buffer, crypto_hash_sha256_BYTES, 100); + pbkdf2(encrypted2B, (unsigned char*)password1, sizeof(password1), salt_buffer, crypto_hash_sha256_BYTES, 100); // Test determinism. TS_ASSERT_EQUALS(*encrypted2A, *encrypted2B); @@ -56,9 +56,9 @@ public: TS_ASSERT_DIFFERS(*encrypted1A, *encrypted2A); // Run twice again with different password. - unsigned char encrypted3A[SHA_DIGEST_SIZE], encrypted3B[SHA_DIGEST_SIZE]; - pbkdf2(encrypted3A, (unsigned char*)password2, sizeof(password2), salt_buffer, SHA_DIGEST_SIZE, 50); - pbkdf2(encrypted3B, (unsigned char*)password2, sizeof(password2), salt_buffer, SHA_DIGEST_SIZE, 50); + unsigned char encrypted3A[crypto_hash_sha256_BYTES], encrypted3B[crypto_hash_sha256_BYTES]; + pbkdf2(encrypted3A, (unsigned char*)password2, sizeof(password2), salt_buffer, crypto_hash_sha256_BYTES, 50); + pbkdf2(encrypted3B, (unsigned char*)password2, sizeof(password2), salt_buffer, crypto_hash_sha256_BYTES, 50); // Test determinism. TS_ASSERT_EQUALS(*encrypted3A, *encrypted3B); diff --git a/source/third_party/encryption/tests/test_sha.h b/source/third_party/encryption/tests/test_sha.h deleted file mode 100644 index 56f9e368f7..0000000000 --- a/source/third_party/encryption/tests/test_sha.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2014 Wildfire Games. - * This file is part of 0 A.D. - * - * 0 A.D. 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. - * - * 0 A.D. 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 0 A.D. If not, see . - */ - -#include "lib/self_test.h" - -#include "third_party/encryption/sha.h" - -class TestEncryptionSha256 : public CxxTest::TestSuite -{ -public: - void test_sha256() - { - // Test two hashes of the same variable are equal. - SHA256 hash1, hash2; - unsigned char finalHash1A[SHA_DIGEST_SIZE], finalHash1B[SHA_DIGEST_SIZE]; - const char cStringToHash1[] = "Hash me!"; - hash1.update(cStringToHash1, sizeof(cStringToHash1)); - hash2.update(cStringToHash1, sizeof(cStringToHash1)); - - hash1.finish(finalHash1A); - hash2.finish(finalHash1B); - TS_ASSERT_EQUALS(*finalHash1A, *finalHash1B); - - // Test that the output isn't the same as the input. - TS_ASSERT_DIFFERS(*cStringToHash1, *finalHash1A) - - // Test if updating the hash multiple times changes the - // original hashes but still results in them being equal. - unsigned char finalHash2A[SHA_DIGEST_SIZE], finalHash2B[SHA_DIGEST_SIZE]; - const char cStringToHash2[] = "Hash me too please!"; - hash1.update(cStringToHash2, sizeof(cStringToHash2)); - hash2.update(cStringToHash2, sizeof(cStringToHash2)); - - hash1.finish(finalHash2A); - hash2.finish(finalHash2B); - TS_ASSERT_EQUALS(*finalHash2A, *finalHash2B); - - // Make sure the updated hash is actually different - // compared to the original hash. - TS_ASSERT_DIFFERS(*finalHash1A, *finalHash2A); - TS_ASSERT_DIFFERS(*finalHash1B, *finalHash2B); - } -};