add support for modified BB encryption

This commit is contained in:
Martin Michelsen
2022-04-09 21:52:18 -07:00
parent 87b80b3c99
commit a078c9f712
3 changed files with 34 additions and 15 deletions
+29 -13
View File
@@ -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<uint32_t*>(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<uint8_t*>(vdata);
uint32_t* data = reinterpret_cast<uint32_t*>(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<uint32_t> 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<uint32_t> 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<const uint8_t*>(
original_seed);
@@ -295,8 +302,19 @@ vector<uint32_t> PSOBBEncryption::generate_stream(
seed.push_back(original_seed_data[x + 2] ^ 0x18);
}
vector<uint32_t> 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<uint32_t> PSOBBEncryption::generate_stream(
ecx = 0;
ebx = 0;
while (ebx < (seed.size() / 4)) {
while (ebx < 0x12) {
ebp = static_cast<uint32_t>(seed[ecx]) << 0x18;
eax = ecx + 1;
edx = eax % seed.size();
eax = (static_cast<uint32_t>(seed[edx]) << 0x10) & 0xFF0000;
eax = (static_cast<uint32_t>(seed[edx]) << 0x10) & 0x00FF0000;
ebp = (ebp | eax) & 0xFFFF00FF;
eax = ecx + 2;
edx = eax % seed.size();
eax = (static_cast<uint32_t>(seed[edx]) << 0x08) & 0xFF00;
eax = (static_cast<uint32_t>(seed[edx]) << 0x08) & 0x0000FF00;
ebp = (ebp | eax) & 0xFFFFFF00;
eax = ecx + 3;
ecx = ecx + 4;
edx = eax % seed.size();
eax = static_cast<uint32_t>(seed[edx]);
eax = static_cast<uint32_t>(seed[edx]) & 0x000000FF;
ebp = ebp | eax;
eax = ecx;
edx = eax % seed.size();
@@ -488,5 +506,3 @@ vector<uint32_t> PSOBBEncryption::generate_stream(
return stream;
}
void PSOBBEncryption::skip(size_t) { }
+5 -2
View File
@@ -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);
Binary file not shown.