mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-27 16:32:27 +00:00
Update openssl calls to use EVP interface (#5072)
This commit is contained in:
parent
6694281f22
commit
6d6cc8ca95
@ -19,9 +19,9 @@
|
||||
#include "common/compiler_macros.h"
|
||||
|
||||
#ifdef EQEMU_USE_OPENSSL
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
#ifdef EQEMU_USE_MBEDTLS
|
||||
#include <mbedtls/des.h>
|
||||
@ -33,6 +33,8 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef ENABLE_SECURITY
|
||||
|
||||
#include <sodium.h>
|
||||
@ -128,23 +130,92 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff
|
||||
#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));
|
||||
|
||||
// Decrypt requires block-aligned input; encrypt zero-pads a trailing
|
||||
// partial block to match the legacy DES_ncbc_encrypt semantics the
|
||||
// game protocol expects.
|
||||
if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PUSH_DISABLE_DEPRECATED_WARNINGS()
|
||||
DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc);
|
||||
POP_DISABLE_DEPRECATED_WARNINGS()
|
||||
unsigned char key[8] = {0};
|
||||
unsigned char iv[8] = {0};
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool result = EVP_CipherInit_ex2(ctx, EVP_des_cbc(), key, iv, enc, nullptr) == 1;
|
||||
if (result) {
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
||||
|
||||
const unsigned char* src = reinterpret_cast<const unsigned char*>(buffer_in);
|
||||
size_t src_len = buffer_in_sz;
|
||||
std::unique_ptr<unsigned char[]> padded;
|
||||
|
||||
if (enc && buffer_in_sz % 8 != 0) {
|
||||
src_len = ((buffer_in_sz / 8) + 1) * 8;
|
||||
padded.reset(new unsigned char[src_len]());
|
||||
memcpy(padded.get(), buffer_in, buffer_in_sz);
|
||||
src = padded.get();
|
||||
}
|
||||
|
||||
int outl = 0;
|
||||
int final_len = 0;
|
||||
result = EVP_CipherUpdate(ctx, reinterpret_cast<unsigned char*>(buffer_out), &outl, src, static_cast<int>(src_len)) == 1
|
||||
&& EVP_CipherFinal_ex(ctx, reinterpret_cast<unsigned char*>(buffer_out) + outl, &final_len) == 1;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
return buffer_out;
|
||||
}
|
||||
|
||||
#ifdef EQEMU_USE_OPENSSL
|
||||
static OSSL_PROVIDER *s_legacy_provider = nullptr;
|
||||
static OSSL_PROVIDER *s_default_provider = nullptr;
|
||||
#endif
|
||||
|
||||
bool eqcrypt_init()
|
||||
{
|
||||
#ifdef EQEMU_USE_OPENSSL
|
||||
if (!s_default_provider) {
|
||||
s_default_provider = OSSL_PROVIDER_load(nullptr, "default");
|
||||
}
|
||||
if (!s_legacy_provider) {
|
||||
s_legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
|
||||
}
|
||||
|
||||
if (!s_default_provider || !s_legacy_provider) {
|
||||
char buf[256];
|
||||
while (auto err = ERR_get_error()) {
|
||||
ERR_error_string_n(err, buf, sizeof(buf));
|
||||
LogError("OpenSSL provider load failure: {}", buf);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void eqcrypt_shutdown()
|
||||
{
|
||||
#ifdef EQEMU_USE_OPENSSL
|
||||
if (s_legacy_provider) {
|
||||
OSSL_PROVIDER_unload(s_legacy_provider);
|
||||
s_legacy_provider = nullptr;
|
||||
}
|
||||
if (s_default_provider) {
|
||||
OSSL_PROVIDER_unload(s_default_provider);
|
||||
s_default_provider = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string eqcrypt_md5(const std::string &msg)
|
||||
{
|
||||
std::string ret;
|
||||
@ -167,14 +238,12 @@ std::string eqcrypt_md5(const std::string &msg)
|
||||
unsigned char md5_digest[16];
|
||||
char tmp[4];
|
||||
|
||||
PUSH_DISABLE_DEPRECATED_WARNINGS()
|
||||
MD5((const unsigned char*)msg.c_str(), msg.length(), md5_digest);
|
||||
POP_DISABLE_DEPRECATED_WARNINGS()
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
sprintf(&tmp[0], "%02x", md5_digest[i]);
|
||||
ret.push_back(tmp[0]);
|
||||
ret.push_back(tmp[1]);
|
||||
if (EVP_Digest(msg.data(), msg.length(), md5_digest, nullptr, EVP_md5(), nullptr) == 1) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
sprintf(&tmp[0], "%02x", md5_digest[i]);
|
||||
ret.push_back(tmp[0]);
|
||||
ret.push_back(tmp[1]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -203,12 +272,12 @@ std::string eqcrypt_sha1(const std::string &msg)
|
||||
unsigned char sha_digest[20];
|
||||
char tmp[4];
|
||||
|
||||
SHA1((const unsigned char*)msg.c_str(), msg.length(), sha_digest);
|
||||
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
sprintf(&tmp[0], "%02x", sha_digest[i]);
|
||||
ret.push_back(tmp[0]);
|
||||
ret.push_back(tmp[1]);
|
||||
if (EVP_Digest(msg.data(), msg.length(), sha_digest, nullptr, EVP_sha1(), nullptr) == 1) {
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
sprintf(&tmp[0], "%02x", sha_digest[i]);
|
||||
ret.push_back(tmp[0]);
|
||||
ret.push_back(tmp[1]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -237,12 +306,12 @@ std::string eqcrypt_sha512(const std::string &msg)
|
||||
unsigned char sha_digest[64];
|
||||
char tmp[4];
|
||||
|
||||
SHA512((const unsigned char*)msg.c_str(), msg.length(), sha_digest);
|
||||
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
sprintf(&tmp[0], "%02x", sha_digest[i]);
|
||||
ret.push_back(tmp[0]);
|
||||
ret.push_back(tmp[1]);
|
||||
if (EVP_Digest(msg.data(), msg.length(), sha_digest, nullptr, EVP_sha512(), nullptr) == 1) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
sprintf(&tmp[0], "%02x", sha_digest[i]);
|
||||
ret.push_back(tmp[0]);
|
||||
ret.push_back(tmp[1]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -48,10 +48,20 @@ namespace CryptoHash {
|
||||
}
|
||||
|
||||
std::string GetEncryptionByModeId(uint32 mode);
|
||||
|
||||
// DES-CBC with an all-zero key and IV (EQ login protocol obfuscation, not security).
|
||||
// On encrypt, a trailing partial block is zero-padded to the next 8-byte boundary, so
|
||||
// buffer_out must be at least ((buffer_in_sz + 7) / 8) * 8 bytes. On decrypt, buffer_in_sz
|
||||
// must already be a multiple of 8 or the call returns nullptr.
|
||||
const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc);
|
||||
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode);
|
||||
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode);
|
||||
|
||||
// OpenSSL 3.0 moved DES behind the "legacy" provider; these load/unload it
|
||||
// for the lifetime of the process. No-op when built against mbedtls.
|
||||
bool eqcrypt_init();
|
||||
void eqcrypt_shutdown();
|
||||
|
||||
struct EncryptionResult {
|
||||
std::string password;
|
||||
int mode = 0;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "common/platform.h"
|
||||
#include "common/timer.h"
|
||||
#include "common/types.h"
|
||||
#include "loginserver/encryption.h"
|
||||
#include "loginserver/login_server.h"
|
||||
#include "loginserver/loginserver_command_handler.h"
|
||||
#include "loginserver/loginserver_webserver.h"
|
||||
@ -160,6 +161,11 @@ int main(int argc, char **argv)
|
||||
RegisterExecutablePlatform(ExePlatformLogin);
|
||||
set_exception_handler();
|
||||
|
||||
if (!eqcrypt_init()) {
|
||||
LogError("Failed to initialize crypto providers");
|
||||
return 1;
|
||||
}
|
||||
|
||||
LogInfo("Logging System Init");
|
||||
|
||||
if (argc == 1) {
|
||||
@ -280,5 +286,7 @@ int main(int argc, char **argv)
|
||||
LogInfo("Server Manager Shutdown");
|
||||
delete server.server_manager;
|
||||
|
||||
eqcrypt_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user