示例#1
0
//helper function. Retrieves an AES block, regardless of whether it is aligned or not with the underlying sector geometry
static inline int get_misaligned_block(ctr_crypto_interface *io, size_t sector, size_t sector_size, size_t block_size, uint8_t *buffer, void (*block_function)(void *io, void *buffer, uint64_t block, size_t block_count))
{
	size_t sectors_to_copy_prior = get_chunks_to_complete_relative_chunk_backwards(sector, sector_size, block_size);
	size_t sectors_to_copy_after = get_chunks_to_complete_relative_chunk(sector, sector_size, block_size);
	if (!sectors_to_copy_after)
		sectors_to_copy_after = block_size;

	size_t sector_count = sectors_to_copy_prior + sectors_to_copy_after;
	size_t buf_size = sector_count * sector_size;
	uint8_t buf[buf_size];
	int res = ctr_io_read_sector(io->lower_io, buf, buf_size, sector - sectors_to_copy_prior, sector_count);

	if (res)
		return res;

	size_t current_block = get_prev_relative_chunk(sector, sector_size, block_size);
	uint64_t block_pos = get_chunk_position(current_block, block_size);
	uint64_t block_start_offset = block_pos - get_chunk_position(sector - sectors_to_copy_prior, sector_size);
	uint8_t *pos = buf + block_start_offset;

	block_function(io, pos, current_block, 1);
	memcpy(buffer, pos, block_size);

	return res;
}
示例#2
0
//process the current window, and advance to the next one.
//Returns a negative number on a failure, a zero when there are still more windows to go, and a 1 when done.
static inline int process_window(ctr_crypto_interface *io, write_window *window, size_t sector_size, size_t block_size, void (*input_function)(void *io, void *buffer, uint64_t block, size_t block_count), void (*output_function)(void *io, void *buffer, uint64_t block, size_t block_count))
{
	//FIXME what if we try to read more than there is disk? Return zeros?
	size_t sectors_to_read = (window->window_size - window->window_offset) / sector_size;
	int res = ctr_io_read_sector(io->lower_io, window->window + window->window_offset, window->window_size - window->window_offset, window->current_sector, sectors_to_read);
	if (res)
		return -1;

	size_t block_start_offset = window->block_offset;
	uint8_t *pos = window->window + block_start_offset;

	size_t amount_to_copy = window->window_size - window->window_offset;
	if (amount_to_copy > window->buffer_size - window->buffer_offset)
		amount_to_copy = window->buffer_size - window->buffer_offset;

	//In the case that blocks are aligned to sectors, this is not necessary... FIXME
	//only process parts that won't be overwritten completely
	//	from block_start_offset to window->window_offset
	size_t blocks_to_process = CEIL(window->window_offset - block_start_offset, block_size);
	if (!blocks_to_process) blocks_to_process = 1;
	output_function(io, pos, window->block, blocks_to_process);

	//now copy data from buffer
	memcpy(window->window + window->window_offset, window->buffer + window->buffer_offset, amount_to_copy);
	window->buffer_offset += amount_to_copy;

	blocks_to_process = CEIL(amount_to_copy + window->window_offset - block_start_offset, block_size);
	input_function(io, pos, window->block, blocks_to_process);

	//We need to write out the full blocks processed actually, not just the sectors
	size_t sectors_processed = (amount_to_copy + window->window_offset) / sector_size;
	size_t sectors_to_copy = CEIL(blocks_to_process * block_size, sector_size);
	res = ctr_io_write_sector(io->lower_io, window->window, sectors_to_copy * sector_size, window->sector);
	if (res)
		return -2;

	//Copy sector that contain part of next block
	update_window(window, sectors_processed);

	return window->buffer_offset >= window->buffer_size;
}
示例#3
0
文件: diskio.c 项目: TuxSH/libctr9
DRESULT disk_read (
	BYTE pdrv,		/* Physical drive number to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res = RES_PARERR;
	if (pdrv < CTR_DISK_COUNT)
	{
		ctr_fatfs_disk *disk = &ctr_fatfs_disks[pdrv];

		if (!(disk->status & STA_NOINIT))
		{
			int result = ctr_io_read_sector(disk->io, buff, count * 0x200, sector + disk->sector_offset, count);
			res = result ? RES_ERROR : RES_OK;
		}
	}

	return res;
}
示例#4
0
//Sets up the window
static inline int setup_window(ctr_crypto_interface *io, write_window *window, size_t sector, size_t sector_size, size_t block_size)
{
	//window_size is a multiple of the sector size by definition

	//What if sectors_to_copy > window_size?
	//That can never happen, since
	//	window_size == lcm(sector_size, block_size) * 4 + sector_size * sectors_per_block
	//so window size should be large enough for at least 4 blocks
	size_t sectors_to_copy_prior = get_chunks_to_complete_relative_chunk_backwards(sector, sector_size, block_size);

	window->sector = sector - sectors_to_copy_prior;
	window->current_sector = sector;
	window->sector_size = sector_size;

	window->block = get_prev_relative_chunk(window->current_sector, sector_size, block_size);
	window->block_offset = get_chunk_position(window->block, block_size) - get_chunk_position(window->sector, sector_size);
	window->block_size = block_size;

	window->window_offset = sectors_to_copy_prior * sector_size;

	int res = ctr_io_read_sector(io->lower_io, window->window, window->window_size, window->sector, sectors_to_copy_prior);

	return res;
}
示例#5
0
int ctr_crypto_interface_read_sector(void *io, void *buffer, size_t buffer_size, size_t sector, size_t count)
{
	int res = 0;
	ctr_crypto_interface *crypto_io = io;
	const size_t sector_size = ctr_io_sector_size(crypto_io->lower_io);
	const size_t block_size = AES_BLOCK_SIZE;

	size_t result_count = count < buffer_size/sector_size ? count : buffer_size/sector_size;

	void (*block_function)(void *io, void *buffer, uint64_t block, size_t block_count);
	block_function = output;

	if (result_count)
	{
		size_t result_size = result_count * sector_size;
		uint8_t *current_processed = buffer;
		size_t current_block = get_prev_relative_chunk(sector, sector_size, block_size);

		res = ctr_io_read_sector(crypto_io->lower_io, buffer, buffer_size, sector, result_count);
		if (res)
			return res;

		//Part 1, deal with misaligned first block
		size_t sectors_to_copy_prior = get_chunks_to_complete_relative_chunk_backwards(sector, sector_size, block_size);
		if (sectors_to_copy_prior)
		{
			uint8_t buf[block_size];
			res = get_misaligned_block(crypto_io, sector, sector_size, block_size, buf, block_function);
			if (res)
				return res;

			//We now have the full block-- we now need to figure out which part of it to copy
			uint64_t sector_pos = get_chunk_position(sector, sector_size);
			uint64_t block_pos = get_chunk_position(current_block, block_size);

			size_t amount_to_copy = block_size - (sector_pos - block_pos);
			amount_to_copy = amount_to_copy < buffer_size ? amount_to_copy : buffer_size;
			memcpy(buffer, buf + (sector_pos - block_pos), amount_to_copy);
			current_processed += amount_to_copy;

			current_block++;
		}

		//Part 2, Deal with all intermediate blocks
		size_t bytes_left = result_size - (size_t)(current_processed - (uint8_t*)buffer);
		size_t blocks = FLOOR(bytes_left, block_size);
		if (blocks)
		{
			block_function(io, current_processed, current_block, blocks);
			current_block += blocks;
			current_processed += blocks * block_size;
			bytes_left -= blocks * block_size;
		}

		//Part 3, deal with the final block
		//FIXME what if we need to deal with a block that actually continues past the end of the disk? pad with zero?
		if (bytes_left)
		{
			uint8_t buf[block_size];
			//size_t current_sector = get_next_relative_block
			size_t block_sector = get_prev_relative_chunk(current_block, block_size, sector_size);
			res = get_misaligned_block(crypto_io, block_sector, sector_size, block_size, buf, block_function);
			if (res)
				return res;

			//We now have the full block-- we now need to figure out which part of it to copy
			uint64_t sector_pos = get_chunk_position(block_sector, sector_size);
			uint64_t block_pos = get_chunk_position(current_block, block_size);

			size_t amount_to_copy = block_size - (sector_pos - block_pos);
			amount_to_copy = amount_to_copy < bytes_left ? amount_to_copy : bytes_left;
			memcpy(current_processed, buf + (sector_pos - block_pos), amount_to_copy);
		}

	}
	return res;
}