Add support for DW dedi authentication

This commit is contained in:
momo5502 2019-01-27 02:17:11 +01:00
parent 6c859bf1d0
commit e107d3fa23
9 changed files with 765 additions and 548 deletions

View File

@ -0,0 +1,61 @@
#include <std_include.hpp>
#include "bdDediAuth.hpp"
#include "game/game.hpp"
#include "steam/steam.hpp"
#include "utils/cryptography.hpp"
namespace demonware
{
void bdDediAuth::call_service(i_server* server, const std::string& data)
{
bit_buffer buffer(data);
bool more_data;
buffer.set_use_data_types(false);
buffer.read_bool(&more_data);
buffer.set_use_data_types(true);
uint32_t seed, title_id, ticket_size;
buffer.read_uint32(&seed);
buffer.read_uint32(&title_id);
uint8_t ticket[1024];
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
game::native::bdAuthTicket auth_ticket{};
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
auth_ticket.m_magicNumber = 0x0EFBDADDE;
auth_ticket.m_type = 0;
auth_ticket.m_titleID = title_id;
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
auth_ticket.m_licenseID = 4;
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
uint8_t lsg_ticket[128];
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
std::memcpy(lsg_ticket, key.data(), 24);
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
auto enc_ticket = utils::cryptography::des3::encrypt(
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
bit_buffer response;
response.set_use_data_types(false);
response.write_bool(false);
response.write_uint32(700);
response.write_uint32(seed);
response.write_bytes(enc_ticket.size(), enc_ticket.data());
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
auto reply = server->create_message(29);
reply->send(&response, false);
}
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "../i_service.hpp"
namespace demonware
{
class bdDediAuth final : public i_generic_service<12>
{
public:
void call_service(i_server* server, const std::string& data) override;
};
}

View File

@ -0,0 +1,71 @@
#include <std_include.hpp>
#include "bdDediRSAAuth.hpp"
#include "game/game.hpp"
#include "steam/steam.hpp"
#include "utils/cryptography.hpp"
namespace demonware
{
void bdDediRSAAuth::call_service(i_server* server, const std::string& data)
{
bit_buffer buffer(data);
bool more_data;
buffer.set_use_data_types(false);
buffer.read_bool(&more_data);
buffer.set_use_data_types(true);
uint32_t seed, title_id, ticket_size;
buffer.read_uint32(&seed);
buffer.read_uint32(&title_id);
unsigned char rsakey[140];
buffer.read_bytes(sizeof(rsakey), rsakey);
uint8_t ticket[1024];
buffer.read_bytes(std::min(ticket_size, static_cast<uint32_t>(sizeof(ticket))), ticket);
game::native::bdAuthTicket auth_ticket{};
std::memset(&auth_ticket, 0xA, sizeof auth_ticket);
auth_ticket.m_magicNumber = 0x0EFBDADDE;
auth_ticket.m_type = 0;
auth_ticket.m_titleID = title_id;
auth_ticket.m_userID = steam::SteamUser()->GetSteamID().bits;
auto key = utils::cryptography::tiger::compute(SERVER_CD_KEY);
strcpy_s(auth_ticket.m_username, "Open-IW5 Server");
std::memcpy(auth_ticket.m_sessionKey, key.data(), 24);
auth_ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
uint8_t lsg_ticket[128];
ZeroMemory(&lsg_ticket, sizeof lsg_ticket);
std::memcpy(lsg_ticket, key.data(), 24);
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&seed), 4));
const std::string enc_key(reinterpret_cast<char*>(&ticket[32]), 24);
auto enc_ticket = utils::cryptography::des3::encrypt(
std::string(reinterpret_cast<char*>(&auth_ticket), sizeof(auth_ticket)), iv, enc_key);
register_hash(&sha1_desc);
register_prng(&yarrow_desc);
std::string encrypted_key = utils::cryptography::rsa::encrypt(std::string(SERVER_CD_KEY, 24),
std::string("DW-RSAENC", 10),
std::string(PCHAR(rsakey), sizeof(rsakey)));
bit_buffer response;
response.set_use_data_types(false);
response.write_bool(false);
response.write_uint32(700);
response.write_uint32(seed);
response.write_bytes(enc_ticket.size(), enc_ticket.data());
response.write_bytes(sizeof(lsg_ticket), lsg_ticket);
response.write_bytes(encrypted_key.size(), encrypted_key.data());
auto reply = server->create_message(29);
reply->send(&response, false);
}
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "../i_service.hpp"
namespace demonware
{
class bdDediRSAAuth final : public i_generic_service<26>
{
public:
void call_service(i_server* server, const std::string& data) override;
};
}

View File

@ -5,6 +5,8 @@
#define SELECT_VALUE(sp, mp, dedi) (game::is_sp() ? (sp) : (game::is_mp() ? (mp) : (dedi)))
#define SERVER_CD_KEY "Open-IW5-CD-Key"
namespace game
{
namespace native

File diff suppressed because it is too large Load Diff

View File

@ -7,8 +7,10 @@
#include "game/demonware/services/bdLSGHello.hpp" // 7
#include "game/demonware/services/bdStorage.hpp" // 10
#include "game/demonware/services/bdDediAuth.hpp" // 12
#include "game/demonware/services/bdTitleUtilities.hpp" // 12
#include "game/demonware/services/bdDML.hpp" // 27
#include "game/demonware/services/bdDediRSAAuth.hpp" // 26
#include "game/demonware/services/bdSteamAuth.hpp" // 28
namespace demonware
@ -375,7 +377,9 @@ namespace demonware
auto lsg_server = register_server("mw3-pc-lobby.prod.demonware.net");
auto auth_server = register_server("mw3-pc-auth.prod.demonware.net");
auth_server->register_service<bdDediAuth>();
auth_server->register_service<bdSteamAuth>();
auth_server->register_service<bdDediRSAAuth>();
lsg_server->register_service<bdLSGHello>();
lsg_server->register_service<bdStorage>();

View File

@ -127,6 +127,54 @@ namespace utils
reinterpret_cast<const uint8_t*>(message.data()), message.size(), &result, key.get()) == CRYPT_OK && result != 0);
}
std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key)
{
initialize();
const auto prng_id = find_prng("yarrow");
rsa_key new_key;
rsa_import(PBYTE(key.data()), key.size(), &new_key);
prng_state yarrow;
rng_make_prng(128, prng_id, &yarrow, nullptr);
unsigned char buffer[0x80];
unsigned long length = sizeof(buffer);
const auto rsa_result = rsa_encrypt_key( //
PBYTE(data.data()), //
data.size(), //
buffer, //
&length, //
PBYTE(hash.data()), //
hash.size(), //
&yarrow, //
prng_id, //
find_hash("sha1"), //
&new_key);
rsa_free(&new_key);
if (rsa_result == CRYPT_OK)
{
return std::string(PCHAR(buffer), length);
}
return {};
}
void rsa::initialize()
{
static auto initialized = false;
if (initialized) return;
initialized = true;
ltc_mp = ltm_desc;
register_hash(&sha1_desc);
register_prng(&yarrow_desc);
}
std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key)
{
initialize();

View File

@ -39,6 +39,15 @@ namespace utils
static bool verify_message(key key, const std::string& message, const std::string& signature);
};
class rsa final
{
public:
static std::string encrypt(const std::string& data, const std::string& hash, const std::string& key);
private:
static void initialize();
};
class des3 final
{
public: