Add support for specifying Acid/Nca/Nrr signature key generations in the keyfile.

This commit is contained in:
Jack 2020-03-10 20:22:36 +08:00
parent 82d6db8e34
commit fdf9a88dd7
4 changed files with 105 additions and 61 deletions

View file

@ -29,36 +29,49 @@ nca_body_keak_ocean_source : Used with master_key_##, aes_kek_generation_s
nca_body_keak_system_source : Used with master_key_##, aes_kek_generation_source and aes_key_generation_source to generate nca_body_keak_system_##. (0x10 bytes)
; Package1 keys
package1_key_## : AES128 Key (0x10 bytes)
package1_key_## : AES128 Key (0x10 bytes)
; Package2 Keys
package2_key_## : AES128 Key (0x10 bytes)
package2_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
package2_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
package2_key_## : AES128 Key (0x10 bytes)
package2_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
package2_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
; Ticket Keys
ticket_commonkey_## : AES128 Key (0x10 bytes)
ticket_commonkey_## : AES128 Key (0x10 bytes)
; PKI Root Signing Key
pki_root_sign_key_modulus : RSA4096 Modulus (0x200 bytes)
pki_root_sign_key_private : RSA4096 Private Exponent (0x200 bytes)
pki_root_sign_key_modulus : RSA4096 Modulus (0x200 bytes)
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_body_keak_application_## : AES128 Key (0x10 bytes)
nca_body_keak_ocean_## : AES128 Key (0x10 bytes)
nca_body_keak_system_## : AES128 Key (0x10 bytes)
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_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)
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

View file

@ -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_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(kAcidBase[nameidx], kRsaKeyPrivate), mAcidSignKey.priv_exponent, fnd::rsa::kRsa2048Size);
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase[nameidx], kRsaKeyModulus), mAcidSignKey.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(kPkg2Base[nameidx], kRsaKeyPrivate), mPkg2SignKey.priv_exponent, fnd::rsa::kRsa2048Size);
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkg2Base[nameidx], kRsaKeyModulus), mPkg2SignKey.modulus, fnd::rsa::kRsa2048Size);
_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_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(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)

View file

@ -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;

View file

@ -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++)