diff --git a/src/PSOEncryption.cc b/src/PSOEncryption.cc index 21ef2cce..3c325151 100644 --- a/src/PSOEncryption.cc +++ b/src/PSOEncryption.cc @@ -210,7 +210,7 @@ void PSOBBEncryption::decrypt(void* vdata, size_t size, bool) { if (size & 7) { throw invalid_argument("size must be a multiple of 8"); } - size >>= 3; + size >>= 2; uint32_t* data = reinterpret_cast(vdata); uint32_t edx, ebx, ebp, esi, edi; @@ -245,15 +245,14 @@ void PSOBBEncryption::encrypt(void* vdata, size_t size, bool) { if (size & 7) { throw invalid_argument("size must be a multiple of 8"); } - size >>= 3; + size >>= 2; - uint8_t* data = reinterpret_cast(vdata); + uint32_t* data = reinterpret_cast(vdata); uint32_t edx, ebx, ebp, esi, edi; edx = 0; while (edx < size) { - ebx = data[edx]; - ebx = ebx ^ this->stream[0]; + ebx = data[edx] ^ this->stream[0]; ebp = ((this->stream[(ebx >> 0x18) + 0x12] + this->stream[((ebx >> 0x10) & 0xFF) + 0x112]) ^ this->stream[((ebx >> 0x8) & 0xFF) + 0x212]) + this->stream[(ebx & 0xFF) + 0x312]; ebp = ebp ^ this->stream[1]; @@ -276,16 +275,24 @@ void PSOBBEncryption::encrypt(void* vdata, size_t size, bool) { } } +void PSOBBEncryption::skip(size_t) { } + PSOBBEncryption::PSOBBEncryption( const KeyFile& key, const void* original_seed, size_t seed_size) : stream(this->generate_stream(key, original_seed, seed_size)) { } + + vector PSOBBEncryption::generate_stream( const KeyFile& key, const void* original_seed, size_t seed_size) { if (seed_size % 3) { throw invalid_argument("seed size must be divisible by 3"); } + vector stream(BB_STREAM_LENGTH, 0); + + // Note: This part is done in the 03 command handler in the BB client, and + // isn't actually part of the encryption library. (Why did they do this?) string seed; const uint8_t* original_seed_data = reinterpret_cast( original_seed); @@ -295,8 +302,19 @@ vector PSOBBEncryption::generate_stream( seed.push_back(original_seed_data[x + 2] ^ 0x18); } - vector stream(BB_STREAM_LENGTH, 0); - memcpy(stream.data(), &key, sizeof(key)); + if (key.is_modcrypt) { + for (size_t x = 0; x < 0x12; x++) { + uint8_t a = key.initial_keys[4 * x + 0]; + uint8_t b = key.initial_keys[4 * x + 1]; + uint8_t c = key.initial_keys[4 * x + 2]; + uint8_t d = key.initial_keys[4 * x + 3]; + stream[x] = ((a ^ d) << 24) | ((b ^ c) << 16) | (a << 8) | b; + } + memcpy(stream.data() + 0x12, &key.private_keys, sizeof(key.private_keys)); + + } else { + memcpy(stream.data(), &key, sizeof(key)); + } // This block was formerly postprocess_initial_stream { @@ -305,20 +323,20 @@ vector PSOBBEncryption::generate_stream( ecx = 0; ebx = 0; - while (ebx < (seed.size() / 4)) { + while (ebx < 0x12) { ebp = static_cast(seed[ecx]) << 0x18; eax = ecx + 1; edx = eax % seed.size(); - eax = (static_cast(seed[edx]) << 0x10) & 0xFF0000; + eax = (static_cast(seed[edx]) << 0x10) & 0x00FF0000; ebp = (ebp | eax) & 0xFFFF00FF; eax = ecx + 2; edx = eax % seed.size(); - eax = (static_cast(seed[edx]) << 0x08) & 0xFF00; + eax = (static_cast(seed[edx]) << 0x08) & 0x0000FF00; ebp = (ebp | eax) & 0xFFFFFF00; eax = ecx + 3; ecx = ecx + 4; edx = eax % seed.size(); - eax = static_cast(seed[edx]); + eax = static_cast(seed[edx]) & 0x000000FF; ebp = ebp | eax; eax = ecx; edx = eax % seed.size(); @@ -488,5 +506,3 @@ vector PSOBBEncryption::generate_stream( return stream; } - -void PSOBBEncryption::skip(size_t) { } diff --git a/src/PSOEncryption.hh b/src/PSOEncryption.hh index 89accd5d..aca42994 100644 --- a/src/PSOEncryption.hh +++ b/src/PSOEncryption.hh @@ -65,8 +65,11 @@ protected: class PSOBBEncryption : public PSOEncryption { public: struct KeyFile { - uint32_t initial_keys[18]; - uint32_t private_keys[1024]; + // initial_keys are actually a stream of uint32_ts, but we treat them as + // bytes for code simplicity + uint8_t initial_keys[0x12 * 4]; + uint32_t private_keys[0x400]; + uint8_t is_modcrypt; } __attribute__((packed)); PSOBBEncryption(const KeyFile& key, const void* seed, size_t seed_size); diff --git a/system/blueburst/keys/default.nsk b/system/blueburst/keys/default.nsk index 38e50719..24b675c8 100755 Binary files a/system/blueburst/keys/default.nsk and b/system/blueburst/keys/default.nsk differ