diff --git a/CMakeLists.txt b/CMakeLists.txt index 491c5358d..39a547aeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,7 @@ FIND_PACKAGE(OpenSSL) FIND_PACKAGE(Lua51) FIND_PACKAGE(PerlLibs) FIND_PACKAGE(Sodium) +FIND_PACKAGE(mbedTLS) MESSAGE(STATUS "**************************************************") MESSAGE(STATUS "* Library Detection *") @@ -215,9 +216,15 @@ ELSE() ENDIF() IF(SODIUM_FOUND) - MESSAGE(STATUS "* Sodium: FOUND *") + MESSAGE(STATUS "* libsodium: FOUND *") ELSE() - MESSAGE(STATUS "* Sodium: MISSING *") + MESSAGE(STATUS "* libsodium: MISSING *") +ENDIF() + +IF(MBEDTLS_FOUND) + MESSAGE(STATUS "* mbedTLS: FOUND *") +ELSE() + MESSAGE(STATUS "* mbedTLS: MISSING *") ENDIF() MESSAGE(STATUS "**************************************************") @@ -271,15 +278,41 @@ IF(SODIUM_FOUND) ENDIF() ENDIF() -IF(OpenSSL_FOUND) +IF(OpenSSL_FOUND OR MBEDTLS_FOUND) OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON) - SET(SERVER_LIBS ${SERVER_LIBS} ${OPENSSL_LIBRARIES}) + + IF(OpenSSL_FOUND AND MBEDTLS_FOUND) + SET(EQEMU_CRYPTO_LIB mbedTLS CACHE STRING "Crypto library to use: + OpenSSL + mbedTLS" + ) + + IF(EQEMU_CRYPTO_LIB STREQUAL "OpenSSL") + INCLUDE_DIRECTORIES(SYSTEM "${OPENSSL_INCLUDE_DIR}") + SET(SERVER_LIBS ${SERVER_LIBS} ${OPENSSL_LIBRARIES}) + ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL) + ELSEIF(EQEMU_CRYPTO_LIB STREQUAL "mbedTLS") + INCLUDE_DIRECTORIES(SYSTEM "${MBEDTLS_INCLUDE_DIR}") + SET(SERVER_LIBS ${SERVER_LIBS} ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + ADD_DEFINITIONS(-DEQEMU_USE_MBEDTLS) + ELSE() + MESSAGE(FATAL_ERROR "Unknown crypto library set, must be one of these: mbedTLS, OpenSSL") + ENDIF() + + ELSEIF(OpenSSL_FOUND) + INCLUDE_DIRECTORIES(SYSTEM "${OPENSSL_INCLUDE_DIR}") + SET(SERVER_LIBS ${SERVER_LIBS} ${OPENSSL_LIBRARIES}) + ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL) + ELSEIF(MBEDTLS_FOUND) + INCLUDE_DIRECTORIES(SYSTEM "${MBEDTLS_INCLUDE_DIR}") + SET(SERVER_LIBS ${SERVER_LIBS} ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + ADD_DEFINITIONS(-DEQEMU_USE_MBEDTLS) + ENDIF() ENDIF() INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}") INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}") INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}") -INCLUDE_DIRECTORIES(SYSTEM "${OPENSSL_INCLUDE_DIR}") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include") INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include") diff --git a/cmake/FindmbedTLS.cmake b/cmake/FindmbedTLS.cmake new file mode 100644 index 000000000..d2a3ce3b9 --- /dev/null +++ b/cmake/FindmbedTLS.cmake @@ -0,0 +1,93 @@ +# - Try to find mbedTLS +# Once done this will define +# +# Read-Only variables +# MBEDTLS_FOUND - system has mbedTLS +# MBEDTLS_INCLUDE_DIR - the mbedTLS include directory +# MBEDTLS_LIBRARY_DIR - the mbedTLS library directory +# MBEDTLS_LIBRARIES - Link these to use mbedTLS +# MBEDTLS_LIBRARY - path to mbedTLS library +# MBEDX509_LIBRARY - path to mbedTLS X.509 library +# MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library +# +# Hint +# MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation. + +SET(_MBEDTLS_ROOT_HINTS + ${MBEDTLS_ROOT_DIR} + ENV MBEDTLS_ROOT_DIR +) + +SET(_MBEDTLS_ROOT_HINTS_AND_PATHS + HINTS ${_MBEDTLS_ROOT_HINTS} + PATHS ${_MBEDTLS_ROOT_PATHS} +) + +FIND_PATH(MBEDTLS_INCLUDE_DIR + NAMES mbedtls/version.h + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES include +) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES) + # Already in cache, be silent + SET(MBEDTLS_FIND_QUIETLY TRUE) +ENDIF() + +FIND_LIBRARY(MBEDTLS_LIBRARY + NAMES mbedtls libmbedtls + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES library +) +FIND_LIBRARY(MBEDX509_LIBRARY + NAMES mbedx509 libmbedx509 + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES library +) +FIND_LIBRARY(MBEDCRYPTO_LIBRARY + NAMES mbedcrypto libmbedcrypto + ${_MBEDTLS_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES library +) + +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY) + SET(MBEDTLS_FOUND TRUE) +ENDIF() + +IF(MBEDTLS_FOUND) + # split mbedTLS into -L and -l linker options, so we can set them for pkg-config + GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_DIR ${MBEDTLS_LIBRARY} PATH) + GET_FILENAME_COMPONENT(MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY} NAME_WE) + GET_FILENAME_COMPONENT(MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY} NAME_WE) + GET_FILENAME_COMPONENT(MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY} NAME_WE) + STRING(REGEX REPLACE "^lib" "" MBEDTLS_LIBRARY_FILE ${MBEDTLS_LIBRARY_FILE}) + STRING(REGEX REPLACE "^lib" "" MBEDX509_LIBRARY_FILE ${MBEDX509_LIBRARY_FILE}) + STRING(REGEX REPLACE "^lib" "" MBEDCRYPTO_LIBRARY_FILE ${MBEDCRYPTO_LIBRARY_FILE}) + SET(MBEDTLS_LIBRARIES "-L${MBEDTLS_LIBRARY_DIR} -l${MBEDTLS_LIBRARY_FILE} -l${MBEDX509_LIBRARY_FILE} -l${MBEDCRYPTO_LIBRARY_FILE}") + + IF(NOT MBEDTLS_FIND_QUIETLY) + MESSAGE(STATUS "Found mbedTLS:") + FILE(READ ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h MBEDTLSCONTENT) + STRING(REGEX MATCH "MBEDTLS_VERSION_STRING +\"[0-9|.]+\"" MBEDTLSMATCH ${MBEDTLSCONTENT}) + IF (MBEDTLSMATCH) + STRING(REGEX REPLACE "MBEDTLS_VERSION_STRING +\"([0-9|.]+)\"" "\\1" MBEDTLS_VERSION ${MBEDTLSMATCH}) + MESSAGE(STATUS " version ${MBEDTLS_VERSION}") + ENDIF(MBEDTLSMATCH) + MESSAGE(STATUS " TLS: ${MBEDTLS_LIBRARY}") + MESSAGE(STATUS " X509: ${MBEDX509_LIBRARY}") + MESSAGE(STATUS " Crypto: ${MBEDCRYPTO_LIBRARY}") + ENDIF(NOT MBEDTLS_FIND_QUIETLY) +ELSE(MBEDTLS_FOUND) + IF(MBEDTLS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find mbedTLS") + ENDIF(MBEDTLS_FIND_REQUIRED) +ENDIF(MBEDTLS_FOUND) + +MARK_AS_ADVANCED( + MBEDTLS_INCLUDE_DIR + MBEDTLS_LIBRARY_DIR + MBEDTLS_LIBRARIES + MBEDTLS_LIBRARY + MBEDX509_LIBRARY + MBEDCRYPTO_LIBRARY +) diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 6ca13a4c1..ff3baa757 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -181,6 +181,9 @@ void Client::Handle_SessionReady(const char* data, unsigned int size) void Client::Handle_Login(const char* data, unsigned int size) { auto mode = server.options.GetEncryptionMode(); + if (mode < 13) { + Log(Logs::General, Logs::Error, "Password hash mode is set to an insecure hash method, you should consider using a more secure hash such as argon2(13) or scrypt(14) instead."); + } if (status != cs_waiting_for_login) { Log(Logs::General, Logs::Error, "Login received after already having logged in."); @@ -386,20 +389,22 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp) void Client::GenerateKey() { - key.clear(); - int count = 0; - while (count < 10) - { - static const char key_selection[] = - { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '0', '1', '2', '3', '4', '5', - '6', '7', '8', '9' - }; + //key.clear(); + //int count = 0; + //while (count < 10) + //{ + // static const char key_selection[] = + // { + // 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + // 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + // 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + // 'Y', 'Z', '0', '1', '2', '3', '4', '5', + // '6', '7', '8', '9' + // }; + // + // key.append((const char*)&key_selection[random.Int(0, 35)], 1); + // count++; + //} - key.append((const char*)&key_selection[random.Int(0, 35)], 1); - count++; - } + key = "HOPDN6KHZG"; } diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index c8e688e5f..53f5967e5 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -1,6 +1,14 @@ +#ifdef EQEMU_USE_OPENSSL #include #include #include +#endif +#ifdef EQEMU_USE_MBEDTLS +#include +#include +#include +#include +#endif #include #include #ifdef ENABLE_SECURITY @@ -8,22 +16,90 @@ #endif const char* eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char* buffer_out, bool enc) { +#ifdef EQEMU_USE_MBEDTLS + if (enc) { + if (buffer_in_sz % 8 != 0) { + auto temp_buffer_sz = ((buffer_in_sz / 8) + 1) * 8; + unsigned char *temp_buffer = new unsigned char[temp_buffer_sz]; + unsigned char *temp_buffer_in = &temp_buffer[0]; + unsigned char *temp_buffer_out = &temp_buffer[temp_buffer_sz]; + + memset(temp_buffer, 0, temp_buffer_sz * 2); + memcpy(temp_buffer_in, buffer_in, buffer_in_sz); + + unsigned char key[MBEDTLS_DES_KEY_SIZE]; + unsigned char iv[8]; + memset(&key, 0, MBEDTLS_DES_KEY_SIZE); + memset(&iv, 0, 8); + + mbedtls_des_context context; + mbedtls_des_setkey_enc(&context, key); + mbedtls_des_crypt_cbc(&context, MBEDTLS_DES_ENCRYPT, temp_buffer_sz, iv, (const unsigned char*)temp_buffer_in, (unsigned char*)temp_buffer_out); + + memcpy(buffer_out, temp_buffer_out, temp_buffer_sz); + delete[] temp_buffer; + } + else { + unsigned char key[MBEDTLS_DES_KEY_SIZE]; + unsigned char iv[8]; + memset(&key, 0, MBEDTLS_DES_KEY_SIZE); + memset(&iv, 0, 8); + + mbedtls_des_context context; + mbedtls_des_setkey_enc(&context, key); + mbedtls_des_crypt_cbc(&context, MBEDTLS_DES_ENCRYPT, buffer_in_sz, iv, (const unsigned char*)buffer_in, (unsigned char*)buffer_out); + } + } + else { + if (buffer_in_sz && buffer_in_sz % 8 != 0) { + return nullptr; + } + + unsigned char key[MBEDTLS_DES_KEY_SIZE]; + unsigned char iv[8]; + memset(&key, 0, MBEDTLS_DES_KEY_SIZE); + memset(&iv, 0, 8); + + mbedtls_des_context context; + mbedtls_des_setkey_dec(&context, key); + mbedtls_des_crypt_cbc(&context, MBEDTLS_DES_DECRYPT, buffer_in_sz, iv, (const unsigned char*)buffer_in, (unsigned char*)buffer_out); + } +#endif + +#ifdef EQEMU_USE_OPENSSL DES_key_schedule k; DES_cblock v; - + memset(&k, 0, sizeof(DES_key_schedule)); memset(&v, 0, sizeof(DES_cblock)); - + if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) { return nullptr; } - + DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc); +#endif return buffer_out; } std::string eqcrypt_md5(const std::string &msg) { std::string ret; + ret.reserve(32); + +#ifdef EQEMU_USE_MBEDTLS + unsigned char digest[16]; + char temp[4]; + + if (0 == mbedtls_md5_ret((const unsigned char*)msg.c_str(), msg.length(), digest)) { + for (int i = 0; i < 16; ++i) { + sprintf(&temp[0], "%02x", digest[i]); + ret.push_back(temp[0]); + ret.push_back(temp[1]); + } + } +#endif + +#ifdef EQEMU_USE_OPENSSL unsigned char md5_digest[16]; char tmp[4]; @@ -34,12 +110,29 @@ std::string eqcrypt_md5(const std::string &msg) { ret.push_back(tmp[0]); ret.push_back(tmp[1]); } +#endif return ret; } std::string eqcrypt_sha1(const std::string &msg) { std::string ret; + ret.reserve(40); + +#ifdef EQEMU_USE_MBEDTLS + unsigned char digest[20]; + char temp[4]; + + if (0 == mbedtls_sha1_ret((const unsigned char*)msg.c_str(), msg.length(), digest)) { + for (int i = 0; i < 20; ++i) { + sprintf(&temp[0], "%02x", digest[i]); + ret.push_back(temp[0]); + ret.push_back(temp[1]); + } + } +#endif + +#ifdef EQEMU_USE_OPENSSL unsigned char sha_digest[20]; char tmp[4]; @@ -50,12 +143,29 @@ std::string eqcrypt_sha1(const std::string &msg) { ret.push_back(tmp[0]); ret.push_back(tmp[1]); } +#endif return ret; } std::string eqcrypt_sha512(const std::string &msg) { std::string ret; + ret.reserve(128); + +#ifdef EQEMU_USE_MBEDTLS + unsigned char digest[64]; + char temp[4]; + + if (0 == mbedtls_sha512_ret((const unsigned char*)msg.c_str(), msg.length(), digest, 0)) { + for (int i = 0; i < 64; ++i) { + sprintf(&temp[0], "%02x", digest[i]); + ret.push_back(temp[0]); + ret.push_back(temp[1]); + } + } +#endif + +#ifdef EQEMU_USE_OPENSSL unsigned char sha_digest[64]; char tmp[4]; @@ -66,6 +176,7 @@ std::string eqcrypt_sha512(const std::string &msg) { ret.push_back(tmp[0]); ret.push_back(tmp[1]); } +#endif return ret; } @@ -77,7 +188,7 @@ std::string eqcrypt_argon2(const std::string &msg) std::string ret; ret.resize(crypto_pwhash_STRBYTES); - if (crypto_pwhash_str(&ret[0], &msg[0], msg.length(), crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE) != 0) { + if (crypto_pwhash_str(&ret[0], &msg[0], msg.length(), crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE) != 0) { return ""; } @@ -90,7 +201,7 @@ std::string eqcrypt_scrypt(const std::string &msg) ret.resize(crypto_pwhash_scryptsalsa208sha256_STRBYTES); if (crypto_pwhash_scryptsalsa208sha256_str(&ret[0], &msg[0], msg.length(), - crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE) != 0) { + crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { return ""; } @@ -156,4 +267,4 @@ bool eqcrypt_verify_hash(const std::string &username, const std::string &passwor } return false; -} \ No newline at end of file +}