From bb1dcb26550c0953e77ea4f2364b527161dc5bfe Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 17 May 2018 07:15:29 -0600 Subject: [PATCH] Fusee: Implement BIS crypto functions. --- fusee/fusee-secondary/src/device_partition.h | 11 ++++- fusee/fusee-secondary/src/se.c | 2 +- fusee/fusee-secondary/src/switch_fs.c | 48 ++++++++++++++------ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/fusee/fusee-secondary/src/device_partition.h b/fusee/fusee-secondary/src/device_partition.h index b61ab7a65..6e908f8a6 100644 --- a/fusee/fusee-secondary/src/device_partition.h +++ b/fusee/fusee-secondary/src/device_partition.h @@ -6,6 +6,8 @@ #include #define DEVPART_IV_MAX_SIZE 16 +#define DEVPART_KEY_MAX 2 +#define DEVPART_KEY_MAX_SIZE 16 struct device_partition_t; @@ -18,6 +20,12 @@ typedef int (*device_partition_cipher_t)(struct device_partition_t *devpart, uin typedef int (*device_partition_reader_t)(struct device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors); typedef int (*device_partition_writer_t)(struct device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors); +typedef enum DevicePartitionCryptoMode { + DevicePartitionCryptoMode_None, + DevicePartitionCryptoMode_Ctr, + DevicePartitionCryptoMode_Xts, +} DevicePartitionCryptoMode; + typedef struct device_partition_t { size_t sector_size; /* The size of a sector */ uint64_t start_sector; /* Offset in the parent device, in sectors. */ @@ -25,7 +33,7 @@ typedef struct device_partition_t { device_partition_cipher_t read_cipher; /* Cipher for read operations. */ device_partition_cipher_t write_cipher; /* Cipher for write operations. */ - uint64_t crypto_flags; /* Additional information for crypto, for conveniency. */ + DevicePartitionCryptoMode crypto_mode; /* Mode to use for cryptographic operations. */ device_partition_initializer_t initializer; /* Initializer. */ device_partition_finalizer_t finalizer; /* Finalizer. */ @@ -38,6 +46,7 @@ typedef struct device_partition_t { void *crypto_work_buffer; /* Work buffer for crypto. */ uint64_t crypto_work_buffer_num_sectors; /* Size of the crypto work buffer in sectors. */ + uint8_t keys[DEVPART_KEY_MAX][DEVPART_KEY_MAX_SIZE]; /* Key. */ uint8_t iv[DEVPART_IV_MAX_SIZE]; /* IV. */ bool initialized; } device_partition_t; diff --git a/fusee/fusee-secondary/src/se.c b/fusee/fusee-secondary/src/se.c index 100dd7217..db4c87ce8 100644 --- a/fusee/fusee-secondary/src/se.c +++ b/fusee/fusee-secondary/src/se.c @@ -438,7 +438,7 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24; } SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; - trigger_se_blocking_op(OP_START, dst, size, src, size); + trigger_se_blocking_op(OP_START, dst, size, dst, size); /* XOR. */ aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size); diff --git a/fusee/fusee-secondary/src/switch_fs.c b/fusee/fusee-secondary/src/switch_fs.c index d21979b26..79a9e6205 100644 --- a/fusee/fusee-secondary/src/switch_fs.c +++ b/fusee/fusee-secondary/src/switch_fs.c @@ -91,23 +91,43 @@ static int mmc_partition_write(device_partition_t *devpart, const void *src, uin } static int switchfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { - unsigned int keyslot = (unsigned int)devpart->crypto_flags; - (void)keyslot; - (void)sector; - (void)num_sectors; - /*devpart->crypto_work_buffer*/ - /* TODO */ - return 0; + unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */ + unsigned int keyslot_b = 5; + size_t size = num_sectors * devpart->sector_size; + switch (devpart->crypto_mode) { + case DevicePartitionCryptoMode_Ctr: + set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10); + se_aes_ctr_crypt(keyslot_a, devpart->crypto_work_buffer, size, devpart->crypto_work_buffer, size, devpart->iv, 0x10); + return 0; + case DevicePartitionCryptoMode_Xts: + set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10); + set_aes_keyslot(keyslot_b, devpart->keys[1], 0x10); + se_aes_128_xts_nintendo_decrypt(keyslot_a, keyslot_b, sector, devpart->crypto_work_buffer, devpart->crypto_work_buffer, num_sectors * devpart->sector_size, devpart->sector_size); + return 0; + case DevicePartitionCryptoMode_None: + default: + return 0; + } } static int switchfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { - unsigned int keyslot = (unsigned int)devpart->crypto_flags; - (void)keyslot; - (void)sector; - (void)num_sectors; - /*devpart->crypto_work_buffer*/ - /* TODO */ - return 0; + unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */ + unsigned int keyslot_b = 5; + size_t size = num_sectors * devpart->sector_size; + switch (devpart->crypto_mode) { + case DevicePartitionCryptoMode_Ctr: + set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10); + se_aes_ctr_crypt(keyslot_a, devpart->crypto_work_buffer, size, devpart->crypto_work_buffer, size, devpart->iv, 0x10); + return 0; + case DevicePartitionCryptoMode_Xts: + set_aes_keyslot(keyslot_a, devpart->keys[0], 0x10); + set_aes_keyslot(keyslot_b, devpart->keys[1], 0x10); + se_aes_128_xts_nintendo_encrypt(keyslot_a, keyslot_b, sector, devpart->crypto_work_buffer, devpart->crypto_work_buffer, num_sectors * devpart->sector_size, devpart->sector_size); + return 0; + case DevicePartitionCryptoMode_None: + default: + return 0; + } } static mmc_partition_info_t g_sd_mmcpart = { &g_sd_mmc, SWITCH_MICROSD, SDMMC_PARTITION_USER };