Fix a long-standing buffer overflow in savedata encryption

BuildHash pads the buffer up to its 16-byte aligned size with zeroes,
so there needs to be space for that. Or, we should just remove that
write, but let's do the smallest change that fixes the bug for now.
This commit is contained in:
Henrik Rydgård 2024-04-07 11:37:35 +02:00
parent 654c16f5f3
commit 77133dd82c
3 changed files with 9 additions and 8 deletions

View File

@ -473,7 +473,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD
u8 *data_ = param->dataBuf;
int aligned_len = align16(cryptedSize);
cryptedData = new u8[aligned_len + 0x10];
cryptedData = new u8[aligned_len + 0x10]{};
memcpy(cryptedData, data_, cryptedSize);
int decryptMode = DetermineCryptMode(param);

View File

@ -219,7 +219,7 @@ int ParamSFOData::GetDataOffset(const u8 *paramsfo, const std::string &dataName)
return -1;
}
bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) const {
void ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) const {
size_t total_size = 0;
size_t key_size = 0;
size_t data_size = 0;
@ -251,9 +251,10 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) const {
total_size += data_size;
*size = total_size;
u8* data = new u8[total_size];
size_t aligned_size = (total_size + 15) & ~15;
u8* data = new u8[aligned_size];
*paramsfo = data;
memset(data, 0, total_size);
memset(data, 0, aligned_size);
memcpy(data, &header, sizeof(Header));
// Now fill
@ -300,8 +301,6 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) const {
index_ptr++;
}
return true;
}
void ParamSFOData::Clear() {

View File

@ -42,9 +42,11 @@ public:
std::string GetDiscID();
bool ReadSFO(const u8 *paramsfo, size_t size);
bool WriteSFO(u8 **paramsfo, size_t *size) const;
// This allocates a buffer (*paramsfo) using new[], whose size is zero-filled up to a multiple of 16 bytes.
// This is required for SavedataParam::BuildHash.
void WriteSFO(u8 **paramsfo, size_t *size) const;
bool ReadSFO(const u8 *paramsfo, size_t size);
bool ReadSFO(const std::vector<u8> &paramsfo) {
if (!paramsfo.empty()) {
return ReadSFO(&paramsfo[0], paramsfo.size());