mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-06 17:41:24 -04:00
Fix bug in user_generate_specific_aes_key, add other read/write le/be funcs
This commit is contained in:
parent
71f01aaa43
commit
4f0e8b8467
3 changed files with 136 additions and 120 deletions
|
@ -32,12 +32,12 @@ void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed,
|
|||
if (seed_size >= 0xE0) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
|
||||
size_t hash_buf_size = seed_size + 4;
|
||||
memcpy(hash_buf, seed, seed_size);
|
||||
|
||||
uint32_t round = 0;
|
||||
|
||||
|
||||
uint32_t round_num = 0;
|
||||
|
||||
uint8_t *p_out = (uint8_t *)masked;
|
||||
|
||||
while (masked_size) {
|
||||
|
@ -45,21 +45,17 @@ void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed,
|
|||
if (cur_size > 0x20) {
|
||||
cur_size = 0x20;
|
||||
}
|
||||
|
||||
hash_buf[seed_size + 0] = (uint8_t)((round >> 24) & 0xFF);
|
||||
hash_buf[seed_size + 1] = (uint8_t)((round >> 16) & 0xFF);
|
||||
hash_buf[seed_size + 2] = (uint8_t)((round >> 8) & 0xFF);
|
||||
hash_buf[seed_size + 3] = (uint8_t)((round >> 0) & 0xFF);
|
||||
round++;
|
||||
|
||||
write32be(hash_buf, seed_size, round_num++);
|
||||
|
||||
flush_dcache_range(hash_buf, hash_buf + hash_buf_size);
|
||||
se_calculate_sha256(cur_hash, hash_buf, hash_buf_size);
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < cur_size; i++) {
|
||||
*p_out ^= cur_hash[i];
|
||||
p_out++;
|
||||
}
|
||||
|
||||
|
||||
masked_size -= cur_size;
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +64,7 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si
|
|||
if (src_size != 0x100) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
|
||||
/* RSA Wrapped titlekeys use RSA-OAEP. */
|
||||
/* Message is of the form prefix || maskedSalt || maskedDB. */
|
||||
/* maskedSalt = salt ^ MGF1(maskedDB) */
|
||||
|
@ -77,43 +73,43 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si
|
|||
/* DB is of the form label_hash || 00....01 || wrapped_titlekey. */
|
||||
/* label_hash is, in practice, a constant in es .rodata. */
|
||||
/* I have no idea why Nintendo did this, it should be either nonconstant (in tik) or in tz .rodata. */
|
||||
|
||||
|
||||
uint8_t *message = (uint8_t *)src;
|
||||
|
||||
|
||||
/* Prefix should always be zero. */
|
||||
if (*message != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t *salt = message + 1;
|
||||
uint8_t *db = message + 0x21;
|
||||
|
||||
|
||||
/* This will be passed to smc_unwrap_rsa_oaep_wrapped_titlekey. */
|
||||
uint8_t *expected_label_hash = (uint8_t *)(&g_tkey_expected_label_hash[0]);
|
||||
|
||||
|
||||
/* Unmask the salt. */
|
||||
calculate_mgf1_and_xor(salt, 0x20, db, 0xDF);
|
||||
/* Unmask the DB. */
|
||||
calculate_mgf1_and_xor(db, 0xDF, salt, 0x20);
|
||||
|
||||
|
||||
/* Validate expected salt. */
|
||||
for (unsigned int i = 0; i < 0x20; i++) {
|
||||
if (expected_label_hash[i] != db[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Don't validate salt from message[1:0x21] at all. */
|
||||
|
||||
|
||||
/* Advance pointer to DB, since we've validated the salt prefix. */
|
||||
db += 0x20;
|
||||
|
||||
|
||||
/* DB must be of the form 0000...01 || wrapped_titlekey */
|
||||
if (*db != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Locate wrapped_titlekey inside DB. */
|
||||
size_t wrapped_key_offset_in_db = 0;
|
||||
while (wrapped_key_offset_in_db < 0xBF) {
|
||||
|
@ -127,13 +123,13 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Validate size... */
|
||||
size_t wrapped_titlekey_size = 0xBF - wrapped_key_offset_in_db;
|
||||
if (wrapped_titlekey_size > dst_size || wrapped_titlekey_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Extract the wrapped key. */
|
||||
memcpy(dst, &db[wrapped_key_offset_in_db], wrapped_titlekey_size);
|
||||
return wrapped_key_offset_in_db;
|
||||
|
@ -143,15 +139,15 @@ void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_siz
|
|||
if (g_tkey_master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) {
|
||||
generic_panic();
|
||||
}
|
||||
|
||||
|
||||
const uint8_t titlekek_source[0x10] = {
|
||||
0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B
|
||||
};
|
||||
|
||||
|
||||
/* Generate the appropriate titlekek into keyslot 9. */
|
||||
unsigned int master_keyslot = mkey_get_keyslot(g_tkey_master_key_rev);
|
||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_source, 0x10);
|
||||
|
||||
|
||||
/* Unwrap the titlekey using the titlekek. */
|
||||
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue