mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-28 15:41:38 +00:00
Initial import of crypto.rc4 algorithm and modernize RCrypto API
This commit is contained in:
parent
bbf8685b3a
commit
00ac90f71b
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
130
libr/crypto/p/crypto_rc4.c
Normal 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
9
libr/crypto/p/rc4.mk
Normal 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}
|
@ -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
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ bp.x86
|
||||
core.anal
|
||||
core.java
|
||||
crypto.aes
|
||||
crypto.rc4
|
||||
debug.bf
|
||||
debug.esil
|
||||
debug.gdb
|
||||
|
Loading…
Reference in New Issue
Block a user