2020-04-20 21:11:02 +00:00
|
|
|
#include "LocalKeyGenerator.h"
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
|
|
|
#include <cstring>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
#include "LocalKeys.h"
|
|
|
|
#include "Utils.h"
|
|
|
|
|
|
|
|
//check functions are based on code provided by Proxima
|
|
|
|
|
|
|
|
int check_sealedkey(std::shared_ptr<ICryptoOperations> cryptops, sealedkey_t& sk)
|
|
|
|
{
|
|
|
|
std::uint8_t result[0x20];
|
|
|
|
|
|
|
|
if(std::string((char*)sk.magic, 8) != SEALEDKEY_MAGIC)
|
|
|
|
{
|
|
|
|
std::cout << "sealedkey: invalid magic" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sk.type_major != SEALEDKEY_EXPECTED_TYPE_MAJOR)
|
|
|
|
{
|
|
|
|
std::cout << "sealedkey: invalid type_major" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
2021-05-27 23:37:57 +00:00
|
|
|
|
2020-04-20 21:11:02 +00:00
|
|
|
if(sk.type_minor != SEALEDKEY_EXPECTED_TYPE_MINOR)
|
|
|
|
{
|
|
|
|
std::cout << "sealedkey: invalid type_minor" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!isZeroVector(sk.padding, sk.padding + sizeof(sk.padding)))
|
|
|
|
{
|
|
|
|
std::cout << "sealedkey: invalid padding" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cryptops->hmac_sha256((unsigned char*)&sk, result, 0x30, sealedkey_retail_key, 0x10);
|
2021-05-27 23:37:57 +00:00
|
|
|
if(memcmp(sk.hmac, result, 0x20) == 0)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "sealedkey: matched retail hmac" << std::endl;
|
|
|
|
return 0;
|
2021-05-27 23:37:57 +00:00
|
|
|
}
|
|
|
|
else
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
cryptops->hmac_sha256((unsigned char*)&sk, result, 0x30, sealedkey_debug_key, 0x10);
|
2021-05-27 23:37:57 +00:00
|
|
|
if(memcmp(sk.hmac, result, 0x20) == 0)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "sealedkey: matched debug hmac" << std::endl;
|
|
|
|
return 0;
|
2021-05-27 23:37:57 +00:00
|
|
|
}
|
|
|
|
else
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "sealedkey: failed to match hmac" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int check_keystone(std::shared_ptr<ICryptoOperations> cryptops, keystone_t& ks)
|
|
|
|
{
|
|
|
|
std::uint8_t result[0x20];
|
|
|
|
|
|
|
|
if(std::string((char*)ks.magic, 8) != KEYSTONE_MAGIC)
|
|
|
|
{
|
|
|
|
std::cout << "keystone: invalid magic" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ks.type != KEYSTONE_EXPECTED_TYPE)
|
|
|
|
{
|
|
|
|
std::cout << "keystone: invalid type" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
2021-05-27 23:37:57 +00:00
|
|
|
|
2020-04-20 21:11:02 +00:00
|
|
|
if(ks.version != KEYSTONE_EXPECTED_VERSION)
|
|
|
|
{
|
|
|
|
std::cout << "keystone: invalid version" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!isZeroVector(ks.padding, ks.padding + sizeof(ks.padding)))
|
|
|
|
{
|
|
|
|
std::cout << "keystone: invalid padding" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cryptops->hmac_sha256((unsigned char*)&ks, result, 0x40, keystone_hmac_secret, 0x20);
|
2021-05-27 23:37:57 +00:00
|
|
|
if(memcmp(ks.keystone_hmac, result, 0x20) == 0)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "keystone: matched retail hmac" << std::endl;
|
|
|
|
return 0;
|
2021-05-27 23:37:57 +00:00
|
|
|
}
|
|
|
|
else
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
cryptops->hmac_sha256((unsigned char*)&ks, result, 0x40, keystone_debug_key, 0x20);
|
2021-05-27 23:37:57 +00:00
|
|
|
if(memcmp(ks.keystone_hmac, result, 0x20) == 0)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "keystone: matched debug hmac!" << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << "keystone: failed to match hmac" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int check_keystone(std::shared_ptr<ICryptoOperations> cryptops, keystone_t& ks, unsigned char* passcode)
|
|
|
|
{
|
|
|
|
if(check_keystone(cryptops, ks) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
std::uint8_t result[0x20];
|
|
|
|
|
|
|
|
cryptops->hmac_sha256(passcode, result, 0x20, passcode_hmac_secret, 0x20);
|
2021-05-27 23:37:57 +00:00
|
|
|
if(memcmp(ks.passcode_hmac, result, 0x20) == 0)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "keystone: matched passcode hmac" << std::endl;
|
|
|
|
return 0;
|
2021-05-27 23:37:57 +00:00
|
|
|
}
|
|
|
|
else
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
cryptops->hmac_sha256(passcode, result, 0x20, passcode_debug_key, 0x20);
|
2021-05-27 23:37:57 +00:00
|
|
|
if(memcmp(ks.passcode_hmac, result, 0x20) == 0)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "keystone: matched debug passcode hmac!" << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << "keystone: failed to match passcode hmac" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//public functions
|
|
|
|
|
2024-01-13 13:40:12 +00:00
|
|
|
int get_sealedkey(std::shared_ptr<ICryptoOperations> cryptops, const psvpfs::path& titleIdPath, unsigned char* dec_key)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
2024-01-13 13:40:12 +00:00
|
|
|
psvpfs::path filepath = titleIdPath / "sce_sys" / "sealedkey";
|
2020-04-20 21:11:02 +00:00
|
|
|
|
2021-05-27 23:37:57 +00:00
|
|
|
if(!psvpfs::exists(filepath))
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "sealedkey does not exist" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sealedkey_t sk;
|
|
|
|
|
|
|
|
std::ifstream inputStream(filepath.generic_string().c_str(), std::ios::in | std::ios::binary);
|
|
|
|
inputStream.read((char*)&sk, sizeof(sealedkey_t));
|
|
|
|
|
|
|
|
if(check_sealedkey(cryptops, sk) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
cryptops->aes_cbc_decrypt(sk.enc_key, dec_key, sizeof(sk.enc_key), PFS_EncKey, 128, sk.iv);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-01-13 13:40:12 +00:00
|
|
|
int get_keystone(std::shared_ptr<ICryptoOperations> cryptops, const psvpfs::path& titleIdPath, char* passcode)
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
2024-01-13 13:40:12 +00:00
|
|
|
psvpfs::path filepath = titleIdPath / "sce_sys" / "keystone";
|
2020-04-20 21:11:02 +00:00
|
|
|
|
2021-05-27 23:37:57 +00:00
|
|
|
if(!psvpfs::exists(filepath))
|
2020-04-20 21:11:02 +00:00
|
|
|
{
|
|
|
|
std::cout << "keystone does not exist" << std::endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
keystone_t ks;
|
|
|
|
|
|
|
|
std::ifstream inputStream(filepath.generic_string().c_str(), std::ios::in | std::ios::binary);
|
|
|
|
inputStream.read((char*)&ks, 0x60);
|
|
|
|
|
|
|
|
if(passcode == 0)
|
|
|
|
return check_keystone(cryptops, ks);
|
|
|
|
else
|
|
|
|
return check_keystone(cryptops, ks, (unsigned char*)passcode);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|