mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-06 11:01:38 +12:00
feat: crypto: Add basic AES keyslot manager
We loads keys from AppData/Alber/sysdata/aes_keys.txt. NOTE: We do differ from other emulators by not hardcoding the generator key, it's the user responsibility to provide it in aes_keys.txt.
This commit is contained in:
parent
bf85b405af
commit
2e5bc0cb14
6 changed files with 280 additions and 2 deletions
84
src/core/crypto/aes_engine.cpp
Normal file
84
src/core/crypto/aes_engine.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "crypto/aes_engine.hpp"
|
||||
#include "helpers.hpp"
|
||||
|
||||
namespace Crypto {
|
||||
void AESEngine::loadKeys(const std::filesystem::path& path) {
|
||||
std::ifstream file(path, std::ios::in);
|
||||
|
||||
if (file.fail()) {
|
||||
Helpers::warn("keys: Couldn't read key file: %s", path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
while (!file.eof()) {
|
||||
std::string line;
|
||||
|
||||
std::getline(file, line);
|
||||
|
||||
// Skip obvious invalid lines
|
||||
if (line.empty() || line.starts_with("#")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto parts = Helpers::split(line, '=');
|
||||
|
||||
if (parts.size() != 2) {
|
||||
Helpers::warn("keys: Failed to parse %s", line.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string& name = parts[0];
|
||||
const std::string& rawKeyHex = parts[1];
|
||||
|
||||
std::size_t slotId;
|
||||
char keyType;
|
||||
|
||||
bool is_generator = name == "generator";
|
||||
|
||||
if (!is_generator && std::sscanf(name.c_str(), "slot0x%zXKey%c", &slotId, &keyType) != 2) {
|
||||
Helpers::warn("keys: Ignoring unknown key %s", name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto key = createKeyFromHex(rawKeyHex);
|
||||
|
||||
if (!key.has_value()) {
|
||||
Helpers::warn("keys: Failed to parse raw key %s", rawKeyHex.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_generator) {
|
||||
m_generator = key;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (slotId >= AesKeySlotCount) {
|
||||
Helpers::warn("keys: Invalid key slot id %u", slotId);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (keyType) {
|
||||
case 'X':
|
||||
setKeyX(slotId, key.value());
|
||||
break;
|
||||
case 'Y':
|
||||
setKeyY(slotId, key.value());
|
||||
break;
|
||||
case 'N':
|
||||
setNormalKey(slotId, key.value());
|
||||
break;
|
||||
default:
|
||||
Helpers::warn("keys: Invalid key type %c", keyType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// As the generator key can be set at any time, force update all normal keys.
|
||||
for (std::size_t i = 0; i < AesKeySlotCount; i++) {
|
||||
updateNormalKey(i);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -135,8 +135,15 @@ bool Emulator::loadROM(const std::filesystem::path& path) {
|
|||
// Inside that path, we be use a game-specific folder as well. Eg if we were loading a ROM called PenguinDemo.3ds, the savedata would be in
|
||||
// %APPDATA%/Alber/PenguinDemo/SaveData on Windows, and so on. We do this because games save data in their own filesystem on the cart
|
||||
char* appData = SDL_GetPrefPath(nullptr, "Alber");
|
||||
const std::filesystem::path dataPath = std::filesystem::path(appData) / path.filename().stem();
|
||||
const std::filesystem::path appDataPath = std::filesystem::path(appData);
|
||||
const std::filesystem::path dataPath = appDataPath / path.filename().stem();
|
||||
const std::filesystem::path aesKeysPath = appDataPath / "sysdata" / "aes_keys.txt";
|
||||
IOFile::setAppDataDir(dataPath);
|
||||
|
||||
if (std::filesystem::exists(aesKeysPath)) {
|
||||
aesEngine.loadKeys(aesKeysPath);
|
||||
}
|
||||
|
||||
SDL_free(appData);
|
||||
|
||||
kernel.initializeFS();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue