Fusee: Implement BIS crypto functions.

This commit is contained in:
Michael Scire 2018-05-17 07:15:29 -06:00
parent 5631b27449
commit bb1dcb2655
3 changed files with 45 additions and 16 deletions

View file

@ -6,6 +6,8 @@
#include <stdbool.h> #include <stdbool.h>
#define DEVPART_IV_MAX_SIZE 16 #define DEVPART_IV_MAX_SIZE 16
#define DEVPART_KEY_MAX 2
#define DEVPART_KEY_MAX_SIZE 16
struct device_partition_t; 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_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 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 { typedef struct device_partition_t {
size_t sector_size; /* The size of a sector */ size_t sector_size; /* The size of a sector */
uint64_t start_sector; /* Offset in the parent device, in sectors. */ 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 read_cipher; /* Cipher for read operations. */
device_partition_cipher_t write_cipher; /* Cipher for write 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_initializer_t initializer; /* Initializer. */
device_partition_finalizer_t finalizer; /* Finalizer. */ device_partition_finalizer_t finalizer; /* Finalizer. */
@ -38,6 +46,7 @@ typedef struct device_partition_t {
void *crypto_work_buffer; /* Work buffer for crypto. */ void *crypto_work_buffer; /* Work buffer for crypto. */
uint64_t crypto_work_buffer_num_sectors; /* Size of the crypto work buffer in sectors. */ 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. */ uint8_t iv[DEVPART_IV_MAX_SIZE]; /* IV. */
bool initialized; bool initialized;
} device_partition_t; } device_partition_t;

View file

@ -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->CRYPTO_REG = keyslot_1 << 24;
} }
SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; 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. */ /* XOR. */
aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size); aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size);

View file

@ -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) { 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; unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */
(void)keyslot; unsigned int keyslot_b = 5;
(void)sector; size_t size = num_sectors * devpart->sector_size;
(void)num_sectors; switch (devpart->crypto_mode) {
/*devpart->crypto_work_buffer*/ case DevicePartitionCryptoMode_Ctr:
/* TODO */ 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; 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) { 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; unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */
(void)keyslot; unsigned int keyslot_b = 5;
(void)sector; size_t size = num_sectors * devpart->sector_size;
(void)num_sectors; switch (devpart->crypto_mode) {
/*devpart->crypto_work_buffer*/ case DevicePartitionCryptoMode_Ctr:
/* TODO */ 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; 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 }; static mmc_partition_info_t g_sd_mmcpart = { &g_sd_mmc, SWITCH_MICROSD, SDMMC_PARTITION_USER };