all: Use bool where applicable (#30)

This commit is contained in:
Mat M 2018-02-22 22:58:39 -05:00 committed by SciresM
parent 1d8f443f68
commit 83216409d2
15 changed files with 154 additions and 145 deletions

View file

@ -15,9 +15,8 @@ typedef struct {
void bootconfig_load_and_verify(const bootconfig_t *bootconfig); void bootconfig_load_and_verify(const bootconfig_t *bootconfig);
void bootconfig_clear(void); void bootconfig_clear(void);
/* Actual configuration getters. */ /* Actual configuration getters. */
int bootconfig_is_package2_plaintext(void); bool bootconfig_is_package2_plaintext(void);
void bootconfig_is_package2_unsigned(void); bool bootconfig_is_package2_unsigned(void);
#endif #endif

View file

@ -13,13 +13,13 @@ uint32_t configitem_set(enum ConfigItem item, uint64_t value) {
g_battery_profile = ((int)(value != 0)) & 1; g_battery_profile = ((int)(value != 0)) & 1;
} }
uint64_t configitem_is_recovery_boot(void) { bool configitem_is_recovery_boot(void) {
uint64_t is_recovery_boot; uint64_t is_recovery_boot;
if (configitem_get(CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) { if (configitem_get(CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) {
panic(); panic();
} }
return is_recovery_boot; return is_recovery_boot != 0;
} }
uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue) { uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue) {

View file

@ -1,9 +1,9 @@
#ifndef EXOSPHERE_CFG_ITEM_H #ifndef EXOSPHERE_CFG_ITEM_H
#define EXOSPHERE_CFG_ITEM_H #define EXOSPHERE_CFG_ITEM_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
enum ConfigItem { enum ConfigItem {
CONFIGITEM_DISABLEPROGRAMVERIFICATION = 1, CONFIGITEM_DISABLEPROGRAMVERIFICATION = 1,
CONFIGITEM_MEMORYCONFIGURATION = 2, CONFIGITEM_MEMORYCONFIGURATION = 2,
@ -23,7 +23,7 @@ enum ConfigItem {
uint32_t configitem_set(enum ConfigItem item, uint64_t value); uint32_t configitem_set(enum ConfigItem item, uint64_t value);
uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue); uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue);
uint64_t configitem_is_recovery_boot(void); bool configitem_is_recovery_boot(void);
uint64_t configitem_is_retail(void); bool configitem_is_retail(void);
#endif #endif

View file

@ -56,7 +56,7 @@ static void gf128_mul(uint8_t *dst, const uint8_t *x, const uint8_t *y) {
/* Performs an AES-GCM GHASH operation over the data into dst. */ /* Performs an AES-GCM GHASH operation over the data into dst. */
static void ghash(void *dst, const void *data, size_t data_size, const void *j_block, int encrypt) { static void ghash(void *dst, const void *data, size_t data_size, const void *j_block, bool encrypt) {
uint8_t x[0x10]; uint8_t x[0x10];
uint8_t h[0x10]; uint8_t h[0x10];
@ -112,7 +112,7 @@ static void ghash(void *dst, const void *data, size_t data_size, const void *j_b
/* This function is a doozy. It decrypts and validates a (non-standard) AES-GCM wrapped keypair. */ /* This function is a doozy. It decrypts and validates a (non-standard) AES-GCM wrapped keypair. */
size_t gcm_decrypt_key(void *dst, size_t dst_size, const void *src, size_t src_size, const void *sealed_kek, size_t kek_size, const void *wrapped_key, size_t key_size, unsigned int usecase, int is_personalized) { size_t gcm_decrypt_key(void *dst, size_t dst_size, const void *src, size_t src_size, const void *sealed_kek, size_t kek_size, const void *wrapped_key, size_t key_size, unsigned int usecase, bool is_personalized) {
if (is_personalized == 0) { if (is_personalized == 0) {
/* Devkit keys use a different keyformat without a MAC/Device ID. */ /* Devkit keys use a different keyformat without a MAC/Device ID. */
if (src_size <= 0x10 || src_size - 0x10 > dst_size) { if (src_size <= 0x10 || src_size - 0x10 > dst_size) {
@ -132,20 +132,20 @@ size_t gcm_decrypt_key(void *dst, size_t dst_size, const void *src, size_t src_s
se_aes_ctr_crypt(KEYSLOT_SWITCH_TEMPKEY, dst, dst_size, src + 0x10, src_size - 0x10, src, 0x10); se_aes_ctr_crypt(KEYSLOT_SWITCH_TEMPKEY, dst, dst_size, src + 0x10, src_size - 0x10, src, 0x10);
if (is_personalized == 0) { if (!is_personalized) {
/* Devkit non-personalized keys have no further authentication. */ /* Devkit non-personalized keys have no further authentication. */
return src_size - 0x10; return src_size - 0x10;
} }
/* J = GHASH(CTR); */ /* J = GHASH(CTR); */
uint8_t j_block[0x10]; uint8_t j_block[0x10];
ghash(j_block, src, 0x10, NULL, 0); ghash(j_block, src, 0x10, NULL, false);
/* MAC = GHASH(PLAINTEXT) ^ ENCRYPT(J) */ /* MAC = GHASH(PLAINTEXT) ^ ENCRYPT(J) */
/* Note: That MAC is calculated over plaintext is non-standard. */ /* Note: That MAC is calculated over plaintext is non-standard. */
/* It is supposed to be over the ciphertext. */ /* It is supposed to be over the ciphertext. */
uint8_t calc_mac[0x10]; uint8_t calc_mac[0x10];
ghash(calc_mac, dst, src_size - 0x20, j_block, 1); ghash(calc_mac, dst, src_size - 0x20, j_block, true);
/* Const-time memcmp. */ /* Const-time memcmp. */
const uint8_t *src_bytes = src; const uint8_t *src_bytes = src;

View file

@ -1,8 +1,13 @@
#ifndef EXOSPHERE_GCM_H #ifndef EXOSPHERE_GCM_H
#define EXOSPHERE_GCM_H #define EXOSPHERE_GCM_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
size_t gcm_decrypt_key(void *dst, size_t dst_size, const void *src, size_t src_size, const void *sealed_kek, size_t kek_size, const void *wrapped_key, size_t key_size, unsigned int usecase, int is_personalized); size_t gcm_decrypt_key(void *dst, size_t dst_size,
const void *src, size_t src_size,
const void *sealed_kek, size_t kek_size,
const void *wrapped_key, size_t key_size,
unsigned int usecase, bool is_personalized);
#endif #endif

View file

@ -1,3 +1,4 @@
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "utils.h" #include "utils.h"
@ -5,7 +6,7 @@
#include "se.h" #include "se.h"
unsigned int g_mkey_revision = 0; unsigned int g_mkey_revision = 0;
int g_determined_mkey_revision = 0; bool g_determined_mkey_revision = false;
uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10]; uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10];
@ -20,9 +21,9 @@ const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] =
{0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ {0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */
}; };
int check_mkey_revision(unsigned int revision) { bool check_mkey_revision(unsigned int revision) {
uint8_t final_vector[0x10]; uint8_t final_vector[0x10];
unsigned int check_keyslot = KEYSLOT_SWITCH_MASTERKEY; unsigned int check_keyslot = KEYSLOT_SWITCH_MASTERKEY;
if (revision > 0) { if (revision > 0) {
/* Generate old master key array. */ /* Generate old master key array. */
@ -32,24 +33,24 @@ int check_mkey_revision(unsigned int revision) {
check_keyslot = KEYSLOT_SWITCH_TEMPKEY; check_keyslot = KEYSLOT_SWITCH_TEMPKEY;
} }
} }
se_aes_ecb_decrypt_block(check_keyslot, final_vector, 0x10, mkey_vectors[0], 0x10); se_aes_ecb_decrypt_block(check_keyslot, final_vector, 0x10, mkey_vectors[0], 0x10);
for (unsigned int i = 0; i < 0x10; i++) { for (unsigned int i = 0; i < 0x10; i++) {
if (final_vector[i] != 0) { if (final_vector[i] != 0) {
return 0; return false;
} }
} }
return 1; return true;
} }
void mkey_detect_revision(void) { void mkey_detect_revision(void) {
if (g_determined_mkey_revision == 1) { if (g_determined_mkey_revision) {
panic(); panic();
} }
for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) {
if (check_mkey_revision(rev)) { if (check_mkey_revision(rev)) {
g_determined_mkey_revision = 1; g_determined_mkey_revision = true;
g_mkey_revision = rev; g_mkey_revision = rev;
break; break;
} }
@ -58,28 +59,28 @@ void mkey_detect_revision(void) {
/* We must have determined the master key, or we're not running on a Switch. */ /* We must have determined the master key, or we're not running on a Switch. */
/* TODO: When panic is implemented, make this a really distinctive color. */ /* TODO: When panic is implemented, make this a really distinctive color. */
/* Maybe bright red? */ /* Maybe bright red? */
if (g_determined_mkey_revision == 0) { if (!g_determined_mkey_revision) {
panic(); panic();
} }
} }
unsigned int mkey_get_revision(void) { unsigned int mkey_get_revision(void) {
if (g_determined_mkey_revision == 0) { if (!g_determined_mkey_revision) {
panic(); panic();
} }
return g_mkey_revision; return g_mkey_revision;
} }
unsigned int mkey_get_keyslot(unsigned int revision) { unsigned int mkey_get_keyslot(unsigned int revision) {
if (g_determined_mkey_revision == 0 || revision >= MASTERKEY_REVISION_MAX) { if (!g_determined_mkey_revision || revision >= MASTERKEY_REVISION_MAX) {
panic(); panic();
} }
if (revision > g_mkey_revision) { if (revision > g_mkey_revision) {
panic(); panic();
} }
if (revision == g_mkey_revision) { if (revision == g_mkey_revision) {
return KEYSLOT_SWITCH_MASTERKEY; return KEYSLOT_SWITCH_MASTERKEY;
} else { } else {

View file

@ -1,6 +1,7 @@
#ifndef EXOSPHERE_MMU_H #ifndef EXOSPHERE_MMU_H
#define EXOSPHERE_MMU_H #define EXOSPHERE_MMU_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "utils.h" #include "utils.h"

View file

@ -1,3 +1,4 @@
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "utils.h" #include "utils.h"
@ -90,7 +91,7 @@ void setup_boot_config(void) {
} }
} }
int rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) { bool rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) {
uint8_t message[RSA_2048_BYTES]; uint8_t message[RSA_2048_BYTES];
uint8_t h_buf[0x24]; uint8_t h_buf[0x24];
@ -102,7 +103,7 @@ int rsa2048_pss_verify(const void *signature, size_t signature_size, const void
/* Validate sanity byte. */ /* Validate sanity byte. */
if (message[RSA_2048_BYTES - 1] != 0xBC) { if (message[RSA_2048_BYTES - 1] != 0xBC) {
return 0; return false;
} }
/* Copy Salt into MGF1 Hash Buffer. */ /* Copy Salt into MGF1 Hash Buffer. */
@ -211,85 +212,85 @@ void verify_header_signature(package2_header_t *header) {
} }
} }
int validate_package2_metadata(package2_meta_t *metadata) { bool validate_package2_metadata(package2_meta_t *metadata) {
if (metadata->magic != MAGIC_PK21) { if (metadata->magic != MAGIC_PK21) {
return 0; return false;
} }
/* Package2 size, version number is stored XORed in header CTR. */ /* Package2 size, version number is stored XORed in header CTR. */
/* Nintendo, what the fuck? */ /* Nintendo, what the fuck? */
uint32_t package_size = metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3]; uint32_t package_size = metadata->ctr_dwords[0] ^ metadata->ctr_dwords[2] ^ metadata->ctr_dwords[3];
uint8_t header_version = (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF); uint8_t header_version = (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF);
/* Ensure package isn't too big or too small. */ /* Ensure package isn't too big or too small. */
if (package_size <= sizeof(package2_header_t) || package_size > PACKAGE2_SIZE_MAX - sizeof(package2_header_t)) { if (package_size <= sizeof(package2_header_t) || package_size > PACKAGE2_SIZE_MAX - sizeof(package2_header_t)) {
return 0; return false;
} }
/* Validate that we're working with a header we know how to handle. */ /* Validate that we're working with a header we know how to handle. */
if (header_version > MASTERKEY_REVISION_MAX) { if (header_version > MASTERKEY_REVISION_MAX) {
return 0; return false;
} }
/* Require aligned entrypoint. */ /* Require aligned entrypoint. */
if (metadata->entrypoint & 3) { if (metadata->entrypoint & 3) {
return 0; return false;
} }
/* Validate section size sanity. */ /* Validate section size sanity. */
if (metadata->section_sizes[0] + metadata->section_sizes[1] + metadata->section_sizes[2] + sizeof(package2_header_t) != package_size) { if (metadata->section_sizes[0] + metadata->section_sizes[1] + metadata->section_sizes[2] + sizeof(package2_header_t) != package_size) {
return 0; return false;
} }
int entrypoint_found = 0; bool entrypoint_found = false;
/* Header has space for 4 sections, but only 3 are validated/potentially loaded on hardware. */ /* Header has space for 4 sections, but only 3 are validated/potentially loaded on hardware. */
for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) { for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) {
/* Validate section size alignment. */ /* Validate section size alignment. */
if (metadata->section_sizes[section] & 3) { if (metadata->section_sizes[section] & 3) {
return 0; return false;
} }
/* Validate section does not overflow. */ /* Validate section does not overflow. */
if (check_32bit_additive_overflow(metadata->section_offsets[section], metadata->section_sizes[section])) { if (check_32bit_additive_overflow(metadata->section_offsets[section], metadata->section_sizes[section])) {
return 0; return false;
} }
/* Check for entrypoint presence. */ /* Check for entrypoint presence. */
uint32_t section_end = metadata->section_offsets[section] + metadata->section_sizes[section]; uint32_t section_end = metadata->section_offsets[section] + metadata->section_sizes[section];
if (metadata->section_offsets[section] <= metadata->entrypoint && metadata->entrypoint < section_end) { if (metadata->section_offsets[section] <= metadata->entrypoint && metadata->entrypoint < section_end) {
entrypoint_found = 1; entrypoint_found = true;
} }
/* Ensure no overlap with later sections. */ /* Ensure no overlap with later sections. */
for (unsigned int later_section = section + 1; later_section < PACKAGE2_SECTION_MAX; later_section++) { for (unsigned int later_section = section + 1; later_section < PACKAGE2_SECTION_MAX; later_section++) {
uint32_t later_section_end = metadata->section_offsets[later_section] + metadata->section_sizes[later_section]; uint32_t later_section_end = metadata->section_offsets[later_section] + metadata->section_sizes[later_section];
if (overlaps(metadata->section_offsets[section], section_end, metadata->section_offsets[later_section], later_section_end)) { if (overlaps(metadata->section_offsets[section], section_end, metadata->section_offsets[later_section], later_section_end)) {
return 0; return false;
} }
} }
/* Validate section hashes. */ /* Validate section hashes. */
void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + metadata->section_offsets[section]); void *section_data = (void *)((uint8_t *)NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS + sizeof(package2_header_t) + metadata->section_offsets[section]);
uint8_t calculated_hash[0x20]; uint8_t calculated_hash[0x20];
se_calculate_sha256(calculated_hash, section_data, metadata->section_sizes[section]); se_calculate_sha256(calculated_hash, section_data, metadata->section_sizes[section]);
if (memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) { if (memcmp(calculated_hash, metadata->section_hashes[section], sizeof(metadata->section_hashes[section])) != 0) {
return 0; return false;
} }
} }
/* Ensure that entrypoint is present in one of our sections. */ /* Ensure that entrypoint is present in one of our sections. */
if (!entrypoint_found) { if (!entrypoint_found) {
return 0; return false;
} }
/* Perform version checks. */ /* Perform version checks. */
/* We will be compatible with all package2s released before current, but not newer ones. */ /* We will be compatible with all package2s released before current, but not newer ones. */
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_400_CURRENT) { if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_400_CURRENT) {
return 0; return false;
} }
return 1; return true;
} }
/* Decrypts package2 header, and returns the master key revision required. */ /* Decrypts package2 header, and returns the master key revision required. */
@ -322,12 +323,12 @@ void load_package2_sections(package2_meta_t *metadata, uint32_t master_key_rev)
void *load_buf = NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS; void *load_buf = NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS;
/* Check whether any of our sections overlap this region. If they do, we must relocate and copy from elsewhere. */ /* Check whether any of our sections overlap this region. If they do, we must relocate and copy from elsewhere. */
int needs_relocation = 0; bool needs_relocation = false;
for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) { for (unsigned int section = 0; section < PACKAGE2_SECTION_MAX; section++) {
uint64_t section_start = DRAM_BASE_PHYSICAL + (uint64_t)metadata->section_offsets[section]; uint64_t section_start = DRAM_BASE_PHYSICAL + (uint64_t)metadata->section_offsets[section];
uint64_t section_end = section_start + (uint64_t)metadata->section_sizes[section]; uint64_t section_end = section_start + (uint64_t)metadata->section_sizes[section];
if (overlaps(section_start, section_end, (uint64_t)(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS), (uint64_t)(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS) + PACKAGE2_SIZE_MAX)) { if (overlaps(section_start, section_end, (uint64_t)(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS), (uint64_t)(NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS) + PACKAGE2_SIZE_MAX)) {
needs_relocation = 1; needs_relocation = true;
} }
} }
if (needs_relocation) { if (needs_relocation) {
@ -336,7 +337,7 @@ void load_package2_sections(package2_meta_t *metadata, uint32_t master_key_rev)
/* However, Nintendo tries panics after 8 loops if a safe section is not found. */ /* However, Nintendo tries panics after 8 loops if a safe section is not found. */
/* This should never be the case, mathematically. */ /* This should never be the case, mathematically. */
/* We will replicate this behavior. */ /* We will replicate this behavior. */
int found_safe_carveout = 0; bool found_safe_carveout = false;
uint64_t potential_base_start = DRAM_BASE_PHYSICAL; uint64_t potential_base_start = DRAM_BASE_PHYSICAL;
uint64_t potential_base_end = potential_base_start + PACKAGE2_SIZE_MAX; uint64_t potential_base_end = potential_base_start + PACKAGE2_SIZE_MAX;
for (unsigned int i = 0; i < 8; i++) { for (unsigned int i = 0; i < 8; i++) {

View file

@ -214,7 +214,7 @@ void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_sr
trigger_se_aes_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); trigger_se_aes_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size);
} }
void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, int encrypt, unsigned int (*callback)(void)) { void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) {
if (keyslot >= KEYSLOT_AES_MAX) { if (keyslot >= KEYSLOT_AES_MAX) {
panic(); panic();
} }
@ -224,7 +224,6 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr,
} }
/* Setup Config register. */ /* Setup Config register. */
encrypt &= 1;
if (encrypt) { if (encrypt) {
SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY);
} else { } else {
@ -263,17 +262,17 @@ void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint
/* Unknown what this write does, but official code writes it for CTR mode. */ /* Unknown what this write does, but official code writes it for CTR mode. */
SECURITY_ENGINE->_0x80C = 1; SECURITY_ENGINE->_0x80C = 1;
set_se_ctr(ctr); set_se_ctr(ctr);
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x81E, 1, callback); se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x81E, true, callback);
} }
void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) { void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) {
set_aes_keyslot_iv(keyslot, iv, 0x10); set_aes_keyslot_iv(keyslot, iv, 0x10);
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x44, 1, callback); se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x44, true, callback);
} }
void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) { void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)) {
set_aes_keyslot_iv(keyslot, iv, 0x10); set_aes_keyslot_iv(keyslot, iv, 0x10);
se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, 0, callback); se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback);
} }

View file

@ -97,7 +97,7 @@ smc_table_t g_smc_tables[2] = {
} }
}; };
int g_is_smc_in_progress = 0; bool g_is_smc_in_progress = false;
uint32_t (*g_smc_callback)(void *, uint64_t) = NULL; uint32_t (*g_smc_callback)(void *, uint64_t) = NULL;
uint64_t g_smc_callback_key = 0; uint64_t g_smc_callback_key = 0;
@ -162,9 +162,9 @@ uint32_t smc_wrapper_sync(smc_args_t *args, uint32_t (*handler)(smc_args_t *)) {
if (g_is_smc_in_progress) { if (g_is_smc_in_progress) {
return 3; return 3;
} }
g_is_smc_in_progress = 1; g_is_smc_in_progress = true;
result = handler(args); result = handler(args);
g_is_smc_in_progress = 0; g_is_smc_in_progress = false;
return result; return result;
} }
@ -191,7 +191,7 @@ uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *),
/* smcCheckStatus needs to be called. */ /* smcCheckStatus needs to be called. */
result = 3; result = 3;
} }
g_is_smc_in_progress = 0; g_is_smc_in_progress = false;
return result; return result;
} }
@ -271,7 +271,7 @@ uint32_t smc_exp_mod_get_result(void *buf, uint64_t size) {
se_get_exp_mod_output(buf, 0x100); se_get_exp_mod_output(buf, 0x100);
/* smc_exp_mod is done now. */ /* smc_exp_mod is done now. */
g_is_smc_in_progress = 0; g_is_smc_in_progress = false;
return 0; return 0;
} }
@ -297,7 +297,7 @@ uint32_t smc_crypt_aes_status_check(void *buf, uint64_t size) {
return 3; return 3;
} }
/* smc_crypt_aes is done now. */ /* smc_crypt_aes is done now. */
g_is_smc_in_progress = 0; g_is_smc_in_progress = false;
return 0; return 0;
} }
@ -346,7 +346,7 @@ uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey_get_result(void *buf, uint64_t siz
se_get_exp_mod_output(wrapped_titlekey, 0x100); se_get_exp_mod_output(wrapped_titlekey, 0x100);
if (tkey_rsa_oaep_unwrap(aes_wrapped_titlekey, 0x10, rsa_wrapped_titlekey, 0x100) != 0x10) { if (tkey_rsa_oaep_unwrap(aes_wrapped_titlekey, 0x10, rsa_wrapped_titlekey, 0x100) != 0x10) {
/* Failed to extract RSA OAEP wrapped key. */ /* Failed to extract RSA OAEP wrapped key. */
g_is_smc_in_progress = 0; g_is_smc_in_progress = false;
return 2; return 2;
} }
@ -357,7 +357,7 @@ uint32_t smc_unwrap_rsa_oaep_wrapped_titlekey_get_result(void *buf, uint64_t siz
p_sealed_key[1] = sealed_titlekey[1]; p_sealed_key[1] = sealed_titlekey[1];
/* smc_unwrap_rsa_oaep_wrapped_titlekey is done now. */ /* smc_unwrap_rsa_oaep_wrapped_titlekey is done now. */
g_is_smc_in_progress = 0; g_is_smc_in_progress = false;
return 0; return 0;
} }
@ -394,18 +394,11 @@ uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) {
/* This is an interesting SMC. */ /* This is an interesting SMC. */
/* The kernel must NEVER be unable to get random bytes, if it needs them */ /* The kernel must NEVER be unable to get random bytes, if it needs them */
/* As such: */ /* As such: */
uint32_t result; uint32_t result;
/* TODO: Make atomic. */ /* TODO: Make atomic. */
if (g_is_smc_in_progress == 0) { if (g_is_smc_in_progress) {
g_is_smc_in_progress = 1;
/* If the kernel isn't denied service by a usermode SMC, generate fresh random bytes. */
result = user_get_random_bytes(args);
/* Also, refill our cache while we have the chance in case we get denied later. */
randomcache_refill();
g_is_smc_in_progress = 0;
} else {
if (args->X[1] > 0x38) { if (args->X[1] > 0x38) {
return 2; return 2;
} }
@ -413,6 +406,13 @@ uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) {
size_t num_bytes = (size_t)args->X[1]; size_t num_bytes = (size_t)args->X[1];
randomcache_getbytes(&args->X[1], num_bytes); randomcache_getbytes(&args->X[1], num_bytes);
result = 0; result = 0;
} else {
g_is_smc_in_progress = true;
/* If the kernel isn't denied service by a usermode SMC, generate fresh random bytes. */
result = user_get_random_bytes(args);
/* Also, refill our cache while we have the chance in case we get denied later. */
randomcache_refill();
g_is_smc_in_progress = false;
} }
return result; return result;
} }

View file

@ -1,3 +1,4 @@
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "utils.h" #include "utils.h"
@ -12,26 +13,26 @@
#include "titlekey.h" #include "titlekey.h"
/* Globals. */ /* Globals. */
int g_crypt_aes_done = 0; bool g_crypt_aes_done = false;
int g_exp_mod_done = 0; bool g_exp_mod_done = false;
uint8_t g_secure_exp_mod_exponent[0x100]; uint8_t g_secure_exp_mod_exponent[0x100];
uint8_t g_rsa_oaep_exponent[0x100]; uint8_t g_rsa_oaep_exponent[0x100];
void set_exp_mod_done(int done) { void set_exp_mod_done(bool done) {
g_exp_mod_done = done & 1; g_exp_mod_done = done;
} }
int get_exp_mod_done(void) { bool get_exp_mod_done(void) {
return g_exp_mod_done; return g_exp_mod_done;
} }
uint32_t exp_mod_done_handler(void) { uint32_t exp_mod_done_handler(void) {
set_exp_mod_done(1); set_exp_mod_done(true);
se_trigger_interrupt(); se_trigger_interrupt();
return 0; return 0;
} }
@ -67,7 +68,7 @@ uint32_t user_exp_mod(smc_args_t *args) {
return 2; return 2;
} }
set_exp_mod_done(0); set_exp_mod_done(false);
/* Hardcode RSA keyslot 0. */ /* Hardcode RSA keyslot 0. */
set_rsa_keyslot(0, modulus, 0x100, exponent, exponent_size); set_rsa_keyslot(0, modulus, 0x100, exponent, exponent_size);
se_exp_mod(0, input, 0x100, exp_mod_done_handler); se_exp_mod(0, input, 0x100, exp_mod_done_handler);
@ -122,16 +123,16 @@ uint32_t user_generate_aes_kek(smc_args_t *args) {
uint8_t usecase = (uint8_t)((packed_options >> 5) & 3); uint8_t usecase = (uint8_t)((packed_options >> 5) & 3);
/* Switched the output based on whether it should be console unique. */ /* Switched the output based on whether it should be console unique. */
int is_personalized = (int)(packed_options & 1); bool is_personalized = (int)(packed_options & 1);
uint64_t is_recovery_boot = configitem_is_recovery_boot(); bool is_recovery_boot = configitem_is_recovery_boot();
/* Mask 2 is only allowed when booted from recovery. */ /* Mask 2 is only allowed when booted from recovery. */
if (mask_id == 2 && is_recovery_boot == 0) { if (mask_id == 2 && !is_recovery_boot) {
return 2; return 2;
} }
/* Mask 1 is only allowed when booted normally. */ /* Mask 1 is only allowed when booted normally. */
if (mask_id == 1 && is_recovery_boot != 0) { if (mask_id == 1 && is_recovery_boot) {
return 2; return 2;
} }
@ -209,21 +210,21 @@ uint32_t user_load_aes_key(smc_args_t *args) {
} }
void set_crypt_aes_done(int done) { void set_crypt_aes_done(bool done) {
g_crypt_aes_done = done & 1; g_crypt_aes_done = done;
} }
int get_crypt_aes_done(void) { bool get_crypt_aes_done(void) {
return g_crypt_aes_done; return g_crypt_aes_done;
} }
uint32_t crypt_aes_done_handler(void) { uint32_t crypt_aes_done_handler(void) {
se_check_for_error(); se_check_for_error();
set_crypt_aes_done(1); set_crypt_aes_done(true);
se_trigger_interrupt(); se_trigger_interrupt();
return 0; return 0;
} }
@ -243,7 +244,7 @@ uint32_t user_crypt_aes(smc_args_t *args) {
panic(); panic();
} }
set_crypt_aes_done(0); set_crypt_aes_done(false);
uint64_t result = 0; uint64_t result = 0;
switch (mode) { switch (mode) {
@ -272,7 +273,7 @@ uint32_t user_generate_specific_aes_key(smc_args_t *args) {
uint64_t wrapped_key[2]; uint64_t wrapped_key[2];
uint8_t key[0x10]; uint8_t key[0x10];
unsigned int master_key_rev; unsigned int master_key_rev;
int should_mask; bool should_mask;
wrapped_key[0] = args->X[1]; wrapped_key[0] = args->X[1];
wrapped_key[1] = args->X[2]; wrapped_key[1] = args->X[2];
@ -283,7 +284,7 @@ uint32_t user_generate_specific_aes_key(smc_args_t *args) {
if (args->X[3] > 1) { if (args->X[3] > 1) {
return 2; return 2;
} }
should_mask = (int)(args->X[3]); should_mask = args->X[3] != 0;
unsigned int keyslot; unsigned int keyslot;
@ -358,7 +359,7 @@ uint32_t user_compute_cmac(smc_args_t *args) {
uint32_t user_load_rsa_oaep_key(smc_args_t *args) { uint32_t user_load_rsa_oaep_key(smc_args_t *args) {
uint64_t sealed_kek[2]; uint64_t sealed_kek[2];
uint64_t wrapped_key[2]; uint64_t wrapped_key[2];
int is_personalized; bool is_personalized;
uint8_t user_data[0x400]; uint8_t user_data[0x400];
void *user_address; void *user_address;
@ -372,7 +373,7 @@ uint32_t user_load_rsa_oaep_key(smc_args_t *args) {
if (args->X[3] > 1) { if (args->X[3] > 1) {
return 2; return 2;
} }
is_personalized = (int)args->X[3]; is_personalized = args->X[3] != 0;
user_address = (void *)args->X[4]; user_address = (void *)args->X[4];
size = (size_t)args->X[5]; size = (size_t)args->X[5];
wrapped_key[0] = args->X[6]; wrapped_key[0] = args->X[6];
@ -401,7 +402,7 @@ uint32_t user_load_rsa_oaep_key(smc_args_t *args) {
uint32_t user_decrypt_rsa_private_key(smc_args_t *args) { uint32_t user_decrypt_rsa_private_key(smc_args_t *args) {
uint64_t sealed_kek[2]; uint64_t sealed_kek[2];
uint64_t wrapped_key[2]; uint64_t wrapped_key[2];
int is_personalized; bool is_personalized;
uint8_t user_data[0x400]; uint8_t user_data[0x400];
void *user_address; void *user_address;
@ -415,7 +416,7 @@ uint32_t user_decrypt_rsa_private_key(smc_args_t *args) {
if (args->X[3] > 1) { if (args->X[3] > 1) {
return 2; return 2;
} }
is_personalized = (int)args->X[3]; is_personalized = args->X[3] != 0;
user_address = (void *)args->X[4]; user_address = (void *)args->X[4];
size = (size_t)args->X[5]; size = (size_t)args->X[5];
wrapped_key[0] = args->X[6]; wrapped_key[0] = args->X[6];
@ -453,7 +454,7 @@ uint32_t user_decrypt_rsa_private_key(smc_args_t *args) {
uint32_t user_load_secure_exp_mod_key(smc_args_t *args) { uint32_t user_load_secure_exp_mod_key(smc_args_t *args) {
uint64_t sealed_kek[2]; uint64_t sealed_kek[2];
uint64_t wrapped_key[2]; uint64_t wrapped_key[2];
int is_personalized; bool is_personalized;
uint8_t user_data[0x400]; uint8_t user_data[0x400];
void *user_address; void *user_address;
@ -467,7 +468,7 @@ uint32_t user_load_secure_exp_mod_key(smc_args_t *args) {
if (args->X[3] > 1) { if (args->X[3] > 1) {
return 2; return 2;
} }
is_personalized = (int)args->X[3]; is_personalized = args->X[3] != 0;
user_address = (void *)args->X[4]; user_address = (void *)args->X[4];
size = (size_t)args->X[5]; size = (size_t)args->X[5];
wrapped_key[0] = args->X[6]; wrapped_key[0] = args->X[6];
@ -521,7 +522,7 @@ uint32_t user_secure_exp_mod(smc_args_t *args) {
return 2; return 2;
} }
set_exp_mod_done(0); set_exp_mod_done(false);
/* Hardcode RSA keyslot 0. */ /* Hardcode RSA keyslot 0. */
set_rsa_keyslot(0, modulus, 0x100, g_secure_exp_mod_exponent, 0x100); set_rsa_keyslot(0, modulus, 0x100, g_secure_exp_mod_exponent, 0x100);
se_exp_mod(0, input, 0x100, exp_mod_done_handler); se_exp_mod(0, input, 0x100, exp_mod_done_handler);
@ -554,7 +555,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) {
return 2; return 2;
} }
set_exp_mod_done(0); set_exp_mod_done(false);
/* Expected label_hash occupies args->X[3] to args->X[6]. */ /* Expected label_hash occupies args->X[3] to args->X[6]. */
tkey_set_expected_label_hash(&args->X[3]); tkey_set_expected_label_hash(&args->X[3]);

View file

@ -19,10 +19,10 @@ uint32_t user_load_titlekey(smc_args_t *args);
uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args); uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args);
void set_crypt_aes_done(int done); void set_crypt_aes_done(bool done);
int get_crypt_aes_done(void); bool get_crypt_aes_done(void);
void set_exp_mod_done(int done); void set_exp_mod_done(bool done);
int get_exp_mod_done(void); bool get_exp_mod_done(void);
#endif #endif

View file

@ -7,10 +7,10 @@ uint64_t g_secure_page_user_address = NULL;
/* Create a user page reference for the desired address. */ /* Create a user page reference for the desired address. */
/* Returns 1 on success, 0 on failure. */ /* Returns 1 on success, 0 on failure. */
int upage_init(upage_ref_t *upage, void *user_address) { bool upage_init(upage_ref_t *upage, void *user_address) {
upage->user_page = get_page_for_address(user_address); upage->user_page = get_page_for_address(user_address);
upage->secure_page = 0ULL; upage->secure_page = 0ULL;
if (g_secure_page_user_address != NULL) { if (g_secure_page_user_address != NULL) {
/* Different physical address indicate SPL was rebooted, or another process got access to svcCallSecureMonitor. Panic. */ /* Different physical address indicate SPL was rebooted, or another process got access to svcCallSecureMonitor. Panic. */
if (g_secure_page_user_address != upage->user_page) { if (g_secure_page_user_address != upage->user_page) {
@ -25,38 +25,38 @@ int upage_init(upage_ref_t *upage, void *user_address) {
upage->secure_page = SECURE_USER_PAGE_ADDR; upage->secure_page = SECURE_USER_PAGE_ADDR;
} }
} }
return upage->secure_page != 0ULL; return upage->secure_page != 0ULL;
} }
int user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, size_t size) { bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, size_t size) {
/* Fail if the page doesn't match. */ /* Fail if the page doesn't match. */
if (get_page_for_address(user_src) != upage->user_page) { if (get_page_for_address(user_src) != upage->user_page) {
return 0; return false;
} }
/* Fail if we go past the page boundary. */ /* Fail if we go past the page boundary. */
if (size != 0 && get_page_for_address(user_src + size - 1) != upage->user_page) { if (size != 0 && get_page_for_address(user_src + size - 1) != upage->user_page) {
return 0; return false;
} }
void *secure_src = (void *)(upage->secure_page + ((uint64_t)user_src - upage->user_page)); void *secure_src = (void *)(upage->secure_page + ((uint64_t)user_src - upage->user_page));
memcpy(secure_dst, secure_src, size); memcpy(secure_dst, secure_src, size);
return 1; return true;
} }
int secure_copy_to_user(upage_ref_t *upage, void *user_dst, void *secure_src, size_t size) { bool secure_copy_to_user(upage_ref_t *upage, void *user_dst, void *secure_src, size_t size) {
/* Fail if the page doesn't match. */ /* Fail if the page doesn't match. */
if (get_page_for_address(user_dst) != upage->user_page) { if (get_page_for_address(user_dst) != upage->user_page) {
return 0; return false;
} }
/* Fail if we go past the page boundary. */ /* Fail if we go past the page boundary. */
if (size != 0 && get_page_for_address(user_dst + size - 1) != upage->user_page) { if (size != 0 && get_page_for_address(user_dst + size - 1) != upage->user_page) {
return 0; return false;
} }
void *secure_dst = (void *)(upage->secure_page + ((uint64_t)user_dst - upage->user_page)); void *secure_dst = (void *)(upage->secure_page + ((uint64_t)user_dst - upage->user_page));
memcpy(secure_dst, secure_src, size); memcpy(secure_dst, secure_src, size);
return 1; return true;
} }

View file

@ -1,6 +1,7 @@
#ifndef EXOSPHERE_USERPAGE_H #ifndef EXOSPHERE_USERPAGE_H
#define EXOSPHERE_USERPAGE_H #define EXOSPHERE_USERPAGE_H
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#define SECURE_USER_PAGE_ADDR (0x1F01F4000ULL) #define SECURE_USER_PAGE_ADDR (0x1F01F4000ULL)
@ -10,10 +11,10 @@ typedef struct {
uint64_t secure_page; uint64_t secure_page;
} upage_ref_t; } upage_ref_t;
int upage_init(upage_ref_t *user_page, void *user_address); bool upage_init(upage_ref_t *user_page, void *user_address);
int user_copy_to_secure(upage_ref_t *user_page, void *secure_dst, void *user_src, size_t size); bool user_copy_to_secure(upage_ref_t *user_page, void *secure_dst, void *user_src, size_t size);
int secure_copy_to_user(upage_ref_t *user_page, void *user_dst, void *secure_src, size_t size); bool secure_copy_to_user(upage_ref_t *user_page, void *user_dst, void *secure_src, size_t size);
static inline uint64_t get_page_for_address(void *address) { static inline uint64_t get_page_for_address(void *address) {
return ((uint64_t)(address)) & 0xFFFFFFFFFFFFF000ULL; return ((uint64_t)(address)) & 0xFFFFFFFFFFFFF000ULL;

View file

@ -1,8 +1,9 @@
#ifndef EXOSPHERE_UTILS_H #ifndef EXOSPHERE_UTILS_H
#define EXOSPHERE_UTILS_H #define EXOSPHERE_UTILS_H
#include <stdint.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#define BIT(x) (1u << (x)) #define BIT(x) (1u << (x))
#define BITL(x) (1ull << (x)) #define BITL(x) (1ull << (x))
@ -19,18 +20,18 @@ static inline uint32_t read32be(const unsigned char *dword, size_t offset) {
return __builtin_bswap32(read32le(dword, offset)); return __builtin_bswap32(read32le(dword, offset));
} }
static __attribute__((noinline)) int check_32bit_additive_overflow(uint32_t a, uint32_t b) { static __attribute__((noinline)) bool check_32bit_additive_overflow(uint32_t a, uint32_t b) {
uint64_t x = (uint64_t)a + (uint64_t)b; uint64_t x = (uint64_t)a + (uint64_t)b;
return x > (uint64_t)(UINT32_MAX); return x > (uint64_t)(UINT32_MAX);
} }
static __attribute__((noinline)) int overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) static __attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be)
{ {
if(as <= bs && bs <= ae) if(as <= bs && bs <= ae)
return 1; return true;
if(bs <= as && as <= be) if(bs <= as && as <= be)
return 1; return true;
return 0; return false;
} }