1 /* CC0 license (public domain) - see LICENSE file for details */
4 #include <ccan/endian/endian.h>
5 #include <string.h> /* for memcpy, memset */
9 * (1) The final quantum of encoding input is an integral multiple of 40
10 * bits; here, the final unit of encoded output will be an integral
11 * multiple of 8 characters with no "=" padding.
13 * (2) The final quantum of encoding input is exactly 8 bits; here, the
14 * final unit of encoded output will be two characters followed by
15 * six "=" padding characters.
17 * (3) The final quantum of encoding input is exactly 16 bits; here, the
18 * final unit of encoded output will be four characters followed by
19 * four "=" padding characters.
21 * (4) The final quantum of encoding input is exactly 24 bits; here, the
22 * final unit of encoded output will be five characters followed by
23 * three "=" padding characters.
25 * (5) The final quantum of encoding input is exactly 32 bits; here, the
26 * final unit of encoded output will be seven characters followed by
27 * one "=" padding character.
29 static size_t padlen(size_t remainder)
47 size_t base32_str_size(size_t bytes)
49 return (bytes + 4) / 5 * 8 + 1;
52 size_t base32_data_size(const char *str, size_t strlen)
54 /* 8 chars == 5 bytes, round up to avoid overflow even though
55 * not required for well-formed strings. */
56 size_t max = (strlen + 7) / 8 * 5, padding = 0;
58 /* Count trailing padding bytes. */
59 while (strlen && str[strlen-1] == '=' && padding < 6) {
64 return max - (padding * 5 + 7) / 8;
67 static bool decode_8_chars(const char c[8], beint64_t *res, int *bytes)
71 for (int i = 0; i < 8; i++) {
74 if (c[i] >= 'a' && c[i] <= 'z')
76 else if (c[i] >= 'A' && c[i] <= 'Z')
78 else if (c[i] >= '2' && c[i] <= '7')
79 val = c[i] - '2' + 26;
80 else if (c[i] == '=') {
85 /* Can't have padding then non-pad */
90 *res = cpu_to_be64(acc);
92 /* Can't have 2 or 5 padding bytes */
93 if (num_pad == 5 || num_pad == 2)
95 *bytes = (40 - num_pad * 5) / 8;
99 bool base32_decode(const char *str, size_t slen, void *buf, size_t bufsize)
104 if (!decode_8_chars(str, &val, &bytes))
108 /* Copy bytes into dst. */
111 memcpy(buf, (char *)&val + 3, bytes);
112 buf = (char *)buf + bytes;
115 return slen == 0 && bufsize == 0;
118 static void encode_8_chars(char *dest, const uint8_t *buf, int bytes)
122 int bits = bytes * 8;
123 static const char enc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
125 assert(bytes > 0 && bytes <= 5);
126 memcpy((char *)&val + 3, buf, bytes);
127 res = be64_to_cpu(val);
130 *dest = enc[(res >> 35) & 0x1F];
137 memset(dest, '=', padlen(bytes));
140 bool base32_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
150 encode_8_chars(dest, buf, bytes);
151 buf = (const char *)buf + bytes;