Commit bd21986e authored by g3gg0's avatar g3gg0
Browse files

io_crypt: added RSA for passwordless encryption, updated menu, decryption working for all modes

--HG--
branch : unified
parent 8066b98215a1
......@@ -13,13 +13,21 @@
#include <stdlib.h>
#include <stdint.h>
#define trace_write(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define trace_write(x,...) do { 0; } while (0)
//#define trace_write(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#endif
#include "io_crypt.h"
#include "crypt_lfsr64.h"
/* when write speed is about 70MiB/s unencrypted:
blocksize 0x00002000: 2MiB/s
blocksize 0x00010000: 5MiB/s
blocksize 0x00020000: 20MiB/s
the larger the block size is, the easier it is to reconstruct the current block key
*/
static uint32_t crypt_lfsr64_blocksize = 0x00020000;
extern uint32_t iocrypt_trace_ctx;
......@@ -58,7 +66,7 @@ static void crypt_lfsr64_xor_uint64(void *dst_in, void *src_in, lfsr64_ctx_t *ct
static void update_key(lfsr64_ctx_t *ctx, uint32_t offset, uint32_t force)
{
/* update the current encryption key whever reaching the next block */
uint32_t block = offset / CRYPT_LFSR64_BLOCKSIZE;
uint32_t block = offset / crypt_lfsr64_blocksize;
if(!force)
{
......@@ -94,7 +102,7 @@ static void update_key(lfsr64_ctx_t *ctx, uint32_t offset, uint32_t force)
/* build an array with key elements for every offset in uint64_t mode */
for(int pos = 0; pos < 8; pos++)
{
uint32_t elem_addr = &ctx->key_uint64[pos];
uint32_t elem_addr = (uint32_t)&ctx->key_uint64[pos];
memcpy((void*)elem_addr, &ctx->key_uint8[pos], 8 - pos);
memcpy((void*)elem_addr + (8-pos), ctx->key_uint8, pos);
......@@ -102,9 +110,9 @@ static void update_key(lfsr64_ctx_t *ctx, uint32_t offset, uint32_t force)
}
#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)
static uint32_t crypt_lfsr64_encrypt(crypt_cipher_t *cipher_ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
{
lfsr64_ctx_t *ctx = (lfsr64_ctx_t *)ctx_in;
lfsr64_ctx_t *ctx = cipher_ctx->priv;
/* initial key creation */
update_key(ctx, offset, 0);
......@@ -113,7 +121,7 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
//trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint8 offset 0x%08X, length 0x%08X", offset, length);
while((IS_UNALIGNED(8) || (offset % 8)) && (length > 0))
{
uint32_t block_remain = offset % CRYPT_LFSR64_BLOCKSIZE;
uint32_t block_remain = offset % crypt_lfsr64_blocksize;
if(block_remain == 0)
{
......@@ -133,7 +141,7 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
/* processing loop for 64 bit writes and even file offsets */
while(length >= 8 && ((offset % 8) == 0))
{
if((offset % CRYPT_LFSR64_BLOCKSIZE) == 0)
if((offset % crypt_lfsr64_blocksize) == 0)
{
update_key(ctx, offset, 0);
}
......@@ -148,7 +156,7 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
/* processing loop for 64 bit writes and odd file offsets */
while(length >= 8)
{
uint32_t block_remain = offset % CRYPT_LFSR64_BLOCKSIZE;
uint32_t block_remain = offset % crypt_lfsr64_blocksize;
if(block_remain == 0)
{
......@@ -171,7 +179,7 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
//trace_write(iocrypt_trace_ctx, "crypt_lfsr64_xor_uint8 offset 0x%08X, length 0x%08X", offset, length);
while(length > 0)
{
uint32_t block_remain = offset % CRYPT_LFSR64_BLOCKSIZE;
uint32_t block_remain = offset % crypt_lfsr64_blocksize;
if(block_remain == 0)
{
......@@ -189,22 +197,27 @@ static void crypt_lfsr64_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint3
#undef IS_UNALIGNED
/* using a symmetric cipher, both encryption and decryption are the same */
static void crypt_lfsr64_decrypt(void *ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
static uint32_t crypt_lfsr64_decrypt(crypt_cipher_t *ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
{
crypt_lfsr64_encrypt(ctx, dst, src, length, offset);
return crypt_lfsr64_encrypt(ctx, dst, src, length, offset);
}
static void crypt_lfsr64_deinit(void **crypt_ctx)
static void crypt_lfsr64_set_blocksize(crypt_cipher_t *crypt_ctx, uint32_t size)
{
if(*crypt_ctx)
crypt_lfsr64_blocksize = size;
}
static void crypt_lfsr64_deinit(crypt_cipher_t *crypt_ctx)
{
if(crypt_ctx && crypt_ctx->priv)
{
free(*crypt_ctx);
*crypt_ctx = NULL;
free(crypt_ctx->priv);
crypt_ctx->priv = NULL;
}
}
/* allocate and initialize an LFSR64 cipher ctx and save to pointer */
void crypt_lfsr64_init(void **crypt_ctx, uint64_t password)
void crypt_lfsr64_init(crypt_cipher_t *crypt_ctx, uint64_t password)
{
lfsr64_ctx_t *ctx = malloc(sizeof(lfsr64_ctx_t));
......@@ -215,9 +228,12 @@ void crypt_lfsr64_init(void **crypt_ctx, uint64_t password)
}
/* setup cipher ctx */
ctx->cipher.encrypt = &crypt_lfsr64_encrypt;
ctx->cipher.decrypt = &crypt_lfsr64_decrypt;
ctx->cipher.deinit = &crypt_lfsr64_deinit;
crypt_ctx->encrypt = &crypt_lfsr64_encrypt;
crypt_ctx->decrypt = &crypt_lfsr64_decrypt;
crypt_ctx->deinit = &crypt_lfsr64_deinit;
crypt_ctx->set_blocksize = &crypt_lfsr64_set_blocksize;
crypt_ctx->priv = ctx;
ctx->password = password;
ctx->current_block = 0xFFFFFFFF;
ctx->lfsr_state = 0;
......@@ -225,7 +241,6 @@ void crypt_lfsr64_init(void **crypt_ctx, uint64_t password)
/* setup initial cipher key */
update_key(ctx, 0, 1);
*crypt_ctx = ctx;
trace_write(iocrypt_trace_ctx, "crypt_lfsr64_init: initialized");
}
......
#ifndef __CRYPT_LFSR_H
#define __CRYPT_LFSR_H
/* when write speed is about 70MiB/s unencrypted:
blocksize 0x00002000: 2MiB/s
blocksize 0x00010000: 5MiB/s
blocksize 0x00020000: 20MiB/s
the larger the block size is, the easier it is to reconstruct the current block key
*/
#define CRYPT_LFSR64_BLOCKSIZE 0x00020000
typedef struct
{
crypt_cipher_t cipher;
uint64_t lfsr_state;
uint8_t key_uint8[8];
uint64_t key_uint64[8];
......@@ -19,6 +11,6 @@ typedef struct
uint32_t current_block;
} lfsr64_ctx_t;
void crypt_lfsr64_init(void **crypt_ctx, uint64_t password);
void crypt_lfsr64_init(crypt_cipher_t *crypt_ctx, uint64_t password);
#endif
......@@ -6,7 +6,9 @@
#include <property.h>
#include <bmp.h>
#include <menu.h>
#define TRACE_DISABLED
#include <string.h>
//#define TRACE_DISABLED
#include "../trace/trace.h"
#else
......@@ -14,14 +16,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define trace_write(x,...) do { 0; } while (0)
//#define trace_write(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define trace_write(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define NotifyBox(x,...) do { printf(__VA_ARGS__); printf("\n"); } while (0)
#define NotifyBoxHide() do { } while(0)
#define beep() do { } while(0)
#define beep_times(x) do { } while(0)
#define msleep(x) usleep((x)*1000)
#define task_create(a,b,c,d,e) do { d(e); } while(0)
#define FIO_CreateFileEx(file) fopen(file, "w+")
#define FIO_WriteFile(f,data,len) fwrite(data, 1, len, f)
#define FIO_ReadFile(f,data,len) fread(data, 1, len, f)
#define FIO_CloseFile(x) fclose(f)
#define FIO_Open(file,mode) fopen(file, "r")
#define FIO_GetFileSize(f,ret) getFileSize(f,ret)
#define INVALID_PTR 0
#define O_RDONLY 0
#define O_SYNC 0
size_t getFileSize(const char * filename, int *ret)
{
struct stat st;
stat(filename, &st);
*ret = st.st_size;
return 0;
}
#endif
#include <rand.h>
......@@ -32,10 +60,11 @@
#include "bigd.h"
#include "bigdigits.h"
#define assert(x) do {} while(0)
static uint32_t crypt_rsa_keysize = 1024;
extern uint32_t iocrypt_trace_ctx;
#define assert(x) do {} while(0)
static bdigit_t small_primes[] = {
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
......@@ -59,7 +88,7 @@ static bdigit_t small_primes[] = {
#define N_SMALL_PRIMES (sizeof(small_primes)/sizeof(bdigit_t))
static int my_rand(unsigned char *bytes, size_t nbytes, const unsigned char *seed, size_t seedlen)
static int crypt_rsa_rand(unsigned char *bytes, size_t nbytes, const unsigned char *seed, size_t seedlen)
{
if(0 && seed)
{
......@@ -80,9 +109,9 @@ static int my_rand(unsigned char *bytes, size_t nbytes, const unsigned char *see
uint32_t words = (nbytes / 4);
uint32_t remain = (nbytes % 4);
rand_fill(bytes, words);
rand_fill((uint32_t*)bytes, words);
for(int pos = 0; pos < remain; pos++)
for(uint32_t pos = 0; pos < remain; pos++)
{
uint32_t rn = 0;
rand_fill(&rn, 1);
......@@ -93,7 +122,6 @@ static int my_rand(unsigned char *bytes, size_t nbytes, const unsigned char *see
}
int generateRSAPrime(BIGD p, size_t nbits, bdigit_t e, size_t ntests,
unsigned char *seed, size_t seedlen, BD_RANDFUNC randFunc)
/* Create a prime p such that gcd(p-1, e) = 1.
......@@ -299,10 +327,9 @@ int crypt_rsa_generate(int nbits, t_crypt_key *priv_key, t_crypt_key *pub_key)
qInv = bdNew();
/* Create RSA key pair (n, e),(d, p, q, dP, dQ, qInv) */
/* NB we use simple my_rand() here -- you should use a proper cryptographically-secure RNG */
res = generateRSAKey(n, e, d, p, q, dP, dQ, qInv, nbits+1, 3, 50, NULL, 0, my_rand);
res = generateRSAKey(n, e, d, p, q, dP, dQ, qInv, nbits+1, 3, 50, NULL, 0, crypt_rsa_rand);
if (res != 0)
if(res != 0)
{
NotifyBox(5000, "Failed to generate RSA key!\n");
goto clean_up;
......@@ -310,50 +337,50 @@ int crypt_rsa_generate(int nbits, t_crypt_key *priv_key, t_crypt_key *pub_key)
priv_key->id = 0x00;
pub_key->id = 0x00;
priv_key->name = strdup ( "new key" );
pub_key->name = strdup ( "new key" );
priv_key->name = strdup("new key");
pub_key->name = strdup("new key");
size_t nchars = bdConvToHex(n, NULL, 0);
buffer = malloc(nchars+1);
nchars = bdConvToHex(n, buffer, nchars+1);
priv_key->primefac = (char*)strdup ( (char *)buffer );
pub_key->primefac = (char*)strdup ( (char *)buffer );
free ( buffer );
priv_key->primefac = (char*)strdup((char *)buffer);
pub_key->primefac = (char*)strdup((char *)buffer);
free(buffer);
nchars = bdConvToHex(d, NULL, 0);
buffer = malloc(nchars+1);
nchars = bdConvToHex(d, buffer, nchars+1);
priv_key->key = (char*)strdup ( (char *)buffer );
free ( buffer );
priv_key->key = (char*)strdup((char *)buffer);
free(buffer);
nchars = bdConvToHex(e, NULL, 0);
buffer = malloc(nchars+1);
nchars = bdConvToHex(e, buffer, nchars+1);
pub_key->key = (char*)strdup ( (char *)buffer );
free ( buffer );
pub_key->key = (char*)strdup((char *)buffer);
free(buffer);
bdConvFromHex ( d, priv_key->key );
bdConvFromHex ( e, pub_key->key );
bdConvFromHex ( n, pub_key->primefac );
bdConvFromHex(d, priv_key->key);
bdConvFromHex(e, pub_key->key);
bdConvFromHex(n, pub_key->primefac);
source = bdNew ();
result = bdNew ();
tmp_buf = (unsigned char*)malloc ( nbits*8*4 );
strcpy ( (char*)tmp_buf, "Test" );
strcpy((char*)tmp_buf, "Test");
bdConvFromOctets ( source, tmp_buf, 8 );
bdConvFromOctets( source, tmp_buf, 8);
bdModExp(result, source, d, n);
bdConvToOctets ( result, tmp_buf, bdSizeof(result)*4 );
bdConvFromOctets ( result, tmp_buf, bdSizeof(result)*4 );
bdConvToOctets(result, tmp_buf, bdSizeof(result)*4);
bdConvFromOctets(result, tmp_buf, bdSizeof(result)*4);
bdModExp(source, result, e, n);
bdConvToOctets ( source, tmp_buf, bdSizeof(source)*4 );
if ( strcmp ( (char*)"Test", (char*)tmp_buf ) )
bdConvToOctets(source, tmp_buf, bdSizeof(source)*4);
if(strcmp((char*)"Test", (char*)tmp_buf))
{
printf ( "Key check FAILED!!\n" );
beep();
......@@ -375,7 +402,7 @@ clean_up:
}
unsigned int crypt_rsa_crypt ( unsigned char *data, int length, t_crypt_key *key )
unsigned int crypt_rsa_crypt(uint8_t *dst, uint8_t *src, int length, t_crypt_key *key)
{
BIGD keyval;
BIGD primefac;
......@@ -388,29 +415,133 @@ unsigned int crypt_rsa_crypt ( unsigned char *data, int length, t_crypt_key *key
buffer = bdNew();
result = bdNew();
bdConvFromHex ( keyval, key->key );
bdConvFromHex ( primefac, key->primefac );
bdConvFromOctets ( buffer, data, length );
bdConvFromHex(keyval, key->key);
bdConvFromHex(primefac, key->primefac);
bdConvFromOctets(buffer, src, length);
bdModExp ( result, buffer, keyval, primefac );
bdModExp(result, buffer, keyval, primefac);
bytes = bdSizeof (result)*4;
bdConvToOctets ( result, data, bytes );
bdConvToOctets(result, dst, bytes);
bdFree ( &keyval );
bdFree ( &primefac );
bdFree ( &buffer );
bdFree ( &result );
bdFree(&keyval);
bdFree(&primefac);
bdFree(&buffer);
bdFree(&result);
return bytes;
}
static void crypt_rsa_encrypt(void *ctx_in, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
t_crypt_key *crypt_rsa_get_priv(crypt_cipher_t *crypt_ctx)
{
if(!crypt_ctx || !crypt_ctx->priv)
{
return NULL;
}
rsa_ctx_t *ctx = (rsa_ctx_t *)crypt_ctx->priv;
if(!strlen(ctx->priv_key.name))
{
return NULL;
}
return &ctx->priv_key;
}
static void crypt_rsa_decrypt(void *ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
t_crypt_key *crypt_rsa_get_pub(crypt_cipher_t *crypt_ctx)
{
if(!crypt_ctx || !crypt_ctx->priv)
{
return NULL;
}
rsa_ctx_t *ctx = (rsa_ctx_t *)crypt_ctx->priv;
if(!strlen(ctx->pub_key.name))
{
return NULL;
}
return &ctx->pub_key;
}
/* returns the key size in bits */
uint32_t crypt_rsa_get_keysize(crypt_cipher_t *crypt_ctx)
{
if(!crypt_ctx || !crypt_ctx->priv)
{
return 0;
}
rsa_ctx_t *ctx = (rsa_ctx_t *)crypt_ctx->priv;
int nibbles = strlen(ctx->pub_key.primefac);
return nibbles * 4;
}
void crypt_rsa_set_keysize(uint32_t size)
{
crypt_rsa_keysize = size;
}
void crypt_rsa_clear_key(t_crypt_key *key)
{
key->name = "";
key->primefac = "";
key->key = "";
}
/* returns the key size in bits */
uint32_t crypt_rsa_blocksize(crypt_cipher_t *crypt_ctx)
{
uint32_t keysize = crypt_rsa_get_keysize(crypt_ctx);
if(!keysize)
{
return 0;
}
return (keysize / 8);
}
static uint32_t crypt_rsa_encrypt(crypt_cipher_t *crypt_ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
{
if(!crypt_ctx || !crypt_ctx->priv)
{
return 0;
}
rsa_ctx_t *ctx = (rsa_ctx_t *)crypt_ctx->priv;
if(crypt_rsa_blocksize(crypt_ctx) > length)
{
trace_write(iocrypt_trace_ctx, "crypt_rsa_decrypt: key size mismatch %d vs. %d", crypt_rsa_blocksize(crypt_ctx), length);
return 0;
}
uint32_t new_len = crypt_rsa_crypt(dst, src, length, &ctx->pub_key);
return new_len;
}
static uint32_t crypt_rsa_decrypt(crypt_cipher_t *crypt_ctx, uint8_t *dst, uint8_t *src, uint32_t length, uint32_t offset)
{
if(!crypt_ctx || !crypt_ctx->priv)
{
return 0;
}
rsa_ctx_t *ctx = (rsa_ctx_t *)crypt_ctx->priv;
if(crypt_rsa_blocksize(crypt_ctx) > length)
{
trace_write(iocrypt_trace_ctx, "crypt_rsa_decrypt: key size mismatch %d vs. %d", crypt_rsa_blocksize(crypt_ctx), length);
return 0;
}
uint32_t new_len = crypt_rsa_crypt(dst, src, length, &ctx->priv_key);
return new_len;
}
static void crypt_rsa_deinit(void **crypt_ctx)
......@@ -422,6 +553,105 @@ static void crypt_rsa_deinit(void **crypt_ctx)
}
}
static uint32_t crypt_rsa_save(char *filename, t_crypt_key *key)
{
FILE* f = FIO_CreateFileEx(filename);
if(f == INVALID_PTR)
{
return 0;
}
FIO_WriteFile(f, key->primefac, strlen(key->primefac));
FIO_WriteFile(f, "\n", 1);
FIO_WriteFile(f, key->key, strlen(key->key));
FIO_WriteFile(f, "\n", 1);
FIO_CloseFile(f);
return 1;
}
uint32_t crypt_rsa_load(char *filename, t_crypt_key *key)
{
uint32_t size = 0;
if(FIO_GetFileSize(filename, &size))
{
trace_write(iocrypt_trace_ctx, "io_crypt: crypt_rsa_load: file not found: '%s'", filename);
return 0;
}
FILE* f = FIO_Open(filename, O_RDONLY | O_SYNC);
if(f == INVALID_PTR)
{
return 0;
}
char *buffer = malloc(size);
if(FIO_ReadFile(f, buffer, size) != (int)size)
{
trace_write(iocrypt_trace_ctx, "io_crypt: crypt_rsa_load: FIO_ReadFile failed");
free(buffer);
return 0;
}
char *sep = strchr(buffer, '\n');
if(!sep)
{
trace_write(iocrypt_trace_ctx, "io_crypt: crypt_rsa_load: invalid file format");
free(buffer);
return 0;
}
/* split strings */
*sep = '\000';
sep++;
/* remove termination */
char *sep2 = strchr(sep, '\n');
if(sep2)
{
*sep2 = '\000';
}
/* now fill key */
key->name = strdup(filename);
key->primefac = strdup(buffer);
key->key = strdup(sep);
free(buffer);
FIO_CloseFile(f);
return 1;
}
void crypt_rsa_generate_keys(crypt_cipher_t *crypt_ctx)
{
t_crypt_key priv_key;
t_crypt_key pub_key;
NotifyBox(60000, "Creating RSA key (%d bits)\nthis may take a while", crypt_rsa_keysize);
trace_write(iocrypt_trace_ctx, "io_crypt: crypt_rsa_generate %d...", crypt_rsa_keysize);
crypt_rsa_generate(crypt_rsa_keysize, &priv_key, &pub_key);
trace_write(iocrypt_trace_ctx, "io_crypt: crypt_rsa_generate %d done", crypt_rsa_keysize);
NotifyBoxHide();
beep();
NotifyBox(2000, "RSA key generated!");
crypt_rsa_save("ML/DATA/io_crypt.key", &priv_key);
crypt_rsa_save("ML/DATA/io_crypt.pub", &pub_key);
/* now reload to make sure all is file */
rsa_ctx_t *ctx = (rsa_ctx_t *)crypt_ctx->priv;
crypt_rsa_clear_key(&ctx->pub_key);
crypt_rsa_clear_key(&ctx->priv_key);
crypt_rsa_load("ML/DATA/io_crypt.pub", &ctx->pub_key);
crypt_rsa_load("ML/DATA/io_crypt.key", &ctx->priv_key);
}
static uint32_t crypt_rsa_testfunc(int size, t_crypt_key *priv_key, t_crypt_key *pub_key)
{
uint32_t ret = 0;
......@@ -451,9 +681,9 @@ static uint32_t crypt_rsa_testfunc(int size, t_crypt_key *priv_key, t_crypt_key
trace_write(iocrypt_trace_ctx, "Encryption test:");
trace_write(iocrypt_trace_ctx, " pre-crypt: 0x%08X%08X%08X%08X (%d bytes)", data[3], data[2], data[1], data[0], size_bytes);
uint32_t new_len = crypt_rsa_crypt(data, size / 8, pub_key);
uint32_t new_len = crypt_rsa_crypt((uint8_t*)data, (uint8_t*)data, size / 8, pub_key);
trace_write(iocrypt_trace_ctx, " post-crypt: 0x%08X%08X%08X%08X (%d bytes)", data[3], data[2], data[1], data[0], new_len);