@ -96,13 +96,13 @@ u64 GetSignatureTypePaddingSize(SignatureType type) {
}
SignatureType Ticket : : GetSignatureType ( ) const {
if ( auto ticket = std : : get_if < RSA4096Ticket > ( & data ) ) {
if ( const auto* ticket = std : : get_if < RSA4096Ticket > ( & data ) ) {
return ticket - > sig_type ;
}
if ( auto ticket = std : : get_if < RSA2048Ticket > ( & data ) ) {
if ( const auto* ticket = std : : get_if < RSA2048Ticket > ( & data ) ) {
return ticket - > sig_type ;
}
if ( auto ticket = std : : get_if < ECDSATicket > ( & data ) ) {
if ( const auto* ticket = std : : get_if < ECDSATicket > ( & data ) ) {
return ticket - > sig_type ;
}
@ -110,13 +110,13 @@ SignatureType Ticket::GetSignatureType() const {
}
TicketData & Ticket : : GetData ( ) {
if ( auto ticket = std : : get_if < RSA4096Ticket > ( & data ) ) {
if ( auto * ticket = std : : get_if < RSA4096Ticket > ( & data ) ) {
return ticket - > data ;
}
if ( auto ticket = std : : get_if < RSA2048Ticket > ( & data ) ) {
if ( auto * ticket = std : : get_if < RSA2048Ticket > ( & data ) ) {
return ticket - > data ;
}
if ( auto ticket = std : : get_if < ECDSATicket > ( & data ) ) {
if ( auto * ticket = std : : get_if < ECDSATicket > ( & data ) ) {
return ticket - > data ;
}
@ -124,13 +124,13 @@ TicketData& Ticket::GetData() {
}
const TicketData & Ticket : : GetData ( ) const {
if ( auto ticket = std : : get_if < RSA4096Ticket > ( & data ) ) {
if ( const auto* ticket = std : : get_if < RSA4096Ticket > ( & data ) ) {
return ticket - > data ;
}
if ( auto ticket = std : : get_if < RSA2048Ticket > ( & data ) ) {
if ( const auto* ticket = std : : get_if < RSA2048Ticket > ( & data ) ) {
return ticket - > data ;
}
if ( auto ticket = std : : get_if < ECDSATicket > ( & data ) ) {
if ( const auto* ticket = std : : get_if < ECDSATicket > ( & data ) ) {
return ticket - > data ;
}
@ -233,8 +233,9 @@ void KeyManager::DeriveGeneralPurposeKeys(std::size_t crypto_revision) {
}
RSAKeyPair < 2048 > KeyManager : : GetETicketRSAKey ( ) const {
if ( IsAllZeroArray ( eticket_extended_kek ) | | ! HasKey ( S128KeyType : : ETicketRSAKek ) )
if ( IsAllZeroArray ( eticket_extended_kek ) | | ! HasKey ( S128KeyType : : ETicketRSAKek ) ) {
return { } ;
}
const auto eticket_final = GetKey ( S128KeyType : : ETicketRSAKek ) ;
@ -261,27 +262,30 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source)
}
std : : optional < Key128 > DeriveSDSeed ( ) {
const FileUtil : : IOFile save_43 ( FileUtil : : GetUserPath ( FileUtil : : UserPath : : NANDDir ) +
" /system/save/8000000000000043 " ,
" rb+ " ) ;
if ( ! save_43 . IsOpen ( ) )
return { } ;
const Common : : FS : : IOFile save_43 ( Common : : FS : : GetUserPath ( Common : : FS : : UserPath : : NANDDir ) +
" /system/save/8000000000000043 " ,
" rb+ " ) ;
if ( ! save_43 . IsOpen ( ) ) {
return std : : nullopt ;
}
const FileUtil : : IOFile sd_private (
FileUtil : : GetUserPath ( FileUtil : : UserPath : : SDMCDir ) + " /Nintendo/Contents/private " , " rb+ " ) ;
if ( ! sd_private . IsOpen ( ) )
return { } ;
const Common : : FS : : IOFile sd_private ( Common : : FS : : GetUserPath ( Common : : FS : : UserPath : : SDMCDir ) +
" /Nintendo/Contents/private " ,
" rb+ " ) ;
if ( ! sd_private . IsOpen ( ) ) {
return std : : nullopt ;
}
std : : array < u8 , 0x10 > private_seed { } ;
if ( sd_private . ReadBytes ( private_seed . data ( ) , private_seed . size ( ) ) ! = private_seed . size ( ) ) {
return { } ;
return std : : nullopt ;
}
std : : array < u8 , 0x10 > buffer { } ;
std : : size_t offset = 0 ;
for ( ; offset + 0x10 < save_43 . GetSize ( ) ; + + offset ) {
if ( ! save_43 . Seek ( offset , SEEK_SET ) ) {
return { } ;
return std : : nullopt ;
}
save_43 . ReadBytes ( buffer . data ( ) , buffer . size ( ) ) ;
@ -291,23 +295,26 @@ std::optional<Key128> DeriveSDSeed() {
}
if ( ! save_43 . Seek ( offset + 0x10 , SEEK_SET ) ) {
return { } ;
return std : : nullopt ;
}
Key128 seed { } ;
if ( save_43 . ReadBytes ( seed . data ( ) , seed . size ( ) ) ! = seed . size ( ) ) {
return { } ;
return std : : nullopt ;
}
return seed ;
}
Loader : : ResultStatus DeriveSDKeys ( std : : array < Key256 , 2 > & sd_keys , KeyManager & keys ) {
if ( ! keys . HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : SDKek ) ) )
if ( ! keys . HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : SDKek ) ) ) {
return Loader : : ResultStatus : : ErrorMissingSDKEKSource ;
if ( ! keys . HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : AESKekGeneration ) ) )
}
if ( ! keys . HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : AESKekGeneration ) ) ) {
return Loader : : ResultStatus : : ErrorMissingAESKEKGenerationSource ;
if ( ! keys . HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : AESKeyGeneration ) ) )
}
if ( ! keys . HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : AESKeyGeneration ) ) ) {
return Loader : : ResultStatus : : ErrorMissingAESKeyGenerationSource ;
}
const auto sd_kek_source =
keys . GetKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : SDKek ) ) ;
@ -320,14 +327,17 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
GenerateKeyEncryptionKey ( sd_kek_source , master_00 , aes_kek_gen , aes_key_gen ) ;
keys . SetKey ( S128KeyType : : SDKek , sd_kek ) ;
if ( ! keys . HasKey ( S128KeyType : : SDSeed ) )
if ( ! keys . HasKey ( S128KeyType : : SDSeed ) ) {
return Loader : : ResultStatus : : ErrorMissingSDSeed ;
}
const auto sd_seed = keys . GetKey ( S128KeyType : : SDSeed ) ;
if ( ! keys . HasKey ( S256KeyType : : SDKeySource , static_cast < u64 > ( SDKeyType : : Save ) ) )
if ( ! keys . HasKey ( S256KeyType : : SDKeySource , static_cast < u64 > ( SDKeyType : : Save ) ) ) {
return Loader : : ResultStatus : : ErrorMissingSDSaveKeySource ;
if ( ! keys . HasKey ( S256KeyType : : SDKeySource , static_cast < u64 > ( SDKeyType : : NCA ) ) )
}
if ( ! keys . HasKey ( S256KeyType : : SDKeySource , static_cast < u64 > ( SDKeyType : : NCA ) ) ) {
return Loader : : ResultStatus : : ErrorMissingSDNCAKeySource ;
}
std : : array < Key256 , 2 > sd_key_sources {
keys . GetKey ( S256KeyType : : SDKeySource , static_cast < u64 > ( SDKeyType : : Save ) ) ,
@ -336,8 +346,9 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
// Combine sources and seed
for ( auto & source : sd_key_sources ) {
for ( std : : size_t i = 0 ; i < source . size ( ) ; + + i )
for ( std : : size_t i = 0 ; i < source . size ( ) ; + + i ) {
source [ i ] ^ = sd_seed [ i & 0xF ] ;
}
}
AESCipher < Key128 > cipher ( sd_kek , Mode : : ECB ) ;
@ -355,9 +366,10 @@ Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& ke
return Loader : : ResultStatus : : Success ;
}
std : : vector < Ticket > GetTicketblob ( const FileUtil : : IOFile & ticket_save ) {
if ( ! ticket_save . IsOpen ( ) )
std : : vector < Ticket > GetTicketblob ( const Common: : FS : : IOFile & ticket_save ) {
if ( ! ticket_save . IsOpen ( ) ) {
return { } ;
}
std : : vector < u8 > buffer ( ticket_save . GetSize ( ) ) ;
if ( ticket_save . ReadBytes ( buffer . data ( ) , buffer . size ( ) ) ! = buffer . size ( ) ) {
@ -417,7 +429,7 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
offset = i + 1 ;
break ;
} else if ( data [ i ] ! = 0x0 ) {
return { } ;
return std : : nullopt ;
}
}
@ -427,16 +439,18 @@ static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
std : : optional < std : : pair < Key128 , Key128 > > ParseTicket ( const Ticket & ticket ,
const RSAKeyPair < 2048 > & key ) {
const auto issuer = ticket . GetData ( ) . issuer ;
if ( IsAllZeroArray ( issuer ) )
return { } ;
if ( IsAllZeroArray ( issuer ) ) {
return std : : nullopt ;
}
if ( issuer [ 0 ] ! = ' R ' | | issuer [ 1 ] ! = ' o ' | | issuer [ 2 ] ! = ' o ' | | issuer [ 3 ] ! = ' t ' ) {
LOG_INFO ( Crypto , " Attempting to parse ticket with non-standard certificate authority. " ) ;
}
Key128 rights_id = ticket . GetData ( ) . rights_id ;
if ( rights_id = = Key128 { } )
return { } ;
if ( rights_id = = Key128 { } ) {
return std : : nullopt ;
}
if ( ! std : : any_of ( ticket . GetData ( ) . title_key_common_pad . begin ( ) ,
ticket . GetData ( ) . title_key_common_pad . end ( ) , [ ] ( u8 b ) { return b ! = 0 ; } ) ) {
@ -468,15 +482,17 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
std : : array < u8 , 0xDF > m_2 ;
std : : memcpy ( m_2 . data ( ) , rsa_step . data ( ) + 0x21 , m_2 . size ( ) ) ;
if ( m_0 ! = 0 )
return { } ;
if ( m_0 ! = 0 ) {
return std : : nullopt ;
}
m_1 = m_1 ^ MGF1 < 0x20 > ( m_2 ) ;
m_2 = m_2 ^ MGF1 < 0xDF > ( m_1 ) ;
const auto offset = FindTicketOffset ( m_2 ) ;
if ( ! offset )
return { } ;
if ( ! offset ) {
return std : : nullopt ;
}
ASSERT ( * offset > 0 ) ;
Key128 key_temp { } ;
@ -487,8 +503,8 @@ std::optional<std::pair<Key128, Key128>> ParseTicket(const Ticket& ticket,
KeyManager : : KeyManager ( ) {
// Initialize keys
const std : : string hactool_keys_dir = FileUtil : : GetHactoolConfigurationPath ( ) ;
const std : : string yuzu_keys_dir = FileUtil: : GetUserPath ( FileUtil : : UserPath : : KeysDir ) ;
const std : : string hactool_keys_dir = Common: : FS : : GetHactoolConfigurationPath ( ) ;
const std : : string yuzu_keys_dir = Common: : FS : : GetUserPath ( Common : : FS : : UserPath : : KeysDir ) ;
if ( Settings : : values . use_dev_keys ) {
dev_mode = true ;
AttemptLoadKeyFile ( yuzu_keys_dir , hactool_keys_dir , " dev.keys " , false ) ;
@ -506,34 +522,39 @@ KeyManager::KeyManager() {
}
static bool ValidCryptoRevisionString ( std : : string_view base , size_t begin , size_t length ) {
if ( base . size ( ) < begin + length )
if ( base . size ( ) < begin + length ) {
return false ;
}
return std : : all_of ( base . begin ( ) + begin , base . begin ( ) + begin + length ,
[ ] ( u8 c ) { return std : : isxdigit ( c ) ; } ) ;
}
void KeyManager : : LoadFromFile ( const std : : string & filename , bool is_title_keys ) {
std : : ifstream file ;
OpenFStream( file , filename , std : : ios_base : : in ) ;
if ( ! file . is_open ( ) )
Common: : FS : : OpenFStream( file , filename , std : : ios_base : : in ) ;
if ( ! file . is_open ( ) ) {
return ;
}
std : : string line ;
while ( std : : getline ( file , line ) ) {
std : : vector < std : : string > out ;
std : : stringstream stream ( line ) ;
std : : string item ;
while ( std : : getline ( stream , item , ' = ' ) )
while ( std : : getline ( stream , item , ' = ' ) ) {
out . push_back ( std : : move ( item ) ) ;
}
if ( out . size ( ) ! = 2 )
if ( out . size ( ) ! = 2 ) {
continue ;
}
out [ 0 ] . erase ( std : : remove ( out [ 0 ] . begin ( ) , out [ 0 ] . end ( ) , ' ' ) , out [ 0 ] . end ( ) ) ;
out [ 1 ] . erase ( std : : remove ( out [ 1 ] . begin ( ) , out [ 1 ] . end ( ) , ' ' ) , out [ 1 ] . end ( ) ) ;
if ( out [ 0 ] . compare ( 0 , 1 , " # " ) = = 0 )
if ( out [ 0 ] . compare ( 0 , 1 , " # " ) = = 0 ) {
continue ;
}
if ( is_title_keys ) {
auto rights_id_raw = Common : : HexStringToArray < 16 > ( out [ 0 ] ) ;
@ -553,14 +574,16 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
s256_keys [ { index . type , index . field1 , index . field2 } ] = key ;
} else if ( out [ 0 ] . compare ( 0 , 8 , " keyblob_ " ) = = 0 & &
out [ 0 ] . compare ( 0 , 9 , " keyblob_k " ) ! = 0 ) {
if ( ! ValidCryptoRevisionString ( out [ 0 ] , 8 , 2 ) )
if ( ! ValidCryptoRevisionString ( out [ 0 ] , 8 , 2 ) ) {
continue ;
}
const auto index = std : : stoul ( out [ 0 ] . substr ( 8 , 2 ) , nullptr , 16 ) ;
keyblobs [ index ] = Common : : HexStringToArray < 0x90 > ( out [ 1 ] ) ;
} else if ( out [ 0 ] . compare ( 0 , 18 , " encrypted_keyblob_ " ) = = 0 ) {
if ( ! ValidCryptoRevisionString ( out [ 0 ] , 18 , 2 ) )
if ( ! ValidCryptoRevisionString ( out [ 0 ] , 18 , 2 ) ) {
continue ;
}
const auto index = std : : stoul ( out [ 0 ] . substr ( 18 , 2 ) , nullptr , 16 ) ;
encrypted_keyblobs [ index ] = Common : : HexStringToArray < 0xB0 > ( out [ 1 ] ) ;
@ -568,8 +591,9 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
eticket_extended_kek = Common : : HexStringToArray < 576 > ( out [ 1 ] ) ;
} else {
for ( const auto & kv : KEYS_VARIABLE_LENGTH ) {
if ( ! ValidCryptoRevisionString ( out [ 0 ] , kv . second . size ( ) , 2 ) )
if ( ! ValidCryptoRevisionString ( out [ 0 ] , kv . second . size ( ) , 2 ) ) {
continue ;
}
if ( out [ 0 ] . compare ( 0 , kv . second . size ( ) , kv . second ) = = 0 ) {
const auto index =
std : : stoul ( out [ 0 ] . substr ( kv . second . size ( ) , 2 ) , nullptr , 16 ) ;
@ -604,10 +628,11 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
void KeyManager : : AttemptLoadKeyFile ( const std : : string & dir1 , const std : : string & dir2 ,
const std : : string & filename , bool title ) {
if ( FileUtil : : Exists ( dir1 + DIR_SEP + filename ) )
if ( Common: : FS : : Exists ( dir1 + DIR_SEP + filename ) ) {
LoadFromFile ( dir1 + DIR_SEP + filename , title ) ;
else if ( FileUtil : : Exists ( dir2 + DIR_SEP + filename ) )
} else if ( Common : : FS : : Exists ( dir2 + DIR_SEP + filename ) ) {
LoadFromFile ( dir2 + DIR_SEP + filename , title ) ;
}
}
bool KeyManager : : BaseDeriveNecessary ( ) const {
@ -615,8 +640,9 @@ bool KeyManager::BaseDeriveNecessary() const {
return ! HasKey ( key_type , index1 , index2 ) ;
} ;
if ( check_key_existence ( S256KeyType : : Header ) )
if ( check_key_existence ( S256KeyType : : Header ) ) {
return true ;
}
for ( size_t i = 0 ; i < CURRENT_CRYPTO_REVISION ; + + i ) {
if ( check_key_existence ( S128KeyType : : Master , i ) | |
@ -641,14 +667,16 @@ bool KeyManager::HasKey(S256KeyType id, u64 field1, u64 field2) const {
}
Key128 KeyManager : : GetKey ( S128KeyType id , u64 field1 , u64 field2 ) const {
if ( ! HasKey ( id , field1 , field2 ) )
if ( ! HasKey ( id , field1 , field2 ) ) {
return { } ;
}
return s128_keys . at ( { id , field1 , field2 } ) ;
}
Key256 KeyManager : : GetKey ( S256KeyType id , u64 field1 , u64 field2 ) const {
if ( ! HasKey ( id , field1 , field2 ) )
if ( ! HasKey ( id , field1 , field2 ) ) {
return { } ;
}
return s256_keys . at ( { id , field1 , field2 } ) ;
}
@ -670,7 +698,7 @@ Key256 KeyManager::GetBISKey(u8 partition_id) const {
template < size_t Size >
void KeyManager : : WriteKeyToFile ( KeyCategory category , std : : string_view keyname ,
const std : : array < u8 , Size > & key ) {
const std : : string yuzu_keys_dir = FileUtil: : GetUserPath ( FileUtil : : UserPath : : KeysDir ) ;
const std : : string yuzu_keys_dir = Common: : FS : : GetUserPath ( Common : : FS : : UserPath : : KeysDir ) ;
std : : string filename = " title.keys_autogenerated " ;
if ( category = = KeyCategory : : Standard ) {
filename = dev_mode ? " dev.keys_autogenerated " : " prod.keys_autogenerated " ;
@ -679,9 +707,9 @@ void KeyManager::WriteKeyToFile(KeyCategory category, std::string_view keyname,
}
const auto path = yuzu_keys_dir + DIR_SEP + filename ;
const auto add_info_text = ! FileUtil : : Exists ( path ) ;
FileUtil : : CreateFullPath ( path ) ;
FileUtil : : IOFile file { path , " a " } ;
const auto add_info_text = ! Common: : FS : : Exists ( path ) ;
Common: : FS : : CreateFullPath ( path ) ;
Common: : FS : : IOFile file { path , " a " } ;
if ( ! file . IsOpen ( ) ) {
return ;
}
@ -765,29 +793,31 @@ void KeyManager::SetKey(S256KeyType id, Key256 key, u64 field1, u64 field2) {
}
bool KeyManager : : KeyFileExists ( bool title ) {
const std : : string hactool_keys_dir = FileUtil : : GetHactoolConfigurationPath ( ) ;
const std : : string yuzu_keys_dir = FileUtil: : GetUserPath ( FileUtil : : UserPath : : KeysDir ) ;
const std : : string hactool_keys_dir = Common: : FS : : GetHactoolConfigurationPath ( ) ;
const std : : string yuzu_keys_dir = Common: : FS : : GetUserPath ( Common : : FS : : UserPath : : KeysDir ) ;
if ( title ) {
return FileUtil : : Exists ( hactool_keys_dir + DIR_SEP + " title.keys " ) | |
FileUtil : : Exists ( yuzu_keys_dir + DIR_SEP + " title.keys " ) ;
return Common: : FS : : Exists ( hactool_keys_dir + DIR_SEP + " title.keys " ) | |
Common: : FS : : Exists ( yuzu_keys_dir + DIR_SEP + " title.keys " ) ;
}
if ( Settings : : values . use_dev_keys ) {
return FileUtil : : Exists ( hactool_keys_dir + DIR_SEP + " dev.keys " ) | |
FileUtil : : Exists ( yuzu_keys_dir + DIR_SEP + " dev.keys " ) ;
return Common: : FS : : Exists ( hactool_keys_dir + DIR_SEP + " dev.keys " ) | |
Common: : FS : : Exists ( yuzu_keys_dir + DIR_SEP + " dev.keys " ) ;
}
return FileUtil : : Exists ( hactool_keys_dir + DIR_SEP + " prod.keys " ) | |
FileUtil : : Exists ( yuzu_keys_dir + DIR_SEP + " prod.keys " ) ;
return Common: : FS : : Exists ( hactool_keys_dir + DIR_SEP + " prod.keys " ) | |
Common: : FS : : Exists ( yuzu_keys_dir + DIR_SEP + " prod.keys " ) ;
}
void KeyManager : : DeriveSDSeedLazy ( ) {
if ( HasKey ( S128KeyType : : SDSeed ) )
if ( HasKey ( S128KeyType : : SDSeed ) ) {
return ;
}
const auto res = DeriveSDSeed ( ) ;
if ( res )
if ( res ) {
SetKey ( S128KeyType : : SDSeed , * res ) ;
}
}
static Key128 CalculateCMAC ( const u8 * source , size_t size , const Key128 & key ) {
@ -799,11 +829,13 @@ static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
}
void KeyManager : : DeriveBase ( ) {
if ( ! BaseDeriveNecessary ( ) )
if ( ! BaseDeriveNecessary ( ) ) {
return ;
}
if ( ! HasKey ( S128KeyType : : SecureBoot ) | | ! HasKey ( S128KeyType : : TSEC ) )
if ( ! HasKey ( S128KeyType : : SecureBoot ) | | ! HasKey ( S128KeyType : : TSEC ) ) {
return ;
}
const auto has_bis = [ this ] ( u64 id ) {
return HasKey ( S128KeyType : : BIS , id , static_cast < u64 > ( BISKeyType : : Crypto ) ) & &
@ -820,10 +852,11 @@ void KeyManager::DeriveBase() {
static_cast < u64 > ( BISKeyType : : Tweak ) ) ;
} ;
if ( has_bis ( 2 ) & & ! has_bis ( 3 ) )
if ( has_bis ( 2 ) & & ! has_bis ( 3 ) ) {
copy_bis ( 2 , 3 ) ;
else if ( has_bis ( 3 ) & & ! has_bis ( 2 ) )
} else if ( has_bis ( 3 ) & & ! has_bis ( 2 ) ) {
copy_bis ( 3 , 2 ) ;
}
std : : bitset < 32 > revisions ( 0xFFFFFFFF ) ;
for ( size_t i = 0 ; i < revisions . size ( ) ; + + i ) {
@ -833,15 +866,17 @@ void KeyManager::DeriveBase() {
}
}
if ( ! revisions . any ( ) )
if ( ! revisions . any ( ) ) {
return ;
}
const auto sbk = GetKey ( S128KeyType : : SecureBoot ) ;
const auto tsec = GetKey ( S128KeyType : : TSEC ) ;
for ( size_t i = 0 ; i < revisions . size ( ) ; + + i ) {
if ( ! revisions [ i ] )
if ( ! revisions [ i ] ) {
continue ;
}
// Derive keyblob key
const auto key = DeriveKeyblobKey (
@ -850,16 +885,18 @@ void KeyManager::DeriveBase() {
SetKey ( S128KeyType : : Keyblob , key , i ) ;
// Derive keyblob MAC key
if ( ! HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : KeyblobMAC ) ) )
if ( ! HasKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : KeyblobMAC ) ) ) {
continue ;
}
const auto mac_key = DeriveKeyblobMACKey (
key , GetKey ( S128KeyType : : Source , static_cast < u64 > ( SourceKeyType : : KeyblobMAC ) ) ) ;
SetKey ( S128KeyType : : KeyblobMAC , mac_key , i ) ;
Key128 cmac = CalculateCMAC ( encrypted_keyblobs [ i ] . data ( ) + 0x10 , 0xA0 , mac_key ) ;
if ( std : : memcmp ( cmac . data ( ) , encrypted_keyblobs [ i ] . data ( ) , cmac . size ( ) ) ! = 0 )
if ( std : : memcmp ( cmac . data ( ) , encrypted_keyblobs [ i ] . data ( ) , cmac . size ( ) ) ! = 0 ) {
continue ;
}
// Decrypt keyblob
if ( keyblobs [ i ] = = std : : array < u8 , 0x90 > { } ) {
@ -883,16 +920,19 @@ void KeyManager::DeriveBase() {
revisions . set ( ) ;
for ( size_t i = 0 ; i < revisions . size ( ) ; + + i ) {
if ( ! HasKey ( S128KeyType : : Master , i ) )
if ( ! HasKey ( S128KeyType : : Master , i ) ) {
revisions . reset ( i ) ;
}
}
if ( ! revisions . any ( ) )
if ( ! revisions . any ( ) ) {
return ;
}
for ( size_t i = 0 ; i < revisions . size ( ) ; + + i ) {
if ( ! revisions [ i ] )
if ( ! revisions [ i ] ) {
continue ;
}
// Derive general purpose keys
DeriveGeneralPurposeKeys ( i ) ;
@ -922,16 +962,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
const auto es = Core : : System : : GetInstance ( ) . GetContentProvider ( ) . GetEntry (
0x0100000000000033 , FileSys : : ContentRecordType : : Program ) ;
if ( es = = nullptr )
if ( es = = nullptr ) {
return ;
}
const auto exefs = es - > GetExeFS ( ) ;
if ( exefs = = nullptr )
if ( exefs = = nullptr ) {
return ;
}
const auto main = exefs - > GetFile ( " main " ) ;
if ( main = = nullptr )
if ( main = = nullptr ) {
return ;
}
const auto bytes = main - > ReadAllBytes ( ) ;
@ -941,16 +984,19 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
const auto seed3 = data . GetRSAKekSeed3 ( ) ;
const auto mask0 = data . GetRSAKekMask0 ( ) ;
if ( eticket_kek ! = Key128 { } )
if ( eticket_kek ! = Key128 { } ) {
SetKey ( S128KeyType : : Source , eticket_kek , static_cast < size_t > ( SourceKeyType : : ETicketKek ) ) ;
}
if ( eticket_kekek ! = Key128 { } ) {
SetKey ( S128KeyType : : Source , eticket_kekek ,
static_cast < size_t > ( SourceKeyType : : ETicketKekek ) ) ;
}
if ( seed3 ! = Key128 { } )
if ( seed3 ! = Key128 { } ) {
SetKey ( S128KeyType : : RSAKek , seed3 , static_cast < size_t > ( RSAKekType : : Seed3 ) ) ;
if ( mask0 ! = Key128 { } )
}
if ( mask0 ! = Key128 { } ) {
SetKey ( S128KeyType : : RSAKek , mask0 , static_cast < size_t > ( RSAKekType : : Mask0 ) ) ;
}
if ( eticket_kek = = Key128 { } | | eticket_kekek = = Key128 { } | | seed3 = = Key128 { } | |
mask0 = = Key128 { } ) {
return ;
@ -976,8 +1022,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
AESCipher < Key128 > es_kek ( temp_kekek , Mode : : ECB ) ;
es_kek . Transcode ( eticket_kek . data ( ) , eticket_kek . size ( ) , eticket_final . data ( ) , Op : : Decrypt ) ;
if ( eticket_final = = Key128 { } )
if ( eticket_final = = Key128 { } ) {
return ;
}
SetKey ( S128KeyType : : ETicketRSAKek , eticket_final ) ;
@ -992,18 +1039,20 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
void KeyManager : : PopulateTickets ( ) {
const auto rsa_key = GetETicketRSAKey ( ) ;
if ( rsa_key = = RSAKeyPair < 2048 > { } )
if ( rsa_key = = RSAKeyPair < 2048 > { } ) {
return ;
}
if ( ! common_tickets . empty ( ) & & ! personal_tickets . empty ( ) )
if ( ! common_tickets . empty ( ) & & ! personal_tickets . empty ( ) ) {
return ;
}
const FileUtil: : IOFile save1 ( FileUtil : : GetUserPath ( FileUtil : : UserPath : : NANDDir ) +
" /system/save/80000000000000e1 " ,
" rb+ " ) ;
const FileUtil: : IOFile save2 ( FileUtil : : GetUserPath ( FileUtil : : UserPath : : NANDDir ) +
" /system/save/80000000000000e2 " ,
" rb+ " ) ;
const Common: : FS : : IOFile save1 ( Common : : FS : : GetUserPath ( Common : : FS : : UserPath : : NANDDir ) +
" /system/save/80000000000000e1 " ,
" rb+ " ) ;
const Common: : FS : : IOFile save2 ( Common : : FS : : GetUserPath ( Common : : FS : : UserPath : : NANDDir ) +
" /system/save/80000000000000e2 " ,
" rb+ " ) ;
const auto blob2 = GetTicketblob ( save2 ) ;
auto res = GetTicketblob ( save1 ) ;
@ -1013,8 +1062,10 @@ void KeyManager::PopulateTickets() {
for ( std : : size_t i = 0 ; i < res . size ( ) ; + + i ) {
const auto common = i < idx ;
const auto pair = ParseTicket ( res [ i ] , rsa_key ) ;
if ( ! pair )
if ( ! pair ) {
continue ;
}
const auto & [ rid , key ] = * pair ;
u128 rights_id ;
std : : memcpy ( rights_id . data ( ) , rid . data ( ) , rid . size ( ) ) ;
@ -1043,27 +1094,33 @@ void KeyManager::SynthesizeTickets() {
}
void KeyManager : : SetKeyWrapped ( S128KeyType id , Key128 key , u64 field1 , u64 field2 ) {
if ( key = = Key128 { } )
if ( key = = Key128 { } ) {
return ;
}
SetKey ( id , key , field1 , field2 ) ;
}
void KeyManager : : SetKeyWrapped ( S256KeyType id , Key256 key , u64 field1 , u64 field2 ) {
if ( key = = Key256 { } )
if ( key = = Key256 { } ) {
return ;
}
SetKey ( id , key , field1 , field2 ) ;
}
void KeyManager : : PopulateFromPartitionData ( PartitionDataManager & data ) {
if ( ! BaseDeriveNecessary ( ) )
if ( ! BaseDeriveNecessary ( ) ) {
return ;
}
if ( ! data . HasBoot0 ( ) )
if ( ! data . HasBoot0 ( ) ) {
return ;
}
for ( size_t i = 0 ; i < encrypted_keyblobs . size ( ) ; + + i ) {
if ( encrypted_keyblobs [ i ] ! = std : : array < u8 , 0xB0 > { } )
if ( encrypted_keyblobs [ i ] ! = std : : array < u8 , 0xB0 > { } ) {
continue ;
}
encrypted_keyblobs [ i ] = data . GetEncryptedKeyblob ( i ) ;
WriteKeyToFile < 0xB0 > ( KeyCategory : : Console , fmt : : format ( " encrypted_keyblob_{:02X} " , i ) ,
encrypted_keyblobs [ i ] ) ;
@ -1085,8 +1142,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
static_cast < u64 > ( SourceKeyType : : Keyblob ) , i ) ;
}
if ( data . HasFuses ( ) )
if ( data . HasFuses ( ) ) {
SetKeyWrapped ( S128KeyType : : SecureBoot , data . GetSecureBootKey ( ) ) ;
}
DeriveBase ( ) ;
@ -1100,8 +1158,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
const auto masters = data . GetTZMasterKeys ( latest_master ) ;
for ( size_t i = 0 ; i < masters . size ( ) ; + + i ) {
if ( masters [ i ] ! = Key128 { } & & ! HasKey ( S128KeyType : : Master , i ) )
if ( masters [ i ] ! = Key128 { } & & ! HasKey ( S128KeyType : : Master , i ) ) {
SetKey ( S128KeyType : : Master , masters [ i ] , i ) ;
}
}
DeriveBase ( ) ;
@ -1111,8 +1170,9 @@ void KeyManager::PopulateFromPartitionData(PartitionDataManager& data) {
std : : array < Key128 , 0x20 > package2_keys { } ;
for ( size_t i = 0 ; i < package2_keys . size ( ) ; + + i ) {
if ( HasKey ( S128KeyType : : Package2 , i ) )
if ( HasKey ( S128KeyType : : Package2 , i ) ) {
package2_keys [ i ] = GetKey ( S128KeyType : : Package2 , i ) ;
}
}
data . DecryptPackage2 ( package2_keys , Package2Type : : NormalMain ) ;
@ -1150,12 +1210,15 @@ const std::map<u128, Ticket>& KeyManager::GetPersonalizedTickets() const {
bool KeyManager : : AddTicketCommon ( Ticket raw ) {
const auto rsa_key = GetETicketRSAKey ( ) ;
if ( rsa_key = = RSAKeyPair < 2048 > { } )
if ( rsa_key = = RSAKeyPair < 2048 > { } ) {
return false ;
}
const auto pair = ParseTicket ( raw , rsa_key ) ;
if ( ! pair )
if ( ! pair ) {
return false ;
}
const auto & [ rid , key ] = * pair ;
u128 rights_id ;
std : : memcpy ( rights_id . data ( ) , rid . data ( ) , rid . size ( ) ) ;
@ -1166,12 +1229,15 @@ bool KeyManager::AddTicketCommon(Ticket raw) {
bool KeyManager : : AddTicketPersonalized ( Ticket raw ) {
const auto rsa_key = GetETicketRSAKey ( ) ;
if ( rsa_key = = RSAKeyPair < 2048 > { } )
if ( rsa_key = = RSAKeyPair < 2048 > { } ) {
return false ;
}
const auto pair = ParseTicket ( raw , rsa_key ) ;
if ( ! pair )
if ( ! pair ) {
return false ;
}
const auto & [ rid , key ] = * pair ;
u128 rights_id ;
std : : memcpy ( rights_id . data ( ) , rid . data ( ) , rid . size ( ) ) ;