bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch#include "lib.h"
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch#include "base32.h"
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch#include "buffer.h"
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschstatic const char b32enc[] =
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschstatic const char b32hexenc[] =
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch "0123456789ABCDEFGHIJKLMNOPQRSTUV";
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschstatic const unsigned char b32dec[256] = {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 48-55 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* 64-71 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, /* 72-79 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* 80-87 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch};
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschstatic const unsigned char b32hexdec[256] = {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0-7 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 8-15 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16-23 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 24-31 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32-39 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 40-47 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 48-55 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56-63 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* 64-71 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* 72-79 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, /* 80-87 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 88-95 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96-103 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 104-111 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112-119 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 120-127 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128-255 */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch};
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschstatic void
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschbase32_encode_with_alphabet(const char *alph,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch bool pad, const void *src, size_t src_size, buffer_t *dest)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch const unsigned char *src_c = src;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch unsigned char tmp[8], endb;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch size_t src_pos;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch /* [5 3][2 5 1][4 4][1 5 2][3 5]
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (5)(3 2)(5)(1 4)(4 1)(5)(2 3)(5)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch /* encode main part */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch for (src_pos = 0; src_pos + 4 < src_size; src_pos += 5) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[0] = alph[src_c[src_pos] >> 3];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ((src_c[src_pos+1] >> 6) & 0x03)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (src_c[src_pos+2] >> 4)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (src_c[src_pos+3] >> 7)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (src_c[src_pos+4] >> 5)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[7] = alph[src_c[src_pos+4] & 0x1f];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_append(dest, tmp, 8);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch /* encode last < 5 bytes if any */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (src_pos < src_size) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[0] = alph[src_c[src_pos] >> 3];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch switch (src_size - src_pos) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 1:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[1] = alph[((src_c[src_pos] & 0x07) << 2)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch endb = 2;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 2:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ((src_c[src_pos+1] >> 6) & 0x03)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch endb = 4;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 3:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ((src_c[src_pos+1] >> 6) & 0x03)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (src_c[src_pos+2] >> 4)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch endb = 5;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 4:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[1] = alph[((src_c[src_pos] & 0x07) << 2) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ((src_c[src_pos+1] >> 6) & 0x03)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[2] = alph[((src_c[src_pos+1] >> 1) & 0x1f)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[3] = alph[((src_c[src_pos+1] & 0x01) << 4) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (src_c[src_pos+2] >> 4)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[4] = alph[((src_c[src_pos+2] & 0x0f) << 1) |
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (src_c[src_pos+3] >> 7)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[5] = alph[((src_c[src_pos+3] >> 2) & 0x1f)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch tmp[6] = alph[((src_c[src_pos+3] & 0x03) << 3)];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch endb = 7;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch default:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch i_unreached();
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch /* add padding if required */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (pad) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch memset(&tmp[endb], '=', sizeof(tmp)-endb);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_append(dest, tmp, 8);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch } else {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_append(dest, tmp, endb);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschvoid base32_encode(bool pad, const void *src, size_t src_size,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_t *dest)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch base32_encode_with_alphabet(b32enc, pad, src, src_size, dest);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschvoid base32hex_encode(bool pad, const void *src, size_t src_size,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_t *dest)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch base32_encode_with_alphabet(b32hexenc, pad, src, src_size, dest);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch#define IS_EMPTY(c) \
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ((c) == '\n' || (c) == '\r' || (c) == ' ' || (c) == '\t')
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschstatic int
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschbase32_decode_with_alphabet(const unsigned char *alph,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch const void *src, size_t src_size, size_t *src_pos_r,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_t *dest)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch const unsigned char *src_c = src;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch size_t block_pos, src_pos;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch unsigned char output[5], ipos, opos;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch int ret = 1;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch /* (5)(3 2)(5)(1 4)(4 1)(5)(2 3)(5)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch [5 3][2 5 1][4 4][1 5 2][3 5]
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch */
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ipos = opos = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch block_pos = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch for (src_pos = 0; src_pos < src_size; src_pos++) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch unsigned char input = alph[src_c[src_pos]];
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (input == 0xff) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (unlikely(!IS_EMPTY(src_c[src_pos])))
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch continue;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ipos++;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch switch (ipos) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 1:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[0] = input << 3;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 2:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[0] |= input >> 2;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[1] = (input & 0x03) << 6;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 1;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 3:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[1] |= input << 1;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 1;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 4:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[1] |= input >> 4;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[2] = (input & 0x0f) << 4;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 2;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 5:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[2] |= input >> 1;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[3] = (input & 0x01) << 7;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 3;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 6:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[3] |= input << 2;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 3;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 7:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[3] |= input >> 3;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[4] = ((input & 0x07) << 5);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 4;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch case 8:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch output[4] |= input;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_append(dest, output, 5);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ipos = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch opos = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch block_pos = src_pos;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch default:
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch i_unreached();
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (ipos > 0) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch for (; src_pos < src_size; src_pos++) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (src_c[src_pos] != '=') {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (unlikely(!IS_EMPTY(src_c[src_pos]))) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ret = -1;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch continue;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (++ipos >= 8) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_append(dest, output, opos);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ipos = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch ret = 0;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch src_pos++;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (src_pos_r != NULL) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (ipos == 0) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch for (; src_pos < src_size; src_pos++) {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch if (!IS_EMPTY(src_c[src_pos]))
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch break;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch *src_pos_r = src_pos;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch } else {
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch *src_pos_r = block_pos;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch }
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return ret;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschint base32_decode(const void *src, size_t src_size,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch size_t *src_pos_r, buffer_t *dest)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return base32_decode_with_alphabet
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (b32dec, src, src_size, src_pos_r, dest);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschint base32hex_decode(const void *src, size_t src_size,
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch size_t *src_pos_r, buffer_t *dest)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return base32_decode_with_alphabet
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (b32hexdec, src, src_size, src_pos_r, dest);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschbuffer_t *t_base32_decode_str(const char *str)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_t *buf;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch size_t len = strlen(str);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(MAX_BASE32_DECODED_SIZE(len));
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (void)base32_decode(str, len, NULL, buf);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return buf;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschbuffer_t *t_base32hex_decode_str(const char *str)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch buffer_t *buf;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch size_t len = strlen(str);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
c147bff818798a979d93537f72f5c1f68f5d5ba8Aki Tuomi buf = t_buffer_create(MAX_BASE32_DECODED_SIZE(len));
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch (void)base32hex_decode(str, len, NULL, buf);
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return buf;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschbool base32_is_valid_char(char c)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return b32dec[(uint8_t)c] != 0xff;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Boschbool base32hex_is_valid_char(char c)
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch{
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch return b32hexdec[(uint8_t)c] != 0xff;
75f7e423ea22446ed529d33cb660dadf680e13e0Stephan Bosch}