From 75f7e423ea22446ed529d33cb660dadf680e13e0 Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Sat, 15 Nov 2014 02:39:04 +0200 Subject: [PATCH] Added support for base32 encode/decode. --- src/lib/Makefile.am | 3 + src/lib/base32.c | 326 ++++++++++++++++++++++++++++++++++++++++++ src/lib/base32.h | 47 ++++++ src/lib/test-base32.c | 190 ++++++++++++++++++++++++ src/lib/test-lib.c | 1 + src/lib/test-lib.h | 1 + 6 files changed, 568 insertions(+) create mode 100644 src/lib/base32.c create mode 100644 src/lib/base32.h create mode 100644 src/lib/test-base32.c diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index ae2f8e0989..4aec0eae25 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -16,6 +16,7 @@ liblib_la_SOURCES = \ aqueue.c \ askpass.c \ backtrace-string.c \ + base32.c \ base64.c \ bits.c \ bsearch-insert-pos.c \ @@ -149,6 +150,7 @@ headers = \ array-decl.h \ askpass.h \ backtrace-string.h \ + base32.h \ base64.h \ bits.h \ bsearch-insert-pos.h \ @@ -278,6 +280,7 @@ test_lib_SOURCES = \ test-lib.c \ test-array.c \ test-aqueue.c \ + test-base32.c \ test-base64.c \ test-bits.c \ test-bsearch-insert-pos.c \ diff --git a/src/lib/base32.c b/src/lib/base32.c new file mode 100644 index 0000000000..b68394113d --- /dev/null +++ b/src/lib/base32.c @@ -0,0 +1,326 @@ +/* Copyright (c) 2007-2014 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "base32.h" +#include "buffer.h" + +static const char b32enc[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + +static const char b32hexenc[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUV"; + +static const unsigned char b32dec[256] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */ + 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 48-55 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */ + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* 64-71 */ + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, /* 72-79 */ + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* 80-87 */ + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */ + + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static const unsigned char b32hexdec[256] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 48-55 */ + 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* 64-71 */ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 72-79 */ + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* 80-87 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */ + + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static void +base32_encode_with_alphabet(const char *alph, + bool pad, const void *src, size_t src_size, buffer_t *dest) +{ + const unsigned char *src_c = src; + unsigned char tmp[8], endb; + size_t src_pos; + + /* [5 3][2 5 1][4 4][1 5 2][3 5] + (5)(3 2)(5)(1 4)(4 1)(5)(2 3)(5) + */ + + /* encode main part */ + for (src_pos = 0; src_pos + 4 < src_size; src_pos += 5) { + tmp[0] = alph[src_c[src_pos] >> 3]; + tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) | + ((src_c[src_pos+1] >> 6) & 0x03)]; + tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)]; + tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) | + (src_c[src_pos+2] >> 4)]; + tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) | + (src_c[src_pos+3] >> 7)]; + tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)]; + tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3) | + (src_c[src_pos+4] >> 5)]; + tmp[7] = alph[src_c[src_pos+4] & 0x1f]; + buffer_append(dest, tmp, 8); + } + + /* encode last < 5 bytes if any */ + if (src_pos < src_size) { + tmp[0] = alph[src_c[src_pos] >> 3]; + switch (src_size - src_pos) { + case 1: + tmp[1] = alph[((src_c[src_pos] & 0x07) << 2)]; + endb = 2; + break; + case 2: + tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) | + ((src_c[src_pos+1] >> 6) & 0x03)]; + tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)]; + tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4)]; + endb = 4; + break; + case 3: + tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) | + ((src_c[src_pos+1] >> 6) & 0x03)]; + tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)]; + tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) | + (src_c[src_pos+2] >> 4)]; + tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1)]; + endb = 5; + break; + case 4: + tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) | + ((src_c[src_pos+1] >> 6) & 0x03)]; + tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)]; + tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) | + (src_c[src_pos+2] >> 4)]; + tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) | + (src_c[src_pos+3] >> 7)]; + tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)]; + tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3)]; + endb = 7; + break; + default: + i_unreached(); + } + + /* add padding if required */ + if (pad) { + memset(&tmp[endb], '=', sizeof(tmp)-endb); + buffer_append(dest, tmp, 8); + } else { + buffer_append(dest, tmp, endb); + } + } +} + +void base32_encode(bool pad, const void *src, size_t src_size, + buffer_t *dest) +{ + base32_encode_with_alphabet(b32enc, pad, src, src_size, dest); +} + +void base32hex_encode(bool pad, const void *src, size_t src_size, + buffer_t *dest) +{ + base32_encode_with_alphabet(b32hexenc, pad, src, src_size, dest); +} + +#define IS_EMPTY(c) \ + ((c) == '\n' || (c) == '\r' || (c) == ' ' || (c) == '\t') + +static int +base32_decode_with_alphabet(const unsigned char *alph, + const void *src, size_t src_size, size_t *src_pos_r, + buffer_t *dest) +{ + const unsigned char *src_c = src; + size_t block_pos, src_pos; + unsigned char output[5], ipos, opos; + int ret = 1; + + /* (5)(3 2)(5)(1 4)(4 1)(5)(2 3)(5) + [5 3][2 5 1][4 4][1 5 2][3 5] + */ + ipos = opos = 0; + block_pos = 0; + for (src_pos = 0; src_pos < src_size; src_pos++) { + unsigned char input = alph[src_c[src_pos]]; + + if (input == 0xff) { + if (unlikely(!IS_EMPTY(src_c[src_pos]))) + break; + continue; + } + + ipos++; + switch (ipos) { + case 1: + output[0] = input << 3; + opos = 0; + break; + case 2: + output[0] |= input >> 2; + output[1] = (input & 0x03) << 6; + opos = 1; + break; + case 3: + output[1] |= input << 1; + opos = 1; + break; + case 4: + output[1] |= input >> 4; + output[2] = (input & 0x0f) << 4; + opos = 2; + break; + case 5: + output[2] |= input >> 1; + output[3] = (input & 0x01) << 7; + opos = 3; + break; + case 6: + output[3] |= input << 2; + opos = 3; + break; + case 7: + output[3] |= input >> 3; + output[4] = ((input & 0x07) << 5); + opos = 4; + break; + case 8: + output[4] |= input; + buffer_append(dest, output, 5); + ipos = 0; + opos = 0; + block_pos = src_pos; + break; + default: + i_unreached(); + } + } + + if (ipos > 0) { + for (; src_pos < src_size; src_pos++) { + if (src_c[src_pos] != '=') { + if (unlikely(!IS_EMPTY(src_c[src_pos]))) { + ret = -1; + break; + } + continue; + } + if (++ipos >= 8) { + buffer_append(dest, output, opos); + ipos = 0; + ret = 0; + src_pos++; + break; + } + } + } + + if (src_pos_r != NULL) { + if (ipos == 0) { + for (; src_pos < src_size; src_pos++) { + if (!IS_EMPTY(src_c[src_pos])) + break; + } + + *src_pos_r = src_pos; + } else { + *src_pos_r = block_pos; + } + } + return ret; +} + +int base32_decode(const void *src, size_t src_size, + size_t *src_pos_r, buffer_t *dest) +{ + return base32_decode_with_alphabet + (b32dec, src, src_size, src_pos_r, dest); +} +int base32hex_decode(const void *src, size_t src_size, + size_t *src_pos_r, buffer_t *dest) +{ + return base32_decode_with_alphabet + (b32hexdec, src, src_size, src_pos_r, dest); +} + +buffer_t *t_base32_decode_str(const char *str) +{ + buffer_t *buf; + size_t len = strlen(str); + + buf = buffer_create_dynamic(pool_datastack_create(), + MAX_BASE32_DECODED_SIZE(len)); + (void)base32_decode(str, len, NULL, buf); + return buf; +} + +buffer_t *t_base32hex_decode_str(const char *str) +{ + buffer_t *buf; + size_t len = strlen(str); + + buf = buffer_create_dynamic(pool_datastack_create(), + MAX_BASE32_DECODED_SIZE(len)); + (void)base32hex_decode(str, len, NULL, buf); + return buf; +} + +bool base32_is_valid_char(char c) +{ + return b32dec[(uint8_t)c] != 0xff; +} + +bool base32hex_is_valid_char(char c) +{ + return b32hexdec[(uint8_t)c] != 0xff; +} diff --git a/src/lib/base32.h b/src/lib/base32.h new file mode 100644 index 0000000000..6a7b52a0e6 --- /dev/null +++ b/src/lib/base32.h @@ -0,0 +1,47 @@ +#ifndef BASE32_H +#define BASE32_H + +/* Translates binary data into base32 (RFC 4648, Section 6). The src must not + point to dest buffer. The pad argument determines whether output is padded + with '='. + */ +void base32_encode(bool pad, const void *src, size_t src_size, + buffer_t *dest); + +/* Translates binary data into base32hex (RFC 4648, Section 7). The src must + not point to dest buffer. The pad argument determines whether output is + padded with '='. + */ +void base32hex_encode(bool pad, const void *src, size_t src_size, + buffer_t *dest); + +/* Translates base32/base32hex data into binary and appends it to dest buffer. + dest may point to same buffer as src. Returns 1 if all ok, 0 if end of + base32 data found, -1 if data is invalid. + + Any whitespace characters are ignored. + + This function may be called multiple times for parsing the same stream. + If src_pos is non-NULL, it's updated to first non-translated character in + src. */ +int base32_decode(const void *src, size_t src_size, + size_t *src_pos_r, buffer_t *dest) ATTR_NULL(4); +int base32hex_decode(const void *src, size_t src_size, + size_t *src_pos_r, buffer_t *dest) ATTR_NULL(4); + +/* Decode given string to a buffer allocated from data stack. */ +buffer_t *t_base32_decode_str(const char *str); +buffer_t *t_base32hex_decode_str(const char *str); + +/* Returns TRUE if c is a valid base32 encoding character (excluding '=') */ +bool base32_is_valid_char(char c); +bool base32hex_is_valid_char(char c); + +/* max. buffer size required for base32_encode()/base32hex_encode() */ +#define MAX_BASE32_ENCODED_SIZE(size) \ + ((size) / 5 * 8 + 8) +/* max. buffer size required for base32_decode()/base32hex_decode() */ +#define MAX_BASE32_DECODED_SIZE(size) \ + ((size) / 8 * 5 + 5) + +#endif diff --git a/src/lib/test-base32.c b/src/lib/test-base32.c new file mode 100644 index 0000000000..dc0f86cf61 --- /dev/null +++ b/src/lib/test-base32.c @@ -0,0 +1,190 @@ +/* Copyright (c) 2007-2014 Dovecot authors, see the included COPYING file */ + +#include "test-lib.h" +#include "str.h" +#include "base32.h" + +#include + +static void test_base32_encode(void) +{ + static const char *input[] = { + "toedeledokie!!", + "bye bye world", + "hoeveel onzin kun je testen?????", + "c'est pas vrai! ", + "dit is het einde van deze test" + }; + static const char *output[] = { + "ORXWKZDFNRSWI33LNFSSCII=", + "MJ4WKIDCPFSSA53POJWGI===", + "NBXWK5TFMVWCA33OPJUW4IDLOVXCA2TFEB2GK43UMVXD6PZ7H47Q====", + "MMTWK43UEBYGC4ZAOZZGC2JBEA======", + "MRUXIIDJOMQGQZLUEBSWS3TEMUQHMYLOEBSGK6TFEB2GK43U" + }; + string_t *str; + unsigned int i; + + test_begin("base32_encode() with padding"); + str = t_str_new(256); + for (i = 0; i < N_ELEMENTS(input); i++) { + str_truncate(str, 0); + base32_encode(TRUE, input[i], strlen(input[i]), str); + test_assert(strcmp(output[i], str_c(str)) == 0); + } + test_end(); + + test_begin("base32_encode() no padding"); + str = t_str_new(256); + for (i = 0; i < N_ELEMENTS(input); i++) { + const char *p = strchr(output[i], '='); + size_t len; + + if (p == NULL) + len = strlen(output[i]); + else + len = (size_t)(p - output[i]); + str_truncate(str, 0); + base32_encode(FALSE, input[i], strlen(input[i]), str); + test_assert(strncmp(output[i], str_c(str), len) == 0); + } + test_end(); +} + +static void test_base32hex_encode(void) +{ + static const char *input[] = { + "toedeledokie!!", + "bye bye world", + "hoeveel onzin kun je testen?????", + "c'est pas vrai! ", + "dit is het einde van deze test" + }; + static const char *output[] = { + "EHNMAP35DHIM8RRBD5II288=", + "C9SMA832F5II0TRFE9M68===", + "D1NMATJ5CLM20RREF9KMS83BELN20QJ541Q6ASRKCLN3UFPV7SVG====", + "CCJMASRK41O62SP0EPP62Q9140======", + "CHKN8839ECG6GPBK41IMIRJ4CKG7COBE41I6AUJ541Q6ASRK" + }; + string_t *str; + unsigned int i; + + test_begin("base32hex_encode() with padding"); + str = t_str_new(256); + for (i = 0; i < N_ELEMENTS(input); i++) { + str_truncate(str, 0); + base32hex_encode(TRUE, input[i], strlen(input[i]), str); + test_assert(strcmp(output[i], str_c(str)) == 0); + } + test_end(); + + test_begin("base32hex_encode() no padding"); + str = t_str_new(256); + for (i = 0; i < N_ELEMENTS(input); i++) { + const char *p = strchr(output[i], '='); + size_t len; + + if (p == NULL) + len = strlen(output[i]); + else + len = (size_t)(p - output[i]); + str_truncate(str, 0); + base32hex_encode(FALSE, input[i], strlen(input[i]), str); + test_assert(strncmp(output[i], str_c(str), len) == 0); + } + test_end(); + +} + +struct test_base32_decode_output { + const char *text; + int ret; + unsigned int src_pos; +}; + +static void test_base32_decode(void) +{ + static const char *input[] = { + "ORXWKZDFNRSWI33LNFSSCII=", + "MJ4WKIDCPFSSA53POJWGI===", + "NBXWK5TFMVWCA33OPJUW4IDLOVXCA2TFEB2GK43UMVXD6PZ7H47Q====", + "MMTWK43UEBYGC4ZAOZZGC2JBEA======", + "MRUXIIDJOMQGQZLUEBSWS3TEMUQHMYLOEBSGK6TFEB2GK43U" + }; + static const struct test_base32_decode_output output[] = { + { "toedeledokie!!", 0, 24 }, + { "bye bye world", 0, 24 }, + { "hoeveel onzin kun je testen?????", 0, 56 }, + { "c'est pas vrai! ", 0, 32 }, + { "dit is het einde van deze test", 1, 48 }, + }; + string_t *str; + unsigned int i; + size_t src_pos; + int ret; + + test_begin("base32_decode()"); + str = t_str_new(256); + for (i = 0; i < N_ELEMENTS(input); i++) { + str_truncate(str, 0); + + src_pos = 0; + ret = base32_decode(input[i], strlen(input[i]), &src_pos, str); + + test_assert(output[i].ret == ret && + strcmp(output[i].text, str_c(str)) == 0 && + (src_pos == output[i].src_pos || + (output[i].src_pos == UINT_MAX && + src_pos == strlen(input[i])))); + } + test_end(); +} + +static void test_base32_random(void) +{ + string_t *str, *dest; + char buf[10]; + unsigned int i, j, max; + + str = t_str_new(256); + dest = t_str_new(256); + + test_begin("padded base32 encode/decode with random input"); + for (i = 0; i < 1000; i++) { + max = rand() % sizeof(buf); + for (j = 0; j < max; j++) + buf[j] = rand(); + + str_truncate(str, 0); + str_truncate(dest, 0); + base32_encode(TRUE, buf, max, str); + test_assert(base32_decode(str_data(str), str_len(str), NULL, dest) >= 0); + test_assert(str_len(dest) == max && + memcmp(buf, str_data(dest), max) == 0); + } + test_end(); + + test_begin("padded base32hex encode/decode with random input"); + for (i = 0; i < 1000; i++) { + max = rand() % sizeof(buf); + for (j = 0; j < max; j++) + buf[j] = rand(); + + str_truncate(str, 0); + str_truncate(dest, 0); + base32hex_encode(TRUE, buf, max, str); + test_assert(base32hex_decode(str_data(str), str_len(str), NULL, dest) >= 0); + test_assert(str_len(dest) == max && + memcmp(buf, str_data(dest), max) == 0); + } + test_end(); +} + +void test_base32(void) +{ + test_base32_encode(); + test_base32hex_encode(); + test_base32_decode(); + test_base32_random(); +} diff --git a/src/lib/test-lib.c b/src/lib/test-lib.c index 8083e0f769..5c264eb9c1 100644 --- a/src/lib/test-lib.c +++ b/src/lib/test-lib.c @@ -7,6 +7,7 @@ int main(void) static void (*test_functions[])(void) = { test_aqueue, test_array, + test_base32, test_base64, test_bits, test_bsearch_insert_pos, diff --git a/src/lib/test-lib.h b/src/lib/test-lib.h index 8fd07c332e..fe19f6bca7 100644 --- a/src/lib/test-lib.h +++ b/src/lib/test-lib.h @@ -6,6 +6,7 @@ void test_aqueue(void); void test_array(void); +void test_base32(void); void test_base64(void); void test_bits(void); void test_bsearch_insert_pos(void); -- 2.47.3