mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
Add support for specifying Acid/Nca/Nrr signature key generations in the keyfile.
This commit is contained in:
parent
82d6db8e34
commit
fdf9a88dd7
4 changed files with 105 additions and 61 deletions
|
@ -45,20 +45,33 @@ pki_root_sign_key_private : RSA4096 Private Exponent (0x200 bytes)
|
|||
|
||||
; NCA Keys
|
||||
nca_header_key : AES128-XTS Key (0x20 bytes)
|
||||
nca_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
nca_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
||||
nca_header_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
nca_header_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes)
|
||||
nca_body_keak_application_## : AES128 Key (0x10 bytes)
|
||||
nca_body_keak_ocean_## : AES128 Key (0x10 bytes)
|
||||
nca_body_keak_system_## : AES128 Key (0x10 bytes)
|
||||
|
||||
; NRR Keys
|
||||
nrr_certificate_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
nrr_certificate_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes)
|
||||
|
||||
; XCI Keys
|
||||
xci_header_key : AES128 Key (0x10 bytes)
|
||||
xci_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
xci_header_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
||||
|
||||
; ACID Keys
|
||||
acid_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
acid_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
||||
acid_sign_key_##_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
acid_sign_key_##_private : RSA2048 Private Exponent (0x100 bytes)
|
||||
```
|
||||
|
||||
## Legacy Keynames
|
||||
Since firmware `9.0.0+` support for signature key generations was retroactively added for RSA-PSS signatures in NRR, ACID and NCA. The old names for these keys are still valid:
|
||||
```
|
||||
nca_header_sign_key_modulus : alias for nca_header_sign_key_00_modulus
|
||||
nca_header_sign_key_private : alias nca_header_sign_key_00_private
|
||||
acid_sign_key_modulus : alias for acid_sign_key_00_modulus
|
||||
acid_sign_key_private : alias for acid_sign_key_00_private
|
||||
```
|
||||
|
||||
## Compatibility with hactool keyset files
|
||||
|
|
|
@ -16,9 +16,7 @@ KeyConfiguration::KeyConfiguration(const KeyConfiguration& other)
|
|||
|
||||
void KeyConfiguration::operator=(const KeyConfiguration& other)
|
||||
{
|
||||
mAcidSignKey = other.mAcidSignKey;
|
||||
mPkg2SignKey = other.mPkg2SignKey;
|
||||
mContentArchiveHeader0SignKey = other.mContentArchiveHeader0SignKey;
|
||||
mXciHeaderSignKey = other.mXciHeaderSignKey;
|
||||
|
||||
mContentArchiveHeaderKey = other.mContentArchiveHeaderKey;
|
||||
|
@ -26,6 +24,9 @@ void KeyConfiguration::operator=(const KeyConfiguration& other)
|
|||
|
||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||
{
|
||||
mAcidSignKey[i] = other.mAcidSignKey[i];
|
||||
mContentArchiveHeader0SignKey[i] = other.mContentArchiveHeader0SignKey[i];
|
||||
mNrrCertificateSignKey[i] = other.mNrrCertificateSignKey[i];
|
||||
mPkg2Key[i] = other.mPkg2Key[i];
|
||||
mPkg1Key[i] = other.mPkg1Key[i];
|
||||
mNcaKeyAreaEncryptionKey[0][i] = other.mNcaKeyAreaEncryptionKey[0][i];
|
||||
|
@ -69,6 +70,7 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
|||
|
||||
#define _CONCAT_2_STRINGS(str1, str2) ((str1) + "_" + (str2))
|
||||
#define _CONCAT_3_STRINGS(str1, str2, str3) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3)
|
||||
#define _CONCAT_4_STRINGS(str1, str2, str3, str4) _CONCAT_2_STRINGS(_CONCAT_2_STRINGS(_CONCAT_2_STRINGS(str1, str2), str3), str4)
|
||||
|
||||
std::string key,val;
|
||||
fnd::Vec<byte_t> dec_array;
|
||||
|
@ -110,6 +112,13 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
|||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[0], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[0][mkeyidx].key, 0x10);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[1], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[1][mkeyidx].key, 0x10);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaKeyAreaEncKeyHwBase[nameidx], kNcaKeyAreaKeyIndexStr[2], kKeyIndex[mkeyidx]), mNcaKeyAreaEncryptionKeyHw[2][mkeyidx].key, 0x10);
|
||||
|
||||
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kPrivateStr), mContentArchiveHeader0SignKey[mkeyidx].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kModulusStr), mContentArchiveHeader0SignKey[mkeyidx].modulus, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kAcidBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kPrivateStr), mAcidSignKey[mkeyidx].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kAcidBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kModulusStr), mAcidSignKey[mkeyidx].modulus, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kNrrCertBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kPrivateStr), mNrrCertificateSignKey[mkeyidx].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_4_STRINGS(kNrrCertBase[nameidx], kSignKey, kKeyIndex[mkeyidx], kModulusStr), mNrrCertificateSignKey[mkeyidx].modulus, fnd::rsa::kRsa2048Size);
|
||||
}
|
||||
|
||||
// store nca header key
|
||||
|
@ -119,20 +128,23 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
|||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kKeyStr), mXciHeaderKey.key, 0x10);
|
||||
|
||||
// store rsa keys
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kRsaKeyPrivate), mContentArchiveHeader0SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kContentArchiveHeaderBase[nameidx], kRsaKeyModulus), mContentArchiveHeader0SignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyPrivate), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase[nameidx], kRsaKeyModulus), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||
// legacy header nca key name
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kPrivateStr), mContentArchiveHeader0SignKey[0].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kContentArchiveHeaderBase[nameidx], kSignKey, kModulusStr), mContentArchiveHeader0SignKey[0].modulus, fnd::rsa::kRsa2048Size);
|
||||
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyPrivate), mAcidSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyModulus), mAcidSignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kSignKey, kPrivateStr), mXciHeaderSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kXciHeaderBase[nameidx], kSignKey, kModulusStr), mXciHeaderSignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyPrivate), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyModulus), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||
// legacy acid header key name
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kAcidBase[nameidx], kSignKey, kPrivateStr), mAcidSignKey[0].priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kAcidBase[nameidx], kSignKey, kModulusStr), mAcidSignKey[0].modulus, fnd::rsa::kRsa2048Size);
|
||||
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyPrivate), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size);
|
||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase[nameidx], kRsaKeyModulus), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kSignKey, kPrivateStr), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkg2Base[nameidx], kSignKey, kModulusStr), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size);
|
||||
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkiRootBase[nameidx], kSignKey, kPrivateStr), pki_root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size);
|
||||
_SAVE_KEYDATA(_CONCAT_3_STRINGS(kPkiRootBase[nameidx], kSignKey, kModulusStr), pki_root_sign_key.modulus, fnd::rsa::kRsa4096Size);
|
||||
}
|
||||
|
||||
#undef _SAVE_KEYDATA
|
||||
|
@ -193,9 +205,9 @@ void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path)
|
|||
|
||||
void KeyConfiguration::clearGeneralKeyConfiguration()
|
||||
{
|
||||
mAcidSignKey = kNullRsa2048Key;
|
||||
|
||||
mPkg2SignKey = kNullRsa2048Key;
|
||||
mContentArchiveHeader0SignKey = kNullRsa2048Key;
|
||||
|
||||
mXciHeaderSignKey = kNullRsa2048Key;
|
||||
mPkiRootKeyList.clear();
|
||||
|
||||
|
@ -204,6 +216,9 @@ void KeyConfiguration::clearGeneralKeyConfiguration()
|
|||
|
||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||
{
|
||||
mAcidSignKey[i] = kNullRsa2048Key;
|
||||
mContentArchiveHeader0SignKey[i] = kNullRsa2048Key;
|
||||
mNrrCertificateSignKey[i] = kNullRsa2048Key;
|
||||
mPkg1Key[i] = kNullAesKey;
|
||||
mPkg2Key[i] = kNullAesKey;
|
||||
mETicketCommonKey[i] = kNullAesKey;
|
||||
|
@ -228,35 +243,23 @@ bool KeyConfiguration::getContentArchiveHeaderKey(fnd::aes::sAesXts128Key& key)
|
|||
bool KeyConfiguration::getContentArchiveHeader0SignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const
|
||||
{
|
||||
// TODO: This needs to be changed to support multiple keys
|
||||
|
||||
bool keyIsFound = false;
|
||||
switch (key_generation)
|
||||
if (key_generation >= kMasterKeyNum)
|
||||
{
|
||||
case (0x00):
|
||||
keyIsFound = copyOutKeyResourceIfExists(mContentArchiveHeader0SignKey, key, kNullRsa2048Key);
|
||||
break;
|
||||
default:
|
||||
keyIsFound = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return keyIsFound;
|
||||
return copyOutKeyResourceIfExists(mContentArchiveHeader0SignKey[key_generation], key, kNullRsa2048Key);
|
||||
}
|
||||
|
||||
bool KeyConfiguration::getAcidSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const
|
||||
{
|
||||
// TODO: This needs to be changed to support multiple keys
|
||||
|
||||
bool keyIsFound = false;
|
||||
switch (key_generation)
|
||||
if (key_generation >= kMasterKeyNum)
|
||||
{
|
||||
case (0x00):
|
||||
keyIsFound = copyOutKeyResourceIfExists(mAcidSignKey, key, kNullRsa2048Key);
|
||||
break;
|
||||
default:
|
||||
keyIsFound = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return keyIsFound;
|
||||
return copyOutKeyResourceIfExists(mAcidSignKey[key_generation], key, kNullRsa2048Key);
|
||||
}
|
||||
|
||||
bool KeyConfiguration::getNcaKeyAreaEncryptionKey(byte_t masterkey_index, byte_t keak_type, fnd::aes::sAes128Key& key) const
|
||||
|
@ -308,6 +311,17 @@ bool KeyConfiguration::getNcaExternalContentKey(const byte_t rights_id[nn::hac::
|
|||
return res_exists;
|
||||
}
|
||||
|
||||
bool KeyConfiguration::getNrrCertificateSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const
|
||||
{
|
||||
// TODO: This needs to be changed to support multiple keys
|
||||
if (key_generation >= kMasterKeyNum)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return copyOutKeyResourceIfExists(mNrrCertificateSignKey[key_generation], key, kNullRsa2048Key);
|
||||
}
|
||||
|
||||
bool KeyConfiguration::getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const
|
||||
{
|
||||
if (masterkey_index >= kMasterKeyNum)
|
||||
|
|
|
@ -34,6 +34,9 @@ public:
|
|||
void addNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], const fnd::aes::sAes128Key& key);
|
||||
bool getNcaExternalContentKey(const byte_t rights_id[nn::hac::nca::kRightsIdLen], fnd::aes::sAes128Key& key) const;
|
||||
|
||||
// nrr key
|
||||
bool getNrrCertificateSignKey(fnd::rsa::sRsa2048Key& key, byte_t key_generation) const;
|
||||
|
||||
// pkg1/pkg2
|
||||
bool getPkg1Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const;
|
||||
bool getPkg2Key(byte_t masterkey_index, fnd::aes::sAes128Key& key) const;
|
||||
|
@ -73,6 +76,7 @@ private:
|
|||
const std::string kXciHeaderBase[kNameVariantNum] = { "xci_header", "xci_header", "xci_header" };
|
||||
const std::string kContentArchiveHeaderBase[kNameVariantNum] = { "nca_header", "header", "nca_header" };
|
||||
const std::string kAcidBase[kNameVariantNum] = { "acid", "acid", "acid" };
|
||||
const std::string kNrrCertBase[kNameVariantNum] = { "nrr_certificate", "nrr_certificate", "nrr_certificate" };
|
||||
const std::string kPkiRootBase[kNameVariantNum] = { "pki_root", "pki_root", "pki_root" };
|
||||
const std::string kTicketCommonKeyBase[kNameVariantNum] = { "ticket_commonkey", "titlekek", "ticket_commonkey" };
|
||||
const std::string kNcaKeyAreaEncKeyBase[kNameVariantNum] = { "nca_key_area_key", "key_area_key", "nca_body_keak" };
|
||||
|
@ -84,8 +88,9 @@ private:
|
|||
const std::string kKeyStr = "key";
|
||||
const std::string kKekStr = "kek";
|
||||
const std::string kSourceStr = "source";
|
||||
const std::string kRsaKeyModulus = "sign_key_modulus";
|
||||
const std::string kRsaKeyPrivate = "sign_key_private";
|
||||
const std::string kSignKey = "sign_key";
|
||||
const std::string kModulusStr = "modulus";
|
||||
const std::string kPrivateStr = "private";
|
||||
const std::string kNcaKeyAreaKeyIndexStr[kNcaKeakNum] = { "application", "ocean", "system" };
|
||||
const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"};
|
||||
|
||||
|
@ -167,7 +172,7 @@ private:
|
|||
|
||||
/* general key config */
|
||||
// acid
|
||||
fnd::rsa::sRsa2048Key mAcidSignKey;
|
||||
fnd::rsa::sRsa2048Key mAcidSignKey[kMasterKeyNum];
|
||||
|
||||
// pkg1 and pkg2
|
||||
fnd::aes::sAes128Key mPkg1Key[kMasterKeyNum];
|
||||
|
@ -175,11 +180,14 @@ private:
|
|||
fnd::aes::sAes128Key mPkg2Key[kMasterKeyNum];
|
||||
|
||||
// nca
|
||||
fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey;
|
||||
fnd::rsa::sRsa2048Key mContentArchiveHeader0SignKey[kMasterKeyNum];
|
||||
fnd::aes::sAesXts128Key mContentArchiveHeaderKey;
|
||||
fnd::aes::sAes128Key mNcaKeyAreaEncryptionKey[kNcaKeakNum][kMasterKeyNum];
|
||||
fnd::aes::sAes128Key mNcaKeyAreaEncryptionKeyHw[kNcaKeakNum][kMasterKeyNum];
|
||||
|
||||
// nrr
|
||||
fnd::rsa::sRsa2048Key mNrrCertificateSignKey[kMasterKeyNum];
|
||||
|
||||
// xci
|
||||
fnd::rsa::sRsa2048Key mXciHeaderSignKey;
|
||||
fnd::aes::sAes128Key mXciHeaderKey;
|
||||
|
|
|
@ -917,6 +917,11 @@ void UserSettings::dumpKeyConfig() const
|
|||
if (mKeyCfg.getContentArchiveHeader0SignKey(rsa2048_key, i) == true)
|
||||
dumpRsa2048Key(rsa2048_key, "Header0-SignatureKey-" + kKeyIndex[i], 2);
|
||||
}
|
||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||
{
|
||||
if (mKeyCfg.getAcidSignKey(rsa2048_key, i) == true)
|
||||
dumpRsa2048Key(rsa2048_key, "Acid-SignatureKey-" + kKeyIndex[i], 2);
|
||||
}
|
||||
|
||||
if (mKeyCfg.getContentArchiveHeaderKey(aesxts_key) == true)
|
||||
dumpAesXtsKey(aesxts_key, "Header-EncryptionKey", 2);
|
||||
|
@ -941,17 +946,21 @@ void UserSettings::dumpKeyConfig() const
|
|||
dumpAesKey(aes_key, "KeyAreaEncryptionKeyHw-System-" + kKeyIndex[i], 2);
|
||||
}
|
||||
|
||||
std::cout << " NRR Keys:" << std::endl;
|
||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||
{
|
||||
if (mKeyCfg.getNrrCertificateSignKey(rsa2048_key, i) == true)
|
||||
dumpRsa2048Key(rsa2048_key, "Certificate-SignatureKey-" + kKeyIndex[i], 2);
|
||||
}
|
||||
|
||||
std::cout << " XCI Keys:" << std::endl;
|
||||
if (mKeyCfg.getXciHeaderSignKey(rsa2048_key) == true)
|
||||
dumpRsa2048Key(rsa2048_key, "Header-SignatureKey", 2);
|
||||
if (mKeyCfg.getXciHeaderKey(aes_key) == true)
|
||||
dumpAesKey(aes_key, "ExtendedHeader-EncryptionKey", 2);
|
||||
|
||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||
{
|
||||
if (mKeyCfg.getAcidSignKey(rsa2048_key, i) == true)
|
||||
dumpRsa2048Key(rsa2048_key, "ACID-SignatureKey-" + kKeyIndex[i], 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::cout << " Package1 Keys:" << std::endl;
|
||||
for (size_t i = 0; i < kMasterKeyNum; i++)
|
||||
|
|
Loading…
Reference in a new issue