From 77cea58fc5a5abe531d10134c52fde17eda8b5b3 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 24 Aug 2022 00:48:49 -0700 Subject: [PATCH] clean up big-endian encryption --- src/PSOEncryption.cc | 26 ++++++++++++++++++++++---- src/PSOEncryption.hh | 8 ++++++++ src/SendCommands.cc | 10 +--------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/PSOEncryption.cc b/src/PSOEncryption.cc index ca168069..f7db03e6 100644 --- a/src/PSOEncryption.cc +++ b/src/PSOEncryption.cc @@ -81,7 +81,8 @@ uint32_t PSOV2Encryption::next(bool advance) { return ret; } -void PSOV2Encryption::encrypt(void* vdata, size_t size, bool advance) { +template +void PSOV2Encryption::encrypt_t(void* vdata, size_t size, bool advance) { if (size & 3) { throw invalid_argument("size must be a multiple of 4"); } @@ -90,12 +91,20 @@ void PSOV2Encryption::encrypt(void* vdata, size_t size, bool advance) { } size >>= 2; - le_uint32_t* data = reinterpret_cast(vdata); + LongT* data = reinterpret_cast(vdata); for (size_t x = 0; x < size; x++) { data[x] ^= this->next(advance); } } +void PSOV2Encryption::encrypt(void* vdata, size_t size, bool advance) { + this->encrypt_t(vdata, size, advance); +} + +void PSOV2Encryption::encrypt_big_endian(void* vdata, size_t size, bool advance) { + this->encrypt_t(vdata, size, advance); +} + void PSOV3Encryption::update_stream() { @@ -158,7 +167,8 @@ PSOV3Encryption::PSOV3Encryption(uint32_t seed) : offset(0) { } } -void PSOV3Encryption::encrypt(void* vdata, size_t size, bool advance) { +template +void PSOV3Encryption::encrypt_t(void* vdata, size_t size, bool advance) { if (size & 3) { throw invalid_argument("size must be a multiple of 4"); } @@ -167,12 +177,20 @@ void PSOV3Encryption::encrypt(void* vdata, size_t size, bool advance) { } size >>= 2; - le_uint32_t* data = reinterpret_cast(vdata); + LongT* data = reinterpret_cast(vdata); for (size_t x = 0; x < size; x++) { data[x] ^= this->next(advance); } } +void PSOV3Encryption::encrypt(void* vdata, size_t size, bool advance) { + this->encrypt_t(vdata, size, advance); +} + +void PSOV3Encryption::encrypt_big_endian(void* vdata, size_t size, bool advance) { + this->encrypt_t(vdata, size, advance); +} + void PSOBBEncryption::decrypt(void* vdata, size_t size, bool advance) { diff --git a/src/PSOEncryption.hh b/src/PSOEncryption.hh index 725ebb64..2fc4b3d8 100644 --- a/src/PSOEncryption.hh +++ b/src/PSOEncryption.hh @@ -39,10 +39,14 @@ public: explicit PSOV2Encryption(uint32_t seed); virtual void encrypt(void* data, size_t size, bool advance = true); + void encrypt_big_endian(void* data, size_t size, bool advance = true); uint32_t next(bool advance = true); protected: + template + void encrypt_t(void* data, size_t size, bool advance); + void update_stream(); uint32_t stream[V2_STREAM_LENGTH + 1]; @@ -54,10 +58,14 @@ public: explicit PSOV3Encryption(uint32_t key); virtual void encrypt(void* data, size_t size, bool advance = true); + void encrypt_big_endian(void* data, size_t size, bool advance = true); uint32_t next(bool advance = true); protected: + template + void encrypt_t(void* data, size_t size, bool advance); + void update_stream(); uint32_t stream[V3_STREAM_LENGTH]; diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 938caf89..e5d5b648 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -254,15 +254,7 @@ void send_function_call( data.resize((data.size() + 3) & ~3); PSOV2Encryption crypt(key); if (code->is_big_endian()) { - // The code section is decrypted without byteswapping on the client. - // Since PowerPC systems (including the GameCube) are usually - // big-endian, we have to treat the data the same way here (hence we - // can't just use crypt.encrypt). - StringReader compressed_r(data); - while (!compressed_r.eof()) { - w.put_u32b(compressed_r.get_u32b() ^ crypt.next()); - } - data = move(w.str()); + crypt.encrypt_big_endian(data.data(), data.size()); } else { crypt.encrypt(data.data(), data.size()); }