mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
all: Use bool where applicable (#30)
This commit is contained in:
parent
1d8f443f68
commit
83216409d2
15 changed files with 154 additions and 145 deletions
|
@ -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
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,7 +21,7 @@ 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;
|
||||||
|
@ -36,20 +37,20 @@ int check_mkey_revision(unsigned int revision) {
|
||||||
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,13 +59,13 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ unsigned int mkey_get_revision(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,9 +212,9 @@ 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. */
|
||||||
|
@ -223,49 +224,49 @@ int validate_package2_metadata(package2_meta_t *metadata) {
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,22 +275,22 @@ int validate_package2_metadata(package2_meta_t *metadata) {
|
||||||
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++) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,14 +398,7 @@ uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
@ -12,23 +13,23 @@
|
||||||
#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();
|
||||||
|
|
||||||
|
@ -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,18 +210,18 @@ 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();
|
||||||
|
|
||||||
|
@ -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]);
|
||||||
|
|
|
@ -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
|
|
@ -7,7 +7,7 @@ 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;
|
||||||
|
|
||||||
|
@ -29,34 +29,34 @@ int upage_init(upage_ref_t *upage, void *user_address) {
|
||||||
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;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue