__int64 __fastcall RBX::Security::SessionCrypto::isTestOnly(unsigned __int8 format)
{
return format >> 7;
}

void __fastcall RBX::Security::SessionCrypto::resetKeyExchangeKeys(RBX::Security::SessionCrypto *this, bool error)
{
std::unique_ptrRBX::Security::SessionCrypto::KeyExchangeKeys::reset(&this->keyExchangeKeys, 0LL);
this->isEarlySessionReady = 0;
if ( error )
*&this->isSessionReady = 256;
}

void __fastcall RBX::Security::SessionCrypto::setRakCryptoFormat(
RBX::Security::SessionCrypto *this,
RBX::Security::SessionCrypto::CryptoFormat value)
{
this->rakFormat = value;
}

// local variable allocation has failed, the output may be wrong!
// Hidden C++ exception states: #wind=4
std::pairstd::string,bool *__fastcall RBX::Security::SessionCrypto::verifyPreauthMac(
std::pairstd::string,bool *result,
RBX::StringView *msg,
RBX::StringView *preauthBlob)
{
bool v5; // bl
char v6; // r13
_QWORD *v7; // rax
__int64 v8; // r8
unsigned __int64 v9; // rsi
unsigned __int64 v10; // rcx
unsigned __int64 v11; // rdx
unsigned __int64 Length; // r9
_QWORD *v13; // r8
const char *Data; // r10
char v15; // al
unsigned __int64 v16; // rcx
unsigned __int8 *Instance; // rcx
unsigned __int64 v18; // r12
_BYTE *v19; // r15
__int128 v20; // xmm6
char *v21; // rdi
std::_String_val<std::_Simple_types >::_Bxty Bx; // xmm7
unsigned int v23; // r9d
unsigned __int64 v24; // rdx
char *Ptr; // rcx
unsigned __int8 *Mylast; // rcx
std::string *v27; // rbx
unsigned __int64 v28; // rdx
char *v29; // rax
unsigned __int64 v30; // rdx
char *v31; // rcx
char *v32; // rcx
unsigned __int64 v33; // rdx
unsigned __int8 *v34; // rax
unsigned __int64 v35; // rdx
char *v36; // rax
_WORD name[4]; // [rsp+28h] [rbp-E0h]
std::_String_val<std::_Simple_types >::_Bxty name_8; // [rsp+30h] [rbp-D8h] BYREF
_BYTE name_24[48]; // [rsp+40h] [rbp-C8h] OVERLAPPED BYREF
std::vector key; // [rsp+70h] [rbp-98h] BYREF
__int64 v42; // [rsp+88h] [rbp-80h]
_BYTE v43[48]; // [rsp+98h] [rbp-70h] OVERLAPPED BYREF
RBX::StringView v44; // [rsp+C8h] [rbp-40h] BYREF
RBX::StringView v45; // [rsp+D8h] [rbp-30h] BYREF
std::string v46; // [rsp+E8h] [rbp-20h] BYREF
char v48; // [rsp+180h] [rbp+78h]

v5 = 1;
v48 = 1;
v6 = 0;
name[0] = 0;
*&v43[32] = 0LL;
v7 = &v43[16];
v8 = 2LL;
do
{
*v7 = 0LL;
v7[1] = 0LL;
v7 += 2;
--v8;
}
while ( v8 );
*&name_24[16] = 0LL;
*&name_24[32] = 0LL;
v9 = 15LL;
*&name_24[40] = 15LL;
if ( DFFlag::ForceNewPaBlob2.value || preauthBlob->Length > 0x20 )
{
v10 = 16LL;
v11 = 0LL;
Length = preauthBlob->Length;
v13 = &v43[16];
do
{
if ( Length == v10 )
break;
Data = preauthBlob->Data;
v15 = preauthBlob->Data[v10];
v16 = v10 + 1;
*(name + v11) = v15;
if ( Length - v16 < 0x10 )
break;
*v13 = &Data[v16];
v13[1] = 16LL;
v10 = v16 + 16;
if ( v10 >= Length )
break;
++v11;
v13 += 2;
}
while ( v11 < 2 );
}
else
{
LOBYTE(name[0]) = 6;
*&v43[16] = preauthBlob->Data + 16;
*&v43[24] = 16LL;
}
Instance = RBX::Security::KeyRing::getInstance();
key._Mypair._Myval2._Myfirst = Instance;
v18 = 0LL;
v19 = &v43[16];
v20 = *&name_24[32];
v21 = *&name_24[16];
Bx = *&name_24[16];
while ( 1 )
{
if ( v6 )
goto LABEL_52;
v23 = *(name + v18);
*&name_24[8] = 15LL;
*name_24 = 10LL;
strcpy(name_8._Buf, "PreAuthKey");
RBX::Security::KeyRing::getKeyForConsumption(Instance, &key._Mypair._Myval2._Mylast, &name_8, v23);
if ( *&name_24[8] >= 0x10uLL )
{
v24 = &name_24[8] + 1LL;
Ptr = name_8._Ptr;
if ( (&name_24[8] + 1LL) >= 0x1000 )
{
v24 = *&name_24[8] + 40LL;
Ptr = *(name_8._Ptr - 1);
if ( (name_8._Ptr - Ptr - 8) > 0x1F )
_invalid_parameter_noinfo_noreturn();
}
operator delete(Ptr, v24);
}
*name_24 = 0LL;
*&name_24[8] = 15LL;
name_8._Buf[0] = 0;
Mylast = key._Mypair._Myval2._Mylast;
if ( key._Mypair._Myval2._Mylast == key._Mypair._Myval2._Myend || !*v19 )
{
v5 = 0;
v48 = 0;
}
else
{
*v43 = key._Mypair._Myval2._Mylast;
*&v43[8] = key._Mypair._Myval2._Myend - key._Mypair._Myval2._Mylast;
v44 = *v43;
v45 = *msg;
v27 = RBX::Crypto::computeKeyedBlake2b(&v46, &v45, &v44, 16);
if ( &name_24[16] != v27 )
{
if ( v9 >= 0x10 )
{
v28 = v9 + 1;
v29 = v21;
if ( v9 + 1 >= 0x1000 )
{
v28 = v9 + 40;
v21 = *(v21 - 1);
if ( (v29 - v21 - 8) > 0x1F )
LABEL_44:
_invalid_parameter_noinfo_noreturn();
}
operator delete(v21, v28);
}
Bx = v27->_Mypair._Myval2._Bx;
*&name_24[16] = v27->_Mypair._Myval2._Bx;
v20 = *&v27->_Mypair._Myval2._Mysize;
*&name_24[32] = v20;
v27->_Mypair._Myval2._Mysize = 0LL;
v27->_Mypair._Myval2._Myres = 15LL;
v27->_Mypair._Myval2._Bx._Buf[0] = 0;
v9 = *&name_24[40];
v21 = *&name_24[16];
}
if ( v46._Mypair._Myval2._Myres >= 0x10 )
{
v30 = v46._Mypair._Myval2._Myres + 1;
v31 = v46._Mypair._Myval2._Bx._Ptr;
if ( v46._Mypair._Myval2._Myres + 1 >= 0x1000 )
{
v30 = v46._Mypair._Myval2._Myres + 40;
v31 = *(v46._Mypair._Myval2._Bx._Ptr - 1);
if ( (v46._Mypair._Myval2._Bx._Ptr - v31 - 8) > 0x1F )
goto LABEL_44;
}
operator delete(v31, v30);
}
v32 = &name_24[16];
if ( v9 >= 0x10 )
v32 = v21;
if ( *v32 == **v19 && *(v32 + 1) == *(*v19 + 8LL) )
{
v6 = 1;
v5 = v48;
}
else
{
v5 = 0;
v48 = 0;
}
Mylast = key._Mypair._Myval2._Mylast;
}
if ( Mylast )
{
v33 = v42 - Mylast;
v34 = Mylast;
if ( (v42 - Mylast) >= 0x1000 )
{
Mylast = *(Mylast - 1);
v33 += 39LL;
if ( (v34 - Mylast - 8) > 0x1F )
_invalid_parameter_noinfo_noreturn();
}
operator delete(Mylast, v33);
}
++v18;
v19 += 16;
if ( v18 >= 2 )
break;
Instance = key._Mypair._Myval2._Myfirst;
}
if ( v6 )
{
LABEL_52:
result->first._Mypair._Myval2._Bx = Bx;
*&result->first._Mypair._Myval2._Mysize = v20;
result->second = v5;
return result;
}
name_8._Ptr = 0LL;
*name_24 = 0LL;
*&name_24[8] = 15LL;
result->first._Mypair._Myval2._Bx._Ptr = 0LL;
result->first._Mypair._Myval2._Mysize = 0LL;
result->first._Mypair._Myval2._Myres = 0LL;
result->first._Mypair._Myval2._Bx = name_8;
*&result->first._Mypair._Myval2._Mysize = *name_24;
result->second = 0;
if ( v9 >= 0x10 )
{
v35 = v9 + 1;
v36 = v21;
if ( v9 + 1 >= 0x1000 )
{
v35 = v9 + 40;
v21 = *(v21 - 1);
if ( (v36 - v21 - 8) > 0x1F )
_invalid_parameter_noinfo_noreturn();
}
operator delete(v21, v35);
}
return result;
}

void __fastcall RBX::Security::SessionCrypto::~SessionCrypto(RBX::Security::SessionCrypto *this)
{
std::_Ref_count_base *Rep; // rbx
RBX::Security::SessionCrypto::KeyExchangeKeys *Myval2; // rbx

this->__vftable = RBX::Security::SessionCrypto::`vftable';
Rep = this->earlyAuthData._Rep;
if ( Rep )
{
if ( _InterlockedExchangeAdd(&Rep->_Uses, 0xFFFFFFFF) == 1 )
{
Rep->_Destroy(Rep);
if ( _InterlockedExchangeAdd(&Rep->_Weaks, 0xFFFFFFFF) == 1 )
Rep->_Delete_this(Rep);
}
}
Myval2 = this->keyExchangeKeys._Mypair._Myval2;
if ( Myval2 )
{
RBX::Security::SessionCrypto::KeyExchangeKeys::~KeyExchangeKeys(Myval2);
operator delete(Myval2, 0xE0uLL);
}
}

bool __fastcall RBX::Security::SessionCrypto::isKeyExchangeComplete(RBX::Security::SessionCrypto *this)
{
return !this->isError && this->isSessionReady;
}

_BOOL8 __fastcall RBX::Security::SessionCrypto::isAesGcm(RBX::Security::SessionCrypto::CryptoFormat format)
{
return (format & 2) != 0;
}

void __fastcall RBX::Security::SessionCrypto::initCommon(RBX::Security::SessionCrypto *this)
{
std::unique_ptrRBX::Security::SessionCrypto::KeyExchangeKeys *p_keyExchangeKeys; // rdi
RBX::Security::SessionCrypto::KeyExchangeKeys *v2; // rax
RBX::Security::SessionCrypto::KeyExchangeKeys *v3; // rbx

*&this->isEarlySessionReady = 0;
p_keyExchangeKeys = &this->keyExchangeKeys;
this->isError = 0;
v2 = operator new(0xE0uLL);
v3 = v2;
if ( v2 )
{
sodium_memzero(v2, 0x20uLL);
sodium_memzero(&v3->secretEphemeralKey, 0x20uLL);
sodium_memzero(&v3->publicEarlyKey, 0x20uLL);
sodium_memzero(&v3->secretEarlyKey, 0x20uLL);
sodium_memzero(&v3->earlySessionKeyClientToServer, 0x20uLL);
sodium_memzero(&v3->earlySessionKeyServerToClient, 0x20uLL);
}
else
{
v3 = 0LL;
}
std::unique_ptrRBX::Security::SessionCrypto::KeyExchangeKeys::reset(p_keyExchangeKeys, v3);
crypto_kx_keypair(
p_keyExchangeKeys->_Mypair._Myval2->publicEphemeralKey._Elems,
p_keyExchangeKeys->_Mypair._Myval2->secretEphemeralKey._Elems);
}

bool __fastcall RBX::Security::SessionCrypto::getSupportAes(RBX::Security::SessionCrypto *this)
{
int is_available; // eax

if ( DFFlag::ScNoAes.value || (is_available = crypto_aead_aes256gcm_is_available(), is_available != 1) )
LOBYTE(is_available) = 0;
return is_available;
}

__int64 __fastcall RBX::Security::SessionCrypto::getRakCryptoFormat(RBX::Security::SessionCrypto *this)
{
return this->rakFormat;
}

RBX::Security::SessionCrypto::CryptoFormat __fastcall RBX::Security::SessionCrypto::getEnabledForRaknet(
RBX::Security::SessionCrypto *this)
{
RBX::Security::SessionCrypto::CryptoFormat result; // al

result = this->rakFormat;
if ( result )
return ~result >> 7;
return result;
}

std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::encryptString(
RBX::Security::SessionCrypto *this,
std::optional<std::string > *result,
const std::string *message)
{
unsigned __int64 Mysize; // rax
RBX::ArrayView v6; // [rsp+20h] [rbp-18h] BYREF

Mysize = message->_Mypair._Myval2._Mysize;
if ( message->_Mypair._Myval2._Myres >= 0x10 )
message = message->_Mypair._Myval2._Bx._Ptr;
v6.buffer = message;
v6.length = Mysize;
RBX::Security::SessionCrypto::encryptData(this, result, &v6);
return result;
}

bool __fastcall RBX::Security::SessionCrypto::encryptRakDataInPlace(
RBX::Security::SessionCrypto *this,
RBX::MutableArrayView *messageToBox)
{
unsigned __int64 length; // r9
unsigned __int64 v4; // r9
bool isServer; // cl
const unsigned __int8 *buffer; // r11
unsigned __int8 *v7; // r8
int (__fastcall *v8)(unsigned __int8 *, unsigned __int8 *, unsigned __int64 *, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, const unsigned __int8 *, const unsigned __int8 *); // r10
__int64 v9; // rax
unsigned __int64 macLen; // [rsp+68h] [rbp+10h] BYREF

length = messageToBox->length;
if ( length < 0x12 || this->isError || !this->isSessionReady )
return 0;
v4 = length - 18;
isServer = this->isServer;
buffer = messageToBox->buffer;
v7 = &messageToBox->buffer[v4];
qmemcpy(v7, "UniqueNumbeR", 12);
*v7 = _InterlockedExchangeAdd64(&this->txRakNonce, 1uLL);
v8 = crypto_aead_chacha20poly1305_ietf_encrypt_detached;
if ( (this->rakFormat & 2) != 0 )
v8 = crypto_aead_aes256gcm_encrypt_detached;
v9 = 96LL;
if ( !isServer )
v9 = 64LL;
return v8(buffer, v7 + 2, &macLen, buffer, v4, 0LL, 0LL, 0LL, v7, this + v9) == 0;
}

std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::encryptData(
RBX::Security::SessionCrypto *this,
std::optional<std::string > *result,
RBX::ArrayView *message)
{
unsigned __int64 v6; // rsi
std::optional<std::string > *p_box; // r10
char *Ptr; // rcx
unsigned __int64 Myres; // rdx
__int64 v10; // r9
const unsigned __int8 *k; // r9
char *v12; // r8
bool Has_value; // al
unsigned __int64 v14; // rdx
char *v16; // rax
unsigned __int8 *m[2]; // [rsp+60h] [rbp-19h]
__int128 v18; // [rsp+70h] [rbp-9h]
__int128 v19; // [rsp+80h] [rbp+7h]
std::optional<std::string > box; // [rsp+90h] [rbp+17h] BYREF
unsigned __int64 maclen_p; // [rsp+F8h] [rbp+7Fh] BYREF

*&v18 = 0LL;
*&v19 = 0LL;
v6 = 15LL;
*(&v19 + 1) = 15LL;
*&box._Dummy = v18;
*&box._Value._Mypair._Myval2._Mysize = v19;
box._Has_value = 1;
std::string::resize(&box, message->length + 28, 0);
p_box = &box;
Ptr = box._Value._Mypair._Myval2._Bx._Ptr;
Myres = box._Value._Mypair._Myval2._Myres;
if ( box._Value._Mypair._Myval2._Myres >= 0x10 )
p_box = box._Value._Mypair._Myval2._Bx._Ptr;
*m = *message;
if ( !this->isError && this->isSessionReady )
{
v10 = 96LL;
if ( !this->isServer )
v10 = 64LL;
k = this + v10;
if ( box._Value._Mypair._Myval2._Mysize == m[1] + 28 )
{
v12 = &p_box->_Value._Mypair._Myval2._Bx._Buf[m[1]];
*v12 = std::_Ref_count_obj2<std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>,std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>)>,std::function<void (std::string)>)>>::`vftable'[4]
+ _InterlockedExchangeAdd64(&this->appNonce, 1uLL);
*(v12 + 2) = 1919246957;
if ( !crypto_aead_chacha20poly1305_ietf_encrypt_detached(
p_box,
&p_box->_Value._Mypair._Myval2._Bx._Buf[m[1] + 12],
&maclen_p,
m[0],
m[1],
0LL,
0LL,
0LL,
&p_box->_Value._Mypair._Myval2._Bx._Buf[m[1]],
k) )
{
result->_Has_value = 0;
Has_value = box._Has_value;
if ( box._Has_value )
{
*&result->_Dummy = *&box._Dummy;
*&result->_Value._Mypair._Myval2._Mysize = *&box._Value._Mypair._Myval2._Mysize;
box._Value._Mypair._Myval2._Mysize = 0LL;
box._Value._Mypair._Myval2._Myres = 15LL;
box._Value._Mypair._Myval2._Bx._Buf[0] = 0;
result->_Has_value = 1;
}
else
{
v6 = box._Value._Mypair._Myval2._Myres;
}
if ( Has_value && v6 >= 0x10 )
{
v14 = v6 + 1;
Ptr = box._Value._Mypair._Myval2._Bx._Ptr;
if ( v6 + 1 < 0x1000
|| (v14 = v6 + 40,
Ptr = *(box._Value._Mypair._Myval2._Bx._Ptr - 1),
(box._Value._Mypair._Myval2._Bx._Ptr - Ptr - 8) <= 0x1F) )
{
LABEL_16:
operator delete(Ptr, v14);
return result;
}
LABEL_23:
_invalid_parameter_noinfo_noreturn();
}
return result;
}
Myres = box._Value._Mypair._Myval2._Myres;
Ptr = box._Value._Mypair._Myval2._Bx._Ptr;
}
}
result->_Has_value = 0;
if ( box._Has_value && Myres >= 0x10 )
{
v14 = Myres + 1;
v16 = Ptr;
if ( v14 < 0x1000 )
goto LABEL_16;
v14 += 39LL;
Ptr = *(Ptr - 1);
if ( (v16 - Ptr - 8) <= 0x1F )
goto LABEL_16;
goto LABEL_23;
}
return result;
}

bool __fastcall RBX::Security::SessionCrypto::earlyEncryptData(
RBX::Security::SessionCrypto *this,
RBX::MutableArrayView *box,
RBX::ArrayView *message,
size_t aadSize)
{
unsigned __int8 *buffer; // rbx
__int64 v8; // rsi
const unsigned __int8 *ad; // rdi
const unsigned __int8 *k; // rsi
unsigned __int64 length; // r10
unsigned __int8 *npub; // [rsp+40h] [rbp-38h]
unsigned __int64 macLen; // [rsp+80h] [rbp+8h] BYREF

if ( this->isError || !this->isEarlySessionReady )
return 0;
buffer = box->buffer;
v8 = 160LL;
ad = message->buffer;
if ( !this->isServer )
v8 = 128LL;
k = &this->keyExchangeKeys._Mypair._Myval2->publicEphemeralKey._Elems[v8];
memcpy_0(buffer, ad, aadSize);
length = message->length;
npub = &buffer[length];
*npub = std::_Ref_count_obj2<std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>,std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>)>,std::function<void (std::string)>)>>::`vftable'[4]
+ _InterlockedExchangeAdd64(&this->appNonce, 1uLL);
*(npub + 2) = 1919246957;
return !crypto_aead_chacha20poly1305_ietf_encrypt_detached(
&buffer[aadSize],
npub + 12,
&macLen,
&ad[aadSize],
length - aadSize,
ad,
aadSize,
0LL,
npub,
k)
&& macLen == 16;
}

bool __fastcall RBX::Security::SessionCrypto::earlyDecryptData(
RBX::Security::SessionCrypto *this,
RBX::MutableArrayView *message,
RBX::ArrayView *box,
size_t aadSize)
{
unsigned __int8 *buffer; // rbx
__int64 v7; // rsi
const unsigned __int8 *ad; // rdi
const unsigned __int8 *k; // rsi

if ( this->isError || !this->isEarlySessionReady )
return 0;
buffer = message->buffer;
v7 = 128LL;
if ( !this->isServer )
v7 = 160LL;
ad = box->buffer;
k = &this->keyExchangeKeys._Mypair._Myval2->publicEphemeralKey._Elems[v7];
memcpy_0(buffer, box->buffer, aadSize);
return !crypto_aead_chacha20poly1305_ietf_decrypt_detached(
&buffer[aadSize],
0LL,
&ad[aadSize],
message->length - aadSize,
&ad[message->length + 12],
ad,
aadSize,
&ad[message->length],
k);
}

std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::decryptString(
RBX::Security::SessionCrypto *this,
std::optional<std::string > *result,
const std::string *box)
{
unsigned __int64 Mysize; // rax
RBX::ArrayView v6; // [rsp+20h] [rbp-18h] BYREF

Mysize = box->_Mypair._Myval2._Mysize;
if ( box->_Mypair._Myval2._Myres >= 0x10 )
box = box->_Mypair._Myval2._Bx._Ptr;
v6.buffer = box;
v6.length = Mysize;
RBX::Security::SessionCrypto::decryptData(this, result, &v6);
return result;
}

char __fastcall RBX::Security::SessionCrypto::decryptRakDataInPlace(
RBX::Security::SessionCrypto *this,
RBX::MutableArrayView *boxToMessage)
{
unsigned __int64 length; // r8
unsigned __int64 v4; // r9
const unsigned __int8 *buffer; // r10
int (__fastcall *v6)(unsigned __int8 *, unsigned __int8 *, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, const unsigned __int8 *); // rbp
int v7; // edi
__int64 v8; // rsi
int v9; // edi

length = boxToMessage->length;
if ( length < 0x12 )
return 0;
buffer = boxToMessage->buffer;
if ( this->isError || !this->isSessionReady )
return 0;
v6 = crypto_aead_chacha20poly1305_ietf_decrypt_detached;
v4 = length - 18;
if ( (this->rakFormat & 2) != 0 )
v6 = crypto_aead_aes256gcm_decrypt_detached;
v7 = *&buffer[v4];
v8 = *&buffer[v4];
if ( (v6)(buffer, 0LL, buffer) )
return 0;
v9 = v7 - LOWORD(this->rxRakNonce);
if ( v9 >= -32768 )
{
if ( v9 > 0 )
{
this->rxRakNonce &= 0xFFFFFFFFFFFF0000uLL;
this->rxRakNonce |= v8;
}
return 1;
}
else
{
this->rxRakNonce = v8 | (this->rxRakNonce + 0x10000) & 0xFFFFFFFFFFFF0000uLL;
return 1;
}
}

// Hidden C++ exception states: #wind=1
std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::decryptData(
RBX::Security::SessionCrypto *this,
std::optional<std::string > *result,
RBX::ArrayView *box)
{
unsigned __int64 length; // rax
unsigned __int64 v7; // r14
std::optional<std::string > *p_message; // r11
char *Ptr; // rcx
unsigned __int64 Myres; // rdx
__int64 v11; // rax
bool Has_value; // al
unsigned __int64 v13; // rdx
char *v15; // rax
unsigned __int8 *c[2]; // [rsp+50h] [rbp-9h]
unsigned __int8 *ca[2]; // [rsp+50h] [rbp-9h]
__int128 v18; // [rsp+60h] [rbp+7h]
std::optional<std::string > message; // [rsp+70h] [rbp+17h] BYREF

length = box->length;
if ( length < 0x1C )
{
result->_Has_value = 0;
return result;
}
c[0] = 0LL;
*&v18 = 0LL;
*(&v18 + 1) = 15LL;
*&message._Dummy = *c;
*&message._Value._Mypair._Myval2._Mysize = v18;
message._Has_value = 1;
v7 = length - 28;
std::string::resize(&message, length - 28, 0);
p_message = &message;
Ptr = message._Value._Mypair._Myval2._Bx._Ptr;
Myres = message._Value._Mypair._Myval2._Myres;
if ( message._Value._Mypair._Myval2._Myres >= 0x10 )
p_message = message._Value._Mypair._Myval2._Bx._Ptr;
*ca = *box;
if ( !this->isError && this->isSessionReady && v7 == ca[1] - 28 && ca[1] >= 0x1C )
{
v11 = 64LL;
if ( !this->isServer )
v11 = 96LL;
if ( !crypto_aead_chacha20poly1305_ietf_decrypt_detached(
p_message,
0LL,
ca[0],
v7,
&ca[0][v7 + 12],
0LL,
0LL,
&ca[0][v7],
this + v11) )
{
result->_Has_value = 0;
Has_value = message._Has_value;
if ( message._Has_value )
{
*&result->_Dummy = *&message._Dummy;
*&result->_Value._Mypair._Myval2._Mysize = *&message._Value._Mypair._Myval2._Mysize;
*&message._Value._Mypair._Myval2._Mysize = _mm_load_si128(&_xmm);
message._Value._Mypair._Myval2._Bx._Buf[0] = 0;
result->_Has_value = 1;
}
if ( Has_value && message._Value._Mypair._Myval2._Myres >= 0x10 )
{
v13 = message._Value._Mypair._Myval2._Myres + 1;
Ptr = message._Value._Mypair._Myval2._Bx._Ptr;
if ( message._Value._Mypair._Myval2._Myres + 1 < 0x1000
|| (v13 = message._Value._Mypair._Myval2._Myres + 40,
Ptr = *(message._Value._Mypair._Myval2._Bx._Ptr - 1),
(message._Value._Mypair._Myval2._Bx._Ptr - Ptr - 8) <= 0x1F) )
{
LABEL_18:
operator delete(Ptr, v13);
return result;
}
LABEL_25:
_invalid_parameter_noinfo_noreturn();
}
return result;
}
Myres = message._Value._Mypair._Myval2._Myres;
Ptr = message._Value._Mypair._Myval2._Bx._Ptr;
}
result->_Has_value = 0;
if ( message._Has_value && Myres >= 0x10 )
{
v13 = Myres + 1;
v15 = Ptr;
if ( v13 < 0x1000 )
goto LABEL_18;
v13 += 39LL;
Ptr = *(Ptr - 1);
if ( (v15 - Ptr - 8) <= 0x1F )
goto LABEL_18;
goto LABEL_25;
}
return result;
}

void __fastcall RBX::Security::SessionCrypto::SessionCrypto(RBX::Security::SessionCrypto *this)
{
this->__vftable = RBX::Security::SessionCrypto::`vftable';
this->appNonce._Storage._Value = 0LL;
this->txRakNonce._Storage._Value = 0LL;
this->keyExchangeKeys._Mypair._Myval2 = 0LL;
*&this->isServer = 0;
this->rakFormat = NoCrypto;
this->earlyAuthData._Ptr = 0LL;
this->earlyAuthData._Rep = 0LL;
this->rxRakNonce = 0x754E657571696E55LL;
_InterlockedExchange64(&this->txRakNonce, 0x754E657571696E55LL);
}

RBX::Security::SessionCrypto *__fastcall RBX::Security::SessionCrypto::`scalar deleting destructor'(
RBX::Security::SessionCrypto *this,
char a2)
{
RBX::Security::SessionCrypto::~SessionCrypto(this);
if ( (a2 & 1) != 0 )
operator delete(this, 0x80uLL);
return this;
}

void __fastcall RBX::Security::SessionCrypto::KeyExchangeKeys::~KeyExchangeKeys(
RBX::Security::SessionCrypto::KeyExchangeKeys *this)
{
sodium_memzero(&this->secretEphemeralKey, 0x20uLL);
sodium_memzero(&this->publicEarlyKey, 0x20uLL);
sodium_memzero(&this->secretEarlyKey, 0x20uLL);
sodium_memzero(&this->earlySessionKeyClientToServer, 0x20uLL);
sodium_memzero(&this->earlySessionKeyServerToClient, 0x20uLL);
}

FF enum __shex RBX::Security::SessionCrypto::CryptoFormat : __int8
FF { // XREF: RBX::Security::SessionCrypto/r
FF NoCrypto = 0x0,
FF ChaCha20Poly1305Ietf = 0x1,
FF Aes256Gcm = 0x2,
FF TestMask = -0x80,
FF TestChaCha20Poly1305Ietf = -0x7F,
FF TestAes256Gcm = -0x7E,
FF };

00000000 struct __cppobj RBX::Security::SessionCrypto::KeyExchangeKeys // sizeof=0xE0
00000000 {
00000000 std::array<unsigned char,32> publicEphemeralKey;
00000020 std::array<unsigned char,32> secretEphemeralKey;
00000040 std::array<unsigned char,32> publicEarlyKey;
00000060 std::array<unsigned char,32> secretEarlyKey;
00000080 std::array<unsigned char,32> earlySessionKeyClientToServer;
000000A0 std::array<unsigned char,32> earlySessionKeyServerToClient;
000000C0 std::array<unsigned char,32> peerPublicEphemeralKey;
000000E0 };

00000000 struct __cppobj __declspec(align(8)) RBX::Security::EarlyAuthData // sizeof=0x48
00000000 {
00000000 std::string preauthBlob;
00000020 std::string authBlob;
00000040 unsigned __int8 authVersion;
00000041 // padding byte
00000042 // padding byte
00000043 // padding byte
00000044 // padding byte
00000045 // padding byte
00000046 // padding byte
00000047 // padding byte
00000048 };

00000000 struct __cppobj std::_Ptr_baseRBX::Security::EarlyAuthData // sizeof=0x10
00000000 { // XREF: std::shared_ptrRBX::Security::EarlyAuthData/r
00000000 RBX::Security::EarlyAuthData *_Ptr; // XREF: RBX::Network::Client::setTicket(std::string const &):loc_1411932AA/w
00000008 std::_Ref_count_base *_Rep; // XREF: RBX::Network::Client::setTicket(std::string const &)+11F/w
00000008 // RakNet::RakPeer::processRbxOpenRequest2(uchar const *,unsigned __int64,RakNet::SystemAddress const &,RakNet::SystemAddress const &,std::shared_ptrRakNet::RakNetSocket &,ushort,RBX::StringView)+8C/w ...
00000010 };

00000000 struct __cppobj RBX::Security::SessionCrypto // sizeof=0x80
00000000 { // XREF: RBX::Security::RakPeerCrypto/r
00000000 // RBX::Security::HeartbeatBlobCrypto/r
00000000 RBX::Security::SessionCrypto_vtbl *__vftable;
00000008 std::atomic appNonce;
00000010 std::atomic txRakNonce;
00000018 unsigned __int64 rxRakNonce;
00000020 std::unique_ptrRBX::Security::SessionCrypto::KeyExchangeKeys keyExchangeKeys;
00000028 bool isServer;
00000029 bool isEarlySessionReady;
0000002A bool isSessionReady;
0000002B bool isError;
0000002C RBX::Security::SessionCrypto::CryptoFormat rakFormat;
0000002D // padding byte
0000002E // padding byte
0000002F // padding byte
00000030 std::shared_ptrRBX::Security::EarlyAuthData earlyAuthData;
00000040 std::array<unsigned char,32> sessionKeyClientToServer;
00000060 std::array<unsigned char,32> sessionKeyServerToClient;
00000080 };

Using this information. Write a session_crypto in rust. A full implementation. Reverse engineer the psuedocode and use anything to help you.