Initial import of crypto.rc4 algorithm and modernize RCrypto API

This commit is contained in:
pancake 2016-03-07 02:38:50 +01:00
parent bbf8685b3a
commit 00ac90f71b
7 changed files with 214 additions and 77 deletions

View File

@ -1,7 +1,7 @@
BIN=rahash2
BINDEPS=r_io r_hash r_socket r_asm r_cons r_util
BINDEPS+=r_anal r_syscall r_reg r_db r_parse
BINDEPS+=r_flags r_lang
BINDEPS+=r_flags r_lang r_crypto
include ../rules.mk

View File

@ -1,54 +1,54 @@
/* radare - LGPL - Copyright 2009-2013 - pancake */
/* radare - LGPL - Copyright 2009-2016 - pancake */
#include "r_crypto.h"
#include "../config.h"
R_LIB_VERSION (r_crypto);
static struct r_crypto_plugin_t *crypto_static_plugins[] =
{ R_CRYPTO_STATIC_PLUGINS };
static RCryptoPlugin *crypto_static_plugins[] = {
R_CRYPTO_STATIC_PLUGINS
};
R_API struct r_crypto_t *r_crypto_init(struct r_crypto_t *cry, int hard) {
R_API RCrypto *r_crypto_init(RCrypto *cry, int hard) {
RCryptoPlugin *p;
int i;
RCryptoPlugin *static_plugin;
if (cry) {
cry->key = NULL;
cry->iv = NULL;
cry->key = NULL;
cry->key_len = 0;
cry->user = NULL;
if (hard) {
// first call initializes the output_* variables
r_crypto_get_output(cry);
INIT_LIST_HEAD(&cry->plugins);
for(i=0;crypto_static_plugins[i];i++) {
static_plugin = R_NEW (RCryptoPlugin);
memcpy (static_plugin, crypto_static_plugins[i], sizeof (RCryptoPlugin));
r_crypto_add(cry, static_plugin);
r_crypto_get_output (cry, NULL);
cry->plugins = r_list_newf (NULL);
for (i=0; crypto_static_plugins[i]; i++) {
p = R_NEW0 (RCryptoPlugin);
memcpy (p, crypto_static_plugins[i], sizeof (RCryptoPlugin));
r_crypto_add (cry, p);
}
}
}
return cry;
}
R_API int r_crypto_add(RCrypto *cry, struct r_crypto_plugin_t *h) {
R_API int r_crypto_add(RCrypto *cry, RCryptoPlugin *h) {
// add a check ?
list_add_tail(&(h->list), &(cry->plugins));
r_list_append (cry->plugins, h);
return true;
}
R_API int r_crypto_del(RCrypto *cry, struct r_crypto_plugin_t *h) {
list_del(&(h->list));
R_API int r_crypto_del(RCrypto *cry, RCryptoPlugin *h) {
r_list_delete_data (cry->plugins, h);
return true;
}
R_API struct r_crypto_t *r_crypto_new() {
RCrypto *cry = R_NEW(RCrypto);
RCrypto *cry = R_NEW0 (RCrypto);
return r_crypto_init (cry, true);
}
R_API struct r_crypto_t *r_crypto_as_new(struct r_crypto_t *cry) {
RCrypto *c = R_NEW(RCrypto);
RCrypto *c = R_NEW0 (RCrypto);
if (c != NULL) {
r_crypto_init (c, false); // soft init
memcpy (&c->plugins, &cry->plugins, sizeof (cry->plugins));
@ -58,84 +58,82 @@ R_API struct r_crypto_t *r_crypto_as_new(struct r_crypto_t *cry) {
R_API struct r_crypto_t *r_crypto_free(RCrypto *cry) {
// TODO: call the destructor function of the plugin to destory the *user pointer if needed
// TODO: free plugins
free(cry->output);
free(cry->key);
free(cry->iv);
free(cry);
r_list_free (cry->plugins);
free (cry->output);
free (cry->key);
free (cry->iv);
free (cry);
return NULL;
}
R_API int r_crypto_use(RCrypto *cry, const char *algo) {
int ret = false;
struct list_head *pos;
list_for_each_prev(pos, &cry->plugins) {
struct r_crypto_plugin_t *h = list_entry(pos, struct r_crypto_plugin_t, list);
if (h->use(algo)) {
R_API bool r_crypto_use(RCrypto *cry, const char *algo) {
RListIter *iter;
RCryptoPlugin *h;
r_list_foreach (cry->plugins, iter, h) {
if (h->use (algo)) {
cry->h = h;
cry->key_len = h->get_key_size(cry);
cry->key = malloc(cry->key_len);
break;
cry->key_len = h->get_key_size (cry);
cry->key = calloc (1, cry->key_len);
return cry->key != NULL;
}
}
return ret;
return false;
}
R_API int r_crypto_set_key(RCrypto *cry, const ut8* key, int mode, int direction) {
int ret = false;
if (cry->h && cry->h->set_key)
ret = cry->h->set_key(cry, key, mode, direction);
return ret;
R_API int r_crypto_set_key(RCrypto *cry, const ut8* key, int keylen, int mode, int direction) {
if (keylen < 0)
keylen = strlen ((const char *)key);
return (cry && cry->h && cry->h->set_key)?
cry->h->set_key (cry, key, keylen, mode, direction): false;
}
R_API int r_crypto_get_key_size(RCrypto *cry) {
int ret = 0;
if (cry->h && cry->h->get_key_size)
ret = cry->h->get_key_size(cry);
return ret;
return (cry && cry->h && cry->h->get_key_size)?
cry->h->get_key_size (cry): 0;
}
R_API int r_crypto_set_iv(RCrypto *cry, const ut8 *iv) {
int ret = false;
if (cry->h && cry->h->set_iv)
ret = cry->h->set_iv(cry, iv);
return ret;
return (cry && cry->h && cry->h->set_iv)?
cry->h->set_iv(cry, iv): 0;
}
// return the number of bytes written in the output buffer
R_API int r_crypto_update(RCrypto *cry, ut8 *buf, int len) {
int olen = 0; // length of output bytes
if (cry->h && cry->h->update)
olen = cry->h->update(cry, buf, len);
return olen;
return (cry && cry->h && cry->h->update)?
cry->h->update (cry, buf, len): 0;
}
R_API int r_crypto_final(RCrypto *cry, ut8 *buf, int len) {
// TODO: same as update()
int olen = 0; // length of output bytes
if (cry->h && cry->h->final)
olen = cry->h->final(cry, buf, len);
return olen;
return (cry && cry->h && cry->h->final)?
cry->h->final (cry, buf, len): 0;
}
// append data to the output buffer
// TODO: internal api?? used from plugins?
// TODO: internal api?? used from plugins? TODO: use r_buf here
R_API int r_crypto_append(RCrypto *cry, const ut8 *buf, int len) {
if (!cry || !buf) {
return -1;
}
if (cry->output_len+len > cry->output_size) {
cry->output_size += 4096 + len;
cry->output = realloc(cry->output, cry->output_size);
cry->output = realloc (cry->output, cry->output_size);
}
memcpy(cry->output + cry->output_len, buf, len);
cry->output_len += len;
return cry->output_len;
}
// NOTE: Passes ownership of buffer, coz other is freed
R_API ut8 *r_crypto_get_output(RCrypto *cry) {
ut8 *buf = cry->output;
// free the buffer
cry->output_size = 4096;
cry->output = malloc(4096);
cry->output_len = 0;
R_API ut8 *r_crypto_get_output(RCrypto *cry, int *size) {
ut8 *buf = calloc (1, cry->output_size);
if (!buf) return NULL;
if (size) {
*size = cry->output_len;
memcpy (buf, cry->output, *size);
} else {
/* initialize */
cry->output = buf;
cry->output_len = 0;
cry->output_size = 4096;
return NULL;
}
return buf;
}

View File

@ -3,7 +3,7 @@
#include <r_crypto.h>
struct r_crypto_plugin_t r_crypto_plugin_aes = {
.name = "crypto_aes",
.name = "aes",
/* TODO */
};

130
libr/crypto/p/crypto_rc4.c Normal file
View File

@ -0,0 +1,130 @@
/* radare - LGPL - Copyright 2016 - pancake */
#include <r_lib.h>
#include <r_crypto.h>
struct rc4_state {
ut8 perm[256];
ut8 index1;
ut8 index2;
int key_size;
};
static __inline void swap_bytes(ut8 *a, ut8 *b) {
if (a != b) {
ut8 temp = *a;
*a = *b;
*b = temp;
}
}
/*
* Initialize an RC4 state buffer using the supplied key,
* which can have arbitrary length.
*/
static void rc4_init(struct rc4_state *const state, const ut8 *key, int keylen) {
ut8 j;
int i;
state->key_size = keylen;
/* Initialize state with identity permutation */
for (i = 0; i < 256; i++)
state->perm[i] = (ut8)i;
state->index1 = 0;
state->index2 = 0;
/* Randomize the permutation using key data */
for (j = i = 0; i < 256; i++) {
j += state->perm[i] + key[i % keylen];
swap_bytes (&state->perm[i], &state->perm[j]);
}
}
/*
* Encrypt some data using the supplied RC4 state buffer.
* The input and output buffers may be the same buffer.
* Since RC4 is a stream cypher, this function is used
* for both encryption and decryption.
*/
static void rc4_crypt(struct rc4_state *const state, const ut8 *inbuf, ut8 *outbuf, int buflen) {
int i;
ut8 j;
for (i = 0; i < buflen; i++) {
/* Update modification indicies */
state->index1++;
state->index2 += state->perm[state->index1];
/* Modify permutation */
swap_bytes (&state->perm[state->index1],
&state->perm[state->index2]);
/* Encrypt/decrypt next byte */
j = state->perm[state->index1] + state->perm[state->index2];
outbuf[i] = inbuf[i] ^ state->perm[j];
}
}
///////////////////////////////////////////////////////////
static struct rc4_state st;
static int rc4_set_key(RCrypto *cry, const ut8 *key, int keylen, int mode, int direction) {
rc4_init (&st, key, keylen);
return true;
}
static int rc4_get_key_size(RCrypto *cry) {
return st.key_size;
}
static bool rc4_use(const char *algo) {
return !strcmp (algo, "rc4");
}
static int update(RCrypto *cry, const ut8 *buf, int len) {
ut8 *obuf = calloc (1, len);
if (!obuf) return false;
rc4_crypt (&st, buf, obuf, len);
r_crypto_append (cry, obuf, len);
free (obuf);
return 0;
}
static int final(RCrypto *cry, const ut8 *buf, int len) {
return update (cry, buf, len);
}
RCryptoPlugin r_crypto_plugin_rc4 = {
.name = "rc4",
.set_key = rc4_set_key,
.get_key_size = rc4_get_key_size,
.use = rc4_use,
.update = update,
.final = final
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_CRYPTO,
.data = &r_crypto_plugin_rc4,
.version = R2_VERSION
};
#endif
#if 0
int main() {
ut8 out[32];
struct rc4_state st;
/* encrypt */
rc4_init (&st, (const ut8*)"key", 3);
rc4_crypt(&st, (const ut8*)"hello world", out, sizeof (out));
/* decrypt */
rc4_init (&st, (const ut8*)"key", 3);
rc4_crypt(&st, out, out, sizeof (out));
eprintf ("%s\n", (const char *)out); // must print "hello world"
}
#endif

9
libr/crypto/p/rc4.mk Normal file
View File

@ -0,0 +1,9 @@
OBJ_RC4=crypto_rc4.o
STATIC_OBJ+=${OBJ_RC4}
TARGET_RC4=crypto_rc4.${EXT_SO}
ALL_TARGETS+=${TARGET_RC4}
${TARGET_RC4}: ${OBJ_RC4}
${CC} $(call libname,crypto_rc4) ${LDFLAGS} ${CFLAGS} -o ${TARGET_RC4} ${OBJ_RC4}

View File

@ -1,8 +1,8 @@
#ifndef R2_CRYPTO_H
#define R2_CRYPTO_H
#include <list.h>
#include <r_types.h>
#include <r_list.h>
#ifdef __cplusplus
extern "C" {
@ -31,19 +31,18 @@ typedef struct r_crypto_t {
int output_len;
int output_size;
void *user;
struct list_head plugins;
RList *plugins;
} RCrypto;
typedef struct r_crypto_plugin_t {
const char *name;
int (*get_key_size)(RCrypto *cry);
int (*set_iv)(RCrypto *cry, const ut8 *iv);
int (*set_key)(RCrypto *cry, const ut8 *key, int mode, int direction);
int (*set_key)(RCrypto *cry, const ut8 *key, int keylen, int mode, int direction);
int (*update)(RCrypto *cry, const ut8 *buf, int len);
int (*final)(RCrypto *cry, const ut8 *buf, int len);
int (*use)(const char *algo);
bool (*use)(const char *algo);
int (*fini)(RCrypto *cry);
struct list_head list;
} RCryptoPlugin;
#ifdef R_API
@ -52,18 +51,18 @@ R_API RCrypto *r_crypto_as_new(RCrypto *cry);
R_API int r_crypto_add(RCrypto *cry, RCryptoPlugin *h);
R_API RCrypto *r_crypto_new(void);
R_API RCrypto *r_crypto_free(RCrypto *cry);
R_API int r_crypto_use(RCrypto *cry, const char *algo);
R_API int r_crypto_set_key(RCrypto *cry, const ut8* key, int mode, int direction);
R_API int r_crypto_get_key_size(RCrypto *cry);
R_API bool r_crypto_use(RCrypto *cry, const char *algo);
R_API int r_crypto_set_key(RCrypto *cry, const ut8* key, int keylen, int mode, int direction);
R_API int r_crypto_set_iv(RCrypto *cry, const ut8 *iv);
R_API int r_crypto_update(RCrypto *cry, ut8 *buf, int len);
R_API int r_crypto_final(RCrypto *cry, ut8 *buf, int len);
R_API int r_crypto_append(RCrypto *cry, const ut8 *buf, int len);
R_API ut8 *r_crypto_get_output(RCrypto *cry);
R_API ut8 *r_crypto_get_output(RCrypto *cry, int *size);
#endif
/* plugin pointers */
extern RCryptoPlugin r_crypto_plugin_aes;
extern RCryptoPlugin r_crypto_plugin_rc4;
#ifdef __cplusplus
}

View File

@ -149,6 +149,7 @@ bp.x86
core.anal
core.java
crypto.aes
crypto.rc4
debug.bf
debug.esil
debug.gdb