From 3019bb477c39f0ed76a9d570c1fb6f9160b90c65 Mon Sep 17 00:00:00 2001 From: Rakholiya Jenish Date: Sat, 7 May 2016 16:01:13 +0530 Subject: [PATCH] Add support for punycode via woE and woD and rahash2 Also add aes-cbc support by getting IV from user --- binr/rahash2/rahash2.c | 4 +- libr/core/cmd_write.c | 31 ++++- libr/crypto/Jamroot | 2 +- libr/crypto/p/crypto_punycode.c | 52 ++++++++ libr/crypto/p/punycode.mk | 9 ++ libr/include/r_crypto.h | 1 + libr/include/r_util.h | 3 + libr/util/Makefile | 2 +- libr/util/punycode.c | 229 ++++++++++++++++++++++++++++++++ plugins.def.cfg | 1 + 10 files changed, 324 insertions(+), 10 deletions(-) create mode 100644 libr/crypto/p/crypto_punycode.c create mode 100644 libr/crypto/p/punycode.mk create mode 100644 libr/util/punycode.c diff --git a/binr/rahash2/rahash2.c b/binr/rahash2/rahash2.c index 8691947672..8774f00916 100644 --- a/binr/rahash2/rahash2.c +++ b/binr/rahash2/rahash2.c @@ -291,7 +291,7 @@ int is_power_of_two(const ut64 x) { //direction: 0 => encrypt, 1 => decrypt int encrypt_or_decrypt(const char *algo, int direction, const char *hashstr, int hashstr_len, const ut8 *iv, int ivlen, int mode) { - bool no_key_mode = !strcmp ("base64", algo) || !strcmp ("base91", algo); //TODO: generalise this for all non key encoding/decoding. + bool no_key_mode = !strcmp ("base64", algo) || !strcmp ("base91", algo) || !strcmp ("punycode", algo); //TODO: generalise this for all non key encoding/decoding. if (no_key_mode || s.len > 0) { RCrypto *cry = r_crypto_new (); if (r_crypto_use (cry, algo)) { @@ -328,7 +328,7 @@ int encrypt_or_decrypt(const char *algo, int direction, const char *hashstr, int } int encrypt_or_decrypt_file (const char *algo, int direction, char *filename, const ut8 *iv, int ivlen, int mode) { - bool no_key_mode = !strcmp ("base64", algo) || !strcmp ("base91", algo); //TODO: generalise this for all non key encoding/decoding. + bool no_key_mode = !strcmp ("base64", algo) || !strcmp ("base91", algo) || !strcmp ("punycode", algo); //TODO: generalise this for all non key encoding/decoding. if (no_key_mode || s.len > 0) { RCrypto *cry = r_crypto_new (); if (r_crypto_use (cry, algo)) { diff --git a/libr/core/cmd_write.c b/libr/core/cmd_write.c index 03b24246f4..0eb691c379 100644 --- a/libr/core/cmd_write.c +++ b/libr/core/cmd_write.c @@ -28,10 +28,10 @@ R_API int cmd_write_hexpair(RCore* core, const char* pairs) { return !len; } -static bool encrypt_or_decrypt_block(RCore *core, const char *algo, const char *key, int direction) { +static bool encrypt_or_decrypt_block(RCore *core, const char *algo, const char *key, int direction, const char *iv) { //TODO: generalise no_key_mode for all non key encoding/decoding. int keylen = key ? strlen (key): 0; - bool no_key_mode = !strcmp ("base64", algo) || !strcmp ("base91", algo); + bool no_key_mode = !strcmp ("base64", algo) || !strcmp ("base91", algo) || !strcmp ("punycode", algo); if (no_key_mode || keylen > 0) { RCrypto *cry = r_crypto_new (); if (r_crypto_use (cry, algo)) { @@ -45,6 +45,19 @@ static bool encrypt_or_decrypt_block(RCore *core, const char *algo, const char * keylen = len; } if (r_crypto_set_key (cry, binkey, keylen, 0, direction)) { + if (iv) { + ut8 *biniv = malloc (strlen (iv) + 1); + int ivlen = r_hex_str2bin (iv, biniv); + if (ivlen < 1) { + ivlen = strlen(iv); + strcpy ((char *)biniv, iv); + } + if (!r_crypto_set_iv (cry, biniv, ivlen)) { + eprintf ("Invalid IV.\n"); + return 0; + } + } + r_crypto_update (cry, (const ut8*)core->block, core->blocksize); r_crypto_final (cry, NULL, 0); @@ -109,9 +122,9 @@ static void cmd_write_op (RCore *core, const char *input) { "woa"," [val]", "+= addition (f.ex: woa 0102)", "woA"," [val]","&= and", "wod"," [val]", "/= divide", - "woD","[algo] [key]","decrypt current block with given algo and key", + "woD","[algo] [key] [IV]","decrypt current block with given algo and key", "woe"," [from to] [step] [wsz=1]",".. create sequence", - "woE"," [algo] [key]", "encrypt current block with given algo and key", + "woE"," [algo] [key] [IV]", "encrypt current block with given algo and key", "wol"," [val]","<<= shift left", "wom"," [val]", "*= multiply", "woo"," [val]","|= or", @@ -168,17 +181,23 @@ static void cmd_write_op (RCore *core, const char *input) { int direction = (input[1] == 'E') ? 0 : 1; const char *algo = NULL; const char *key = NULL; + const char *iv = NULL; char *space, *args = strdup (r_str_chop_ro (input+2)); space = strchr (args, ' '); if (space) { *space++ = 0; key = space; + space = strchr (key, ' '); + if (space) { + *space++ = 0; + iv = space; + } } algo = args; if (algo && *algo) { - encrypt_or_decrypt_block (core, algo, key, direction); + encrypt_or_decrypt_block (core, algo, key, direction, iv); } else { - eprintf ("Usage: wo%c [algo] [key]\n", ((!direction)?'E':'D')); + eprintf ("Usage: wo%c [algo] [key] [IV]\n", ((!direction)?'E':'D')); eprintf ("TODO: list currently supported crypto algorithms\n"); eprintf (" rc2, rc4, xor, blowfish, aes, rot, ror, rol\n"); } diff --git a/libr/crypto/Jamroot b/libr/crypto/Jamroot index 8d9862feab..607a734b45 100644 --- a/libr/crypto/Jamroot +++ b/libr/crypto/Jamroot @@ -1,4 +1,4 @@ OBJS = crypto.c ; -OBJS += p/crypto_aes.c p/crypto_aes_algo.c p/crypto_xor.c p/crypto_blowfish.c p/crypto_rc2.c p/crypto_rot.c p/crypto_rol.c p/crypto_ror.c p/crypto_base64.c p/crypto_base91.c p/crypto_aes_cbc.c; +OBJS += p/crypto_aes.c p/crypto_aes_algo.c p/crypto_xor.c p/crypto_blowfish.c p/crypto_rc2.c p/crypto_rot.c p/crypto_rol.c p/crypto_ror.c p/crypto_base64.c p/crypto_base91.c p/crypto_aes_cbc.c p/crypto_punycode.c; lib r_crypto : $(OBJS) : ../include ../util ; diff --git a/libr/crypto/p/crypto_punycode.c b/libr/crypto/p/crypto_punycode.c new file mode 100644 index 0000000000..a04257dee2 --- /dev/null +++ b/libr/crypto/p/crypto_punycode.c @@ -0,0 +1,52 @@ +#include +#include +#include + +static int flag = 0; + +static int punycode_set_key(RCrypto *cry, const ut8 *key, int keylen, int mode, int direction) { + flag = direction; + return true; +} + +static int punycode_get_key_size(RCrypto *cry) { + return 0; +} + +static bool punycode_use(const char *algo) { + return !strcmp (algo, "punycode"); +} + +static int update(RCrypto *cry, const ut8 *buf, int len) { + char *obuf; + int olen; + if (flag) { + obuf = r_punycode_decode ((const char *)buf, len, &olen); + } else { + obuf = r_punycode_encode ((const char *)buf, len, &olen); + } + r_crypto_append (cry, (ut8*)obuf, olen); + free (obuf); + return 0; +} + +static int final(RCrypto *cry, const ut8* buf, int len) { + return update (cry, buf, len); +} + +RCryptoPlugin r_crypto_plugin_punycode = { + .name = "punycode", + .set_key = punycode_set_key, + .get_key_size = punycode_get_key_size, + .use = punycode_use, + .update = update, + .final = final +}; + +#ifndef CORELIB +struct r_lib_struct_t radare_plugin = { + .type = R_LIB_TYPE_CRYPTO, + .data = &r_crypto_plugin_punycode, + .version = R2_VERSION +} +#endif diff --git a/libr/crypto/p/punycode.mk b/libr/crypto/p/punycode.mk new file mode 100644 index 0000000000..26429c6289 --- /dev/null +++ b/libr/crypto/p/punycode.mk @@ -0,0 +1,9 @@ +OBJ_PUNY=crypto_punycode.o + +STATIC_OBJ+=${OBJ_PUNY} +TARGET_PUNY=crypto_punycode.${EXT_SO} + +ALL_TARGETS+=${TARGET_PUNY} + +${TARGET_PUNY}: ${OBJ_PUNY} + ${CC} $(call libname,crypto_punycode) ${LDFLAGS} ${CFLAGS} -o ${TARGET_PUNY} ${OBJ_PUNY} diff --git a/libr/include/r_crypto.h b/libr/include/r_crypto.h index 45b82125ba..1c5fe29ead 100644 --- a/libr/include/r_crypto.h +++ b/libr/include/r_crypto.h @@ -72,6 +72,7 @@ extern RCryptoPlugin r_crypto_plugin_ror; extern RCryptoPlugin r_crypto_plugin_base64; extern RCryptoPlugin r_crypto_plugin_base91; extern RCryptoPlugin r_crypto_plugin_aes_cbc; +extern RCryptoPlugin r_crypto_plugin_punycode; #ifdef __cplusplus } diff --git a/libr/include/r_util.h b/libr/include/r_util.h index 28856b45d9..7dabb98350 100644 --- a/libr/include/r_util.h +++ b/libr/include/r_util.h @@ -483,6 +483,9 @@ R_API char *r_base64_encode_dyn(const char *str, int len); R_API int r_base91_encode(char *bout, const ut8 *bin, int len); R_API int r_base91_decode(ut8 *bout, const char *bin, int len); +R_API char *r_punycode_encode(const char*src, int srclen, int *dstlen); +R_API char *r_punycode_decode(const char *src, int srclen, int *dstlen); + /* strings */ static inline void r_str_rmch (char *s, char ch) { for (;*s; s++) { diff --git a/libr/util/Makefile b/libr/util/Makefile index 6eb17980d2..fd464ec3bc 100644 --- a/libr/util/Makefile +++ b/libr/util/Makefile @@ -12,7 +12,7 @@ OBJS+=strpool.o bitmap.o strht.o p_date.o p_format.o print.o OBJS+=p_seven.o slist.o randomart.o log.o zip.o debruijn.o OBJS+=utf8.o strbuf.o lib.o name.o spaces.o OBJS+=diff.o bdiff.o stack.o queue.o tree.o des.o -OBJS+=swap.o +OBJS+=swap.o punycode.o # DO NOT BUILD r_big api (not yet used and its buggy) ifeq (1,0) diff --git a/libr/util/punycode.c b/libr/util/punycode.c new file mode 100644 index 0000000000..a77dc0bf01 --- /dev/null +++ b/libr/util/punycode.c @@ -0,0 +1,229 @@ +#include +#include +#include + +#define BASE 36 +#define TMIN 1 +#define TMAX 26 +#define SKEW 38 +#define DAMP 700 +#define INITIAL_N 128 +#define INITIAL_BIAS 72 + +ut32 adapt_bias(ut32 delta, unsigned n_points, int is_first) { + ut32 k; + delta /= is_first ? DAMP : 2; + delta += delta / n_points; + + for (k = 0; k > ((BASE - TMIN) * TMAX) / 2; k += BASE) { + delta /= (BASE - TMIN); + } + + return k + (((BASE - TMIN + 1) * delta) / (delta + SKEW)); +} + +char encode_digit(int c) { + assert (c >= 0 && c <= BASE - TMIN); + if (c > 25) { + return c + 22; + } + return c + 'a'; +} + +static ut32 encode_var_int(const ut32 bias, const ut32 delta, char *dst) { + ut32 i, k, q, t; + i = 0; + k = BASE; + q = delta; + + while (true) { + if (k <= bias) { + t = TMIN; + } else if (k >= bias + TMAX) { + t = TMAX; + } else { + t = k - bias; + } + + if (q < t) { + break; + } + + dst[i++] = encode_digit (t + (q - t) % (BASE - t)); + + q = (q - t) / (BASE - t); + k += BASE; + } + + dst[i++] = encode_digit (q); + + return i; +} + +static char decode_digit(char v) { + if (v >= '0' && v <= '9') { + return v - 22; + } + if (v >= 'a' && v <= 'z') { + return v - 'a'; + } + if (v >= 'A' && v <= 'Z') { + return v - 'A'; + } + return -1; +} + +R_API char *r_punycode_encode(const char *src, int srclen, int *dstlen) { + ut8 m, n; + ut32 b, h; + ut32 si, di; + ut32 delta, bias; + char *dst; + + *dstlen = 0; + + if (!src || srclen < 1) { + return NULL; + } + + dst = calloc (2*srclen+10, 1); + if (!dst) { + return NULL; + } + + for (si = 0, di = 0; si < srclen; si++) { + if ((ut8)src[si] < 128) { + dst[di++] = src[si]; + } + } + + b = h = di; + + if (di > 0) { + dst[di++] = '-'; + } + + n = INITIAL_N; + bias = INITIAL_BIAS; + + for (delta = 0; h < srclen; n++, delta++) { + for (m = 0xff, si = 0; si < srclen; si++) { + if ((ut8)src[si] >= n && (ut8)src[si] <= m) { + m = src[si]; + } + } + + if ((unsigned int)(m - n) > (UT32_MAX - delta) / (h + 1)) { + return NULL; + } + + delta += (m - n) * (h + 1); + n = m; + + for (si = 0; si < srclen; si++) { + if ((ut8)src[si] < n) { + if (++delta == 0) { + return NULL; + } + } else if ((ut8)src[si] == n) { + di += encode_var_int (bias, delta, &dst[di]); + bias = adapt_bias (delta, h+1, h == b); + delta = 0; + h++; + } + } + } + *dstlen = di; + return dst; +} + +R_API char *r_punycode_decode(const char *src, int srclen, int *dstlen) { + ut8 n; + const char *p; + ut32 si, di; + ut32 b, t, i, k, w; + ut32 digit, org_i, bias; + char *dst; + + *dstlen = 0; + if (!src || srclen < 1) { + return NULL; + } + + dst = calloc (2*srclen + 10, 1); + if (!dst) { + return NULL; + } + + for (si = 0; si < srclen; si++) { + if (src[si] & 0x80) { + return NULL; /*just return it*/ + } + } + + for (p = src + srclen - 1; p > src && *p != '-'; p--); + b = p - src; + + di = b; + for (i = 0; i < di; i++) { + dst[i] = src[i]; + } + + i = 0; + n = INITIAL_N; + bias = INITIAL_BIAS; + + for (si = b + (b > 0); si < srclen; di++) { + org_i = i; + + for (w = 1, k = BASE; ; k += BASE) { + digit = decode_digit (src[si++]); + + if ((char)digit == -1) { + free (dst); + return NULL; + } + + if (digit > (UT32_MAX - i) / w) { + free (dst); + return NULL; + } + + i += digit * w; + + if (k <= bias) { + t = TMIN; + } else if (k >= bias + TMAX) { + t = TMAX; + } else { + t = k - bias; + } + + if (digit < t) { + break; + } + + if (w > UT32_MAX / (BASE - t)) { + free (dst); + return NULL; + } + + w *= BASE- t; + } + + bias = adapt_bias(i - org_i, di+1, org_i == 0); + + if (i / (di + 1) > UT32_MAX - n) { + free (dst); + return NULL; + } + + n += i / (di + 1); + i %= (di + 1); + + memmove (dst+i+1, dst+i, (di-i) * sizeof(char)); + dst[i++] = n; + } + *dstlen = di; + return dst; +} diff --git a/plugins.def.cfg b/plugins.def.cfg index 21318d7451..a0abd9b32f 100644 --- a/plugins.def.cfg +++ b/plugins.def.cfg @@ -159,6 +159,7 @@ crypto.ror crypto.base64 crypto.base91 crypto.aes_cbc +crypto.punycode debug.bf debug.esil debug.gdb