Commit 068a5e71 authored by g3gg0's avatar g3gg0
Browse files

io_crypt: split cipher and handling into separate files

--HG--
branch : unified
parent 852ad87b59fd
# define the module name - make sure name is max 8 characters
MODULE_NAME=io_crypt
MODULE_OBJS=io_crypt.o crypt_lfsr64.o
MODULE_OBJS=io_crypt.o crypt_lfsr64.o hash_password.o
# include modules environment
include ../Makefile.modules
# include host tool makefile rules
include Makefile.io_decrypt
#ifdef HOST_PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define trace_write(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#else
#include <dryos.h>
#include <property.h>
#include <bmp.h>
#include <menu.h>
#include "../trace/trace.h"
#endif
#include <io_crypt.h>
#include <crypt_lfsr64.h>
#include "io_crypt.h"
#include "crypt_lfsr64.h"
extern uint32_t iocrypt_trace_ctx;
......@@ -25,25 +39,13 @@ static void crypt_lfsr64_clock(lfsr64_ctx_t *ctx, uint32_t clocks)
ctx->lfsr_state = lfsr;
}
/* xor the buffer with 8/32/64 bit alignment */
/* xor the buffer with 8/64 bit alignment */
static void crypt_lfsr64_xor_uint8(void *dst_in, void *src_in, lfsr64_ctx_t *ctx, uint32_t offset)
{
/* pick the correct byte from the encryption key */
uint8_t key = ((uint8_t *)&ctx->key)[offset % 8];
uint8_t *dst = (uint8_t *)dst_in;
uint8_t *src = (uint8_t *)src_in;
*dst = *src ^ key;
}
static void crypt_lfsr64_xor_uint32(void *dst_in, void *src_in, lfsr64_ctx_t *ctx, uint32_t offset)
{
/* pick the correct word from the encryption key */
uint32_t key = ((uint32_t *)&ctx->key)[(offset % 8) / 4];
uint32_t *dst = (uint32_t *)dst_in;
uint32_t *src = (uint32_t *)src_in;
*dst = *src ^ key;
*dst = *src ^ ctx->key_uint8[offset % 8];
}
static void crypt_lfsr64_xor_uint64(void *dst_in, void *src_in, lfsr64_ctx_t *ctx, uint32_t offset)
......@@ -51,50 +53,78 @@ static void crypt_lfsr64_xor_uint64(void *dst_in, void *src_in, lfsr64_ctx_t *ct
uint64_t *dst = (uint64_t *)dst_in;
uint64_t *src = (uint64_t *)src_in;
*dst = *src ^ ctx->key;
*dst = *src ^ ctx->key_uint64[offset % 8];
}
static void update_key(lfsr64_ctx_t *ctx, uint32_t offset, uint32_t force)
{
/* update the current encryption key whever reaching the next block */
if(force || (offset % CRYPT_BLOCKSIZE) == 0)
uint32_t block = offset / CRYPT_LFSR64_BLOCKSIZE;
if(!force)
{
uint32_t block = offset / CRYPT_BLOCKSIZE;
ctx->current_offset = offset;
/* first feed it with base key and block */
ctx->lfsr_state = ctx->password ^ block;
crypt_lfsr64_clock(ctx, 32);
/* then update it with the file offset again and shift by an amount based on file offset */
ctx->lfsr_state ^= block;
crypt_lfsr64_clock(ctx, (11 * block) % 128);
/* mask it again */
ctx->lfsr_state ^= ctx->password;
ctx->key = ctx->lfsr_state;
if(ctx->current_block == block)
{
return;
}
}
ctx->current_block = block;
/* first feed it with base key and block */
ctx->lfsr_state = ctx->password ^ block;
crypt_lfsr64_clock(ctx, 32);
/* then update it with the file offset again and shift by an amount based on file offset */
ctx->lfsr_state ^= block;
crypt_lfsr64_clock(ctx, (11 * block) % 128);
/* mask it again */
ctx->lfsr_state ^= ctx->password;
trace_write(iocrypt_trace_ctx, "update_key: offset 0x%08X, password: 0x%08X%08X, key: 0x%08X%08X", offset, (uint32_t)(ctx->password>>32), (uint32_t)ctx->password, (uint32_t)(ctx->lfsr_state>>32), (uint32_t)ctx->lfsr_state);
/* build an array with key elements for every offset in uint8_t mode */
//trace_write(iocrypt_trace_ctx, "update_key: key_uint8");
uint64_t lfsr = ctx->lfsr_state;
for(int pos = 0; pos < 8; pos++)
{
ctx->key_uint8[pos] = (uint8_t)(lfsr & 0xFF);
lfsr >>= 8;
//trace_write(iocrypt_trace_ctx, "update_key: 0x%02X", ctx->key_uint8[pos]);
}
/* build an array with key elements for every offset in uint64_t mode */
//trace_write(iocrypt_trace_ctx, "update_key: key_uint32");
for(int pos = 0; pos < 8; pos++)
{
uint32_t elem_addr = &ctx->key_uint64[pos];
trace_write(iocrypt_trace_ctx, "update_key: offset 0x%08X", offset);
trace_write(iocrypt_trace_ctx, "update_key: password: 0x%08X%08X", ctx->password);
trace_write(iocrypt_trace_ctx, "update_key: key: 0x%08X%08X", ctx->key);
memcpy((void*)elem_addr, &ctx->key_uint8[pos], 8 - pos);
memcpy((void*)elem_addr + (8-pos), ctx->key_uint8, pos);
//trace_write(iocrypt_trace_ctx, "update_key: 0x%08X%08X", (uint32_t)(ctx->key_uint64[pos]>>32), (uint32_t)ctx->key_uint64[pos]);
}
}
#define IS_UNALIGNED(x) ( (((uint32_t)dst) % (x)) || (((uint32_t)src) % (x)) )
#define IS_UNALIGNED(x) ((((uint32_t)dst) % (x)) || (((uint32_t)src) % (x)))
static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
{
lfsr64_ctx_t *ctx = (lfsr64_ctx_t *)ctx_in;
/* initial key creation */
update_key(ctx, offset, 1);
update_key(ctx, offset, 0);
/* try to get the addresses aligned */
trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint8 offset 0x%08X, length 0x%08X", offset, length);
while(IS_UNALIGNED(8) && (length > 0))
while((IS_UNALIGNED(8) || (offset % 8)) && (length > 0))
{
update_key(ctx, offset, 0);
uint32_t block_remain = offset % CRYPT_LFSR64_BLOCKSIZE;
if(block_remain == 0)
{
update_key(ctx, offset, 0);
}
crypt_lfsr64_xor_uint8(dst, src, ctx, offset);
dst += 1;
src += 1;
......@@ -102,13 +132,22 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
length -= 1;
}
/* for 64 bit encryption, we have to make sure that the memories and offsets are aligned */
trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint64 offset 0x%08X, length 0x%08X", offset, length);
if(!IS_UNALIGNED(8) && !(offset % 8))
if(!IS_UNALIGNED(8))
{
while(length >= 8)
{
update_key(ctx, offset, 0);
uint32_t block_remain = offset % CRYPT_LFSR64_BLOCKSIZE;
if(block_remain == 0)
{
update_key(ctx, offset, 0);
}
else if(block_remain < 8)
{
break;
}
crypt_lfsr64_xor_uint64(dst, src, ctx, offset);
dst += 8;
src += 8;
......@@ -117,26 +156,19 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
}
}
trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint32 offset 0x%08X, length 0x%08X", offset, length);
if(!IS_UNALIGNED(4) && !(offset % 4))
{
while(length >= 4)
{
update_key(ctx, offset, 0);
crypt_lfsr64_xor_uint32(dst, src, ctx, offset);
dst += 4;
src += 4;
offset += 4;
length -= 4;
}
}
/* do the rest */
trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint8 offset 0x%08X, length 0x%08X", offset, length);
while(length > 0)
{
update_key(ctx, offset, 0);
uint32_t block_remain = offset % CRYPT_LFSR64_BLOCKSIZE;
if(block_remain == 0)
{
update_key(ctx, offset, 0);
}
crypt_lfsr64_xor_uint8(dst, src, ctx, offset);
trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint8 offset 0x%08X, 0x%02X <- 0x%02X", offset, *dst, *src);
dst += 1;
src += 1;
offset += 1;
......@@ -159,7 +191,6 @@ static void crypt_lfsr64_deinit(void **crypt_ctx)
}
}
/* allocate and initialize an LFSR64 cipher ctx and save to pointer */
void crypt_lfsr64_init(void **crypt_ctx, uint64_t password)
{
......@@ -176,7 +207,7 @@ void crypt_lfsr64_init(void **crypt_ctx, uint64_t password)
ctx->cipher.decrypt = &crypt_lfsr64_decrypt;
ctx->cipher.deinit = &crypt_lfsr64_deinit;
ctx->password = password;
ctx->current_offset = 0;
ctx->current_block = 0xFFFFFFFF;
ctx->lfsr_state = 0;
/* setup initial cipher key */
......
#ifndef __CRYPT_LFSR_H
#define __CRYPT_LFSR_H
#define CRYPT_LFSR64_BLOCKSIZE 0x00002000
typedef struct
{
crypt_cipher_t cipher;
uint64_t lfsr_state;
uint64_t key;
uint8_t key_uint8[8];
uint64_t key_uint64[8];
uint64_t password;
uint32_t current_offset;
uint32_t current_block;
} lfsr64_ctx_t;
void crypt_lfsr64_init(void **crypt_ctx, uint64_t password);
#endif
#ifdef HOST_PROGRAM
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define trace_write(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#else
#include <dryos.h>
#include <property.h>
#include <bmp.h>
#include <menu.h>
#include "../trace/trace.h"
#endif
#include "io_crypt.h"
#include "crypt_lfsr64.h"
extern uint32_t iocrypt_trace_ctx;
static void iocrypt_lfsr64_clock(uint64_t *lfsr_in, uint32_t clocks)
{
uint64_t lfsr = *lfsr_in;
for(uint32_t clock = 0; clock < clocks; clock++)
{
/* maximum length LFSR according to http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf */
uint32_t bit = ((lfsr >> 63) ^ (lfsr >> 62) ^ (lfsr >> 60) ^ (lfsr >> 59)) & 1;
lfsr = (lfsr << 1) | bit;
}
*lfsr_in = lfsr;
}
void hash_password(char *password, uint64_t *hash_ret)
{
uint64_t hash = 0xDEADBEEFDEADBEEF;
/* use the password to generate an 128 bit key */
for(uint32_t pos = 0; pos < strlen((char *)password); pos++)
{
uint64_t mask = 0;
mask = password[pos];
mask |= mask << 8;
mask |= mask << 16;
mask |= mask << 32;
/* randomize random randomness with randomized random randomness */
iocrypt_lfsr64_clock(&mask, 8192 + pos * 11 + password[pos]);
hash ^= mask;
iocrypt_lfsr64_clock(&hash, 8192);
}
/* some final clocking */
iocrypt_lfsr64_clock(&hash, 8192);
trace_write(iocrypt_trace_ctx, "hash_password: '%s'", password);
trace_write(iocrypt_trace_ctx, "hash_password: 0x%08X%08X", (uint32_t)(hash>>32), (uint32_t)hash);
*hash_ret = hash;
return;
}
#ifndef __HASH_PASSWORD_H
#define __HASH_PASSWORD_H
void hash_password(char *password, uint64_t *hash);
#endif
\ No newline at end of file
......@@ -36,60 +36,13 @@ static IME_UPDATE_FUNC(iocrypt_ime_update)
return IME_OK;
}
static void iocrypt_lfsr64_clock(uint64_t *lfsr_in, uint32_t clocks)
{
uint64_t lfsr = *lfsr_in;
for(uint32_t clock = 0; clock < clocks; clock++)
{
/* maximum length LFSR according to http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf */
uint32_t bit = ((lfsr >> 63) ^ (lfsr >> 62) ^ (lfsr >> 60) ^ (lfsr >> 59)) & 1;
lfsr = (lfsr << 1) | bit;
}
*lfsr_in = lfsr;
}
static void set_password(char *password)
static IME_DONE_FUNC(iocrypt_ime_done)
{
uint64_t key = 0xDEADBEEFDEADBEEF;
/* use the password to generate an 128 bit key */
for(uint32_t pos = 0; pos < strlen((char *)password); pos++)
{
uint64_t mask = 0;
mask = password[pos];
mask |= mask << 8;
mask |= mask << 16;
mask |= mask << 32;
/* randomize random randomness with randomized random randomness */
iocrypt_lfsr64_clock(&mask, 8192 + pos * 11 + password[pos]);
key ^= mask;
iocrypt_lfsr64_clock(&key, 8192);
}
/* some final clocking */
iocrypt_lfsr64_clock(&key, 8192);
/* done, use that key */
iocrypt_key = key;
iocrypt_disabled = 0;
gui_stop_menu();
give_semaphore(iocrypt_password_sem);
trace_write(iocrypt_trace_ctx, "password: '%s'", password);
trace_write(iocrypt_trace_ctx, "password: 0x%08X%08X", iocrypt_key);
}
static IME_DONE_FUNC(iocrypt_ime_done)
{
/* if key input dialog was cancelled */
if(status != IME_OK)
{
gui_stop_menu();
iocrypt_disabled = 1;
NotifyBox(2000, "Crypto disabled");
beep();
......@@ -98,16 +51,43 @@ static IME_DONE_FUNC(iocrypt_ime_done)
return IME_OK;
}
set_password(text);
hash_password(text, &iocrypt_key);
/* done, use that key */
iocrypt_disabled = 0;
give_semaphore(iocrypt_password_sem);
#if 0
/* do some unaligned writes to check alignment handling */
uint8_t buffer[256];
memset(buffer, 0x00, sizeof(buffer));
FILE* f = FIO_CreateFileEx("B:/IO_CRYPT.CR2");
for(int loop = 0; loop < 10 * 1024; loop++)
{
FIO_WriteFile(f, &buffer[0], 19);
FIO_WriteFile(f, &buffer[1], 21);
FIO_WriteFile(f, &buffer[2], 33);
FIO_WriteFile(f, &buffer[3], 31);
FIO_WriteFile(f, &buffer[7], 3);
bmp_printf(FONT_LARGE, 0, 60, "Loop: %d", loop);
}
FIO_CloseFile(f);
beep();
#endif
return IME_OK;
}
static uint32_t iodev_GetPosition(uint32_t fd)
{
uint32_t *ctx = (uint32_t *)(iodev_ctx + iodev_ctx_size * fd);
return ctx[2];
}
/* these are the iodev hooks */
static uint32_t hook_iodev_CloseFile(uint32_t fd)
{
......@@ -208,7 +188,7 @@ static uint32_t hook_iodev_WriteFile(uint32_t fd, uint8_t *buf, uint32_t length)
ret = orig_iodev->WriteFile(fd, work_ptr, length);
trace_write(iocrypt_trace_ctx, "iodev_WriteFile post(0x%08X, 0x%08X) -> fd = %d, fd_pos = 0x%08X, %s", buf, length, fd, fd_pos, iocrypt_files[fd].filename);
trace_write(iocrypt_trace_ctx, "iodev_WriteFile post(0x%08X, 0x%08X) -> fd = %d, fd_pos = 0x%08X, fd_pos (now) = 0x%08X, %s", buf, length, fd, fd_pos, iodev_GetPosition(fd), iocrypt_files[fd].filename);
/* if we were not able to write it from scratch, undo in-place encryption */
if(work_ptr == buf)
......@@ -235,7 +215,7 @@ static void iocrypt_enter_pw()
gui_open_menu();
if(!ime_base_start("io_crypt: Enter password", iocrypt_ime_text, sizeof(iocrypt_ime_text), IME_UTF8, IME_CHARSET_ANY, &iocrypt_ime_update, &iocrypt_ime_done, 0, 0, 0, 0))
if(!ime_base_start("io_crypt: Enter password", iocrypt_ime_text, sizeof(iocrypt_ime_text) - 1, IME_UTF8, IME_CHARSET_ANY, &iocrypt_ime_update, &iocrypt_ime_done, 0, 0, 0, 0))
{
give_semaphore(iocrypt_password_sem);
iocrypt_disabled = 1;
......
......@@ -3,12 +3,11 @@
#define __IO_CRYPT_H
#define CRYPT_SCRATCH_SIZE 0x00800000
#define CRYPT_BLOCKSIZE 0x00010000
typedef struct crypt_cipher_t
{
void (*encrypt)(void *ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset);
void (*decrypt)(void *ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset);
void (*reset)(void **ctx);
void (*deinit)(void **ctx);
} crypt_cipher_t;
......
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include "io_crypt.h"
#include "crypt_lfsr64.h"
#include "hash_password.h"
#define BLOCKSIZE (8 * 1024)
int main(int argc, char *argv[])
{
if(argc != 4)
{
printf("Usage: '%s <infile> <outfile> <password>\n", argv[0]);
return -1;
}
char *in_filename = argv[1];
char *out_filename = argv[2];
char *password = argv[3];
/* hash the password */
uint64_t key = 0;
hash_password(password, &key);
/* setup cipher with that hash */
crypt_cipher_t *crypt_ctx;
crypt_lfsr64_init(&crypt_ctx, key);
/* open files */
FILE *in_file = fopen(in_filename, "rb");
if(!in_file)
{
printf("Could not open '%s'\n", in_filename);
return;
}
FILE *out_file = fopen(out_filename, "w");
if(!in_file)
{
printf("Could not open '%s'\n", out_filename);
return;
}
char *buffer = malloc(BLOCKSIZE);
uint32_t file_offset = 0;
while(!feof(in_file))
{
int ret = fread(buffer, 1, BLOCKSIZE, in_file);
if(ret > 0)
{
crypt_ctx->decrypt(crypt_ctx, buffer, buffer, ret, file_offset);
fwrite(buffer, 1, ret, out_file);
file_offset += ret;
}
}
fclose(in_file);
fclose(out_file);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment