diff --git a/libr/include/r_util.h b/libr/include/r_util.h index c060f77efb4ed..27862c6ded19f 100644 --- a/libr/include/r_util.h +++ b/libr/include/r_util.h @@ -36,6 +36,7 @@ int gettimeofday (struct timeval* p, void* tz); #include "r_util/r_new_rbtree.h" #include "r_util/r_intervaltree.h" #include "r_util/r_big.h" +#include "r_util/r_base32.h" #include "r_util/r_base36.h" #include "r_util/r_base64.h" #include "r_util/r_base91.h" diff --git a/libr/include/r_util/r_base32.h b/libr/include/r_util/r_base32.h new file mode 100644 index 0000000000000..69672a5cb9fcd --- /dev/null +++ b/libr/include/r_util/r_base32.h @@ -0,0 +1,22 @@ +#ifndef R2_BASE32_H +#define R2_BASE32_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if R2_USE_NEW_ABI + +#include + +R_API char *r_base32_encode(const ut8 *data, size_t input_length, size_t *output_length); +R_API ut8 *r_base32_decode(const char *data, size_t input_length, size_t *output_length); +R_API char *base32_encode_ut64(ut64 input); +R_API ut64 base32_decode_ut64(const char *input); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libr/meson.build b/libr/meson.build index da84cbaa5146d..e1866e9735a97 100644 --- a/libr/meson.build +++ b/libr/meson.build @@ -479,6 +479,7 @@ r_util_files = [ 'include/r_util/r_asn1.h', 'include/r_util/r_assert.h', 'include/r_util/r_axml.h', + 'include/r_util/r_base32.h', 'include/r_util/r_base36.h', 'include/r_util/r_base64.h', 'include/r_util/r_base91.h', diff --git a/libr/util/Makefile b/libr/util/Makefile index 46e4f5dfb6b94..ed8707f607637 100644 --- a/libr/util/Makefile +++ b/libr/util/Makefile @@ -15,7 +15,7 @@ OBJS+=udiff.o bdiff.o stack.o queue.o tree.o idpool.o assert.o bplist.o OBJS+=punycode.o pkcs7.o x509.o asn1.o asn1_str.o json_parser.o json_indent.o skiplist.o OBJS+=pj.o rbtree.o intervaltree.o qrcode.o vector.o str_constpool.o str_trim.o OBJS+=ascii_table.o protobuf.o graph_drawable.o axml.o sstext.o new_rbtree.o token.o -OBJS+=rvc.o rvc_git.o rvc_rvc.o bscanf.o rprintf.o +OBJS+=rvc.o rvc_git.o rvc_rvc.o bscanf.o rprintf.o base32.o ifeq (${HAVE_GPERF},1) OBJS+=d/ascii.o diff --git a/libr/util/base32.c b/libr/util/base32.c new file mode 100644 index 0000000000000..3d1fe763ac194 --- /dev/null +++ b/libr/util/base32.c @@ -0,0 +1,123 @@ +/* radare - LGPL - Copyright 2024 - pancake */ + +#include + +#if R2_USE_NEW_ABI +static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; +static const char base32_padding = '='; + +// Utility function to find index in base32 alphabet +static int base32_char_index(char c) { + if (c >= 'A' && c <= 'Z') { + return c - 'A'; + } + if (c >= '2' && c <= '7') { + return c - '2' + 26; + } + return -1; +} + +R_API char *r_base32_encode(const ut8 *data, size_t input_length, size_t *output_length) { + size_t encoded_size = (input_length + 4) / 5 * 8; + char *encoded_data = (char *)malloc (encoded_size + 1); + if (!encoded_data) { + return NULL; + } + + size_t i, j, index; + int current_byte, next_byte; + for (i = 0, j = 0; i < input_length;) { + current_byte = data[i++] << 8; + if (i < input_length) current_byte |= data[i++]; + current_byte <<= 8; + if (i < input_length) current_byte |= data[i++]; + current_byte <<= 8; + if (i < input_length) current_byte |= data[i++]; + current_byte <<= 8; + if (i < input_length) current_byte |= data[i++]; + + for (index = 0; index < 8; index++) { + next_byte = (current_byte & 0xF8000000) >> 27; + encoded_data[j++] = base32_alphabet[next_byte]; + current_byte <<= 5; + } + } + + while (j < encoded_size) { + encoded_data[j++] = base32_padding; + } + encoded_data[encoded_size] = '\0'; + + if (output_length) { + *output_length = encoded_size; + } + return encoded_data; +} + +R_API ut8 *r_base32_decode(const char *data, size_t input_length, size_t *output_length) { + if (input_length % 8 != 0) { + return NULL; + } + + size_t decoded_size = input_length * 5 / 8; + unsigned char *decoded_data = (unsigned char *)malloc (decoded_size); + if (!decoded_data) { + return NULL; + } + + size_t i, j, index; + int current_byte, next_byte; + for (i = 0, j = 0; i < input_length;) { + current_byte = 0; + for (index = 0; index < 8 && i < input_length; index++) { + next_byte = base32_char_index (toupper (data[i++])); + if (next_byte == -1) { + return NULL; + } + current_byte = (current_byte << 5) | next_byte; + } + + for (index = 0; index < 5; index++) { + decoded_data[j++] = (current_byte & 0xFF000000) >> 24; + current_byte <<= 8; + } + } + + if (output_length) { + *output_length = decoded_size; + } + return decoded_data; +} + +R_API char *base32_encode_ut64(ut64 input) { + size_t encoded_size = 13; // Maximum 13 characters for 64-bit input + char *encoded_data = (char *)malloc (encoded_size + 1); + if (!encoded_data) { + return NULL; + } + + int i; + for (i = 12; i >= 0; i--) { + encoded_data[i] = base32_alphabet[input & 0x1F]; + input >>= 5; + } + encoded_data[encoded_size] = '\0'; + + return encoded_data; +} + +// Decode function for ut64 +R_API ut64 base32_decode_ut64(const char *input) { + ut64 decoded_value = 0; + int i; + for (i = 0; i < 13; i++) { + int index = base32_char_index (toupper (input[i])); + if (index == -1) { + return 0; + } + decoded_value = (decoded_value << 5) | index; + } + return decoded_value; +} + +#endif diff --git a/libr/util/meson.build b/libr/util/meson.build index 9a465d47061a1..bcfc13f925b7e 100644 --- a/libr/util/meson.build +++ b/libr/util/meson.build @@ -19,6 +19,7 @@ r_util_sources = [ 'sstext.c', 'getopt.c', 'print_code.c', + 'base32.c', 'base36.c', 'base85.c', 'base91.c',