mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
Fix smcComputeCmac, generally improve userpage cache usage
This commit is contained in:
parent
ec8f27f1be
commit
8e5228866c
3 changed files with 24 additions and 11 deletions
|
@ -216,7 +216,7 @@ void clear_aes_keyslot_iv(unsigned int keyslot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
for (size_t i = 0; i < (0x10 >> 2); i++) {
|
||||||
SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8;
|
SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i;
|
||||||
SECURITY_ENGINE->AES_KEYTABLE_DATA = 0;
|
SECURITY_ENGINE->AES_KEYTABLE_DATA = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,11 +584,14 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||||
if (keyslot >= KEYSLOT_AES_MAX) {
|
if (keyslot >= KEYSLOT_AES_MAX) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data_size) {
|
||||||
|
flush_dcache_range((uint8_t *)data, (uint8_t *)data + data_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* Generate the derived key, to be XOR'd with final output block. */
|
/* Generate the derived key, to be XOR'd with final output block. */
|
||||||
uint8_t derived_key[0x10];
|
uint8_t derived_key[0x10] = {0};
|
||||||
memset(derived_key, 0, sizeof(derived_key));
|
se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high);
|
||||||
se_aes_128_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key));
|
|
||||||
shift_left_xor_rb(derived_key);
|
shift_left_xor_rb(derived_key);
|
||||||
if (data_size & 0xF) {
|
if (data_size & 0xF) {
|
||||||
shift_left_xor_rb(derived_key);
|
shift_left_xor_rb(derived_key);
|
||||||
|
@ -597,6 +600,7 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||||
SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16);
|
||||||
SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | (0x145);
|
SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | (0x145);
|
||||||
clear_aes_keyslot_iv(keyslot);
|
clear_aes_keyslot_iv(keyslot);
|
||||||
|
|
||||||
|
|
||||||
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
unsigned int num_blocks = (data_size + 0xF) >> 4;
|
||||||
/* Handle aligned blocks. */
|
/* Handle aligned blocks. */
|
||||||
|
@ -605,22 +609,22 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con
|
||||||
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
trigger_se_blocking_op(OP_START, NULL, 0, data, data_size);
|
||||||
SECURITY_ENGINE->CRYPTO_REG |= 0x80;
|
SECURITY_ENGINE->CRYPTO_REG |= 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create final block. */
|
/* Create final block. */
|
||||||
uint8_t last_block[0x10];
|
uint8_t last_block[0x10] = {0};
|
||||||
memset(last_block, 0, sizeof(last_block));
|
|
||||||
if (data_size & 0xF) {
|
if (data_size & 0xF) {
|
||||||
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
|
memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF);
|
||||||
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
|
last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */
|
||||||
} else if (data_size >= 0x10) {
|
} else if (data_size >= 0x10) {
|
||||||
memcpy(last_block, data + data_size - 0x10, 0x10);
|
memcpy(last_block, data + data_size - 0x10, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < 0x10; i++) {
|
for (unsigned int i = 0; i < 0x10; i++) {
|
||||||
last_block[i] ^= derived_key[i];
|
last_block[i] ^= derived_key[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform last operation. */
|
/* Perform last operation. */
|
||||||
|
SECURITY_ENGINE->BLOCK_COUNT_REG = 0;
|
||||||
flush_dcache_range(last_block, last_block + sizeof(last_block));
|
flush_dcache_range(last_block, last_block + sizeof(last_block));
|
||||||
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
|
trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block));
|
||||||
|
|
||||||
|
|
|
@ -355,8 +355,9 @@ uint32_t user_compute_cmac(smc_args_t *args) {
|
||||||
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
flush_dcache_range(user_data, user_data + size);
|
flush_dcache_range(user_data, user_data + size);
|
||||||
|
|
||||||
se_compute_aes_128_cmac(keyslot, result_cmac, 0x10, user_data, size);
|
se_compute_aes_128_cmac(keyslot, result_cmac, 0x10, user_data, size);
|
||||||
|
|
||||||
/* Copy CMAC out. */
|
/* Copy CMAC out. */
|
||||||
|
@ -399,6 +400,8 @@ uint32_t user_load_rsa_oaep_key(smc_args_t *args) {
|
||||||
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_dcache_range(user_data, user_data + size);
|
||||||
|
|
||||||
/* Ensure that our private key is 0x100 bytes. */
|
/* Ensure that our private key is 0x100 bytes. */
|
||||||
if (gcm_decrypt_key(user_data, size, user_data, size, sealed_kek, 0x10, wrapped_key, 0x10, CRYPTOUSECASE_RSAOAEP, is_personalized) < 0x100) {
|
if (gcm_decrypt_key(user_data, size, user_data, size, sealed_kek, 0x10, wrapped_key, 0x10, CRYPTOUSECASE_RSAOAEP, is_personalized) < 0x100) {
|
||||||
|
@ -446,6 +449,8 @@ uint32_t user_decrypt_rsa_private_key(smc_args_t *args) {
|
||||||
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_dcache_range(user_data, user_data + size);
|
||||||
|
|
||||||
size_t out_size;
|
size_t out_size;
|
||||||
|
|
||||||
|
@ -494,6 +499,8 @@ uint32_t user_load_secure_exp_mod_key(smc_args_t *args) {
|
||||||
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
if (upage_init(&page_ref, user_address) == 0 || user_copy_to_secure(&page_ref, user_data, user_address, size) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_dcache_range(user_data, user_data + size);
|
||||||
|
|
||||||
size_t out_size;
|
size_t out_size;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ bool upage_init(upage_ref_t *upage, void *user_address) {
|
||||||
mmu_map_page(mmu_l3_tbl, USER_PAGE_SECURE_MONITOR_ADDR, upage->user_address, userpage_attributes);
|
mmu_map_page(mmu_l3_tbl, USER_PAGE_SECURE_MONITOR_ADDR, upage->user_address, userpage_attributes);
|
||||||
tlb_invalidate_page_inner_shareable((void *)USER_PAGE_SECURE_MONITOR_ADDR);
|
tlb_invalidate_page_inner_shareable((void *)USER_PAGE_SECURE_MONITOR_ADDR);
|
||||||
upage->secure_monitor_address = USER_PAGE_SECURE_MONITOR_ADDR;
|
upage->secure_monitor_address = USER_PAGE_SECURE_MONITOR_ADDR;
|
||||||
|
} else {
|
||||||
|
generic_panic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue