1 /* Licensed under BSD-MIT - see LICENSE file for details */
10 * sixbit_to_b64 - maps a 6-bit value to the base64 alphabet
11 * @param map A base 64 map (see base64_init_map)
12 * @param sixbit Six-bit value to map
13 * @return a base 64 character
15 static char sixbit_to_b64(const base64_maps_t *maps, const uint8_t sixbit)
20 return maps->encode_map[(unsigned char)sixbit];
24 * sixbit_from_b64 - maps a base64-alphabet character to its 6-bit value
25 * @param maps A base 64 maps structure (see base64_init_maps)
26 * @param sixbit Six-bit value to map
27 * @return a six-bit value
29 static int8_t sixbit_from_b64(const base64_maps_t *maps,
30 const unsigned char b64letter)
34 ret = maps->decode_map[(unsigned char)b64letter];
35 if (ret == (char)0xff) {
43 bool base64_char_in_alphabet(const base64_maps_t *maps, const char b64char)
45 return (maps->decode_map[(const unsigned char)b64char] != (char)0xff);
48 void base64_init_maps(base64_maps_t *dest, const char src[64])
52 memcpy(dest->encode_map,src,64);
53 memset(dest->decode_map,0xff,256);
54 for (i=0; i<64; i++) {
55 dest->decode_map[(unsigned char)src[i]] = i;
59 size_t base64_encoded_length(size_t srclen)
61 return ((srclen + 2) / 3) * 4;
64 void base64_encode_triplet_using_maps(const base64_maps_t *maps,
65 char dest[4], const char src[3])
71 dest[0] = sixbit_to_b64(maps, (a & 0xfc) >> 2);
72 dest[1] = sixbit_to_b64(maps, ((a & 0x3) << 4) | ((b & 0xf0) >> 4));
73 dest[2] = sixbit_to_b64(maps, ((c & 0xc0) >> 6) | ((b & 0xf) << 2));
74 dest[3] = sixbit_to_b64(maps, c & 0x3f);
77 void base64_encode_tail_using_maps(const base64_maps_t *maps, char dest[4],
78 const char *src, const size_t srclen)
80 char longsrc[3] = { 0 };
84 memcpy(longsrc, src, srclen);
85 base64_encode_triplet_using_maps(maps, dest, longsrc);
86 memset(dest+1+srclen, '=', 3-srclen);
89 ssize_t base64_encode_using_maps(const base64_maps_t *maps,
90 char *dest, const size_t destlen,
91 const char *src, const size_t srclen)
93 size_t src_offset = 0;
94 size_t dest_offset = 0;
96 if (destlen < base64_encoded_length(srclen)) {
101 while (srclen - src_offset >= 3) {
102 base64_encode_triplet_using_maps(maps, &dest[dest_offset], &src[src_offset]);
107 if (src_offset < srclen) {
108 base64_encode_tail_using_maps(maps, &dest[dest_offset], &src[src_offset], srclen-src_offset);
112 memset(&dest[dest_offset], '\0', destlen-dest_offset);
117 size_t base64_decoded_length(size_t srclen)
119 return ((srclen+3)/4*3);
122 int base64_decode_quartet_using_maps(const base64_maps_t *maps, char dest[3],
130 a = sixbit_from_b64(maps, src[0]);
131 b = sixbit_from_b64(maps, src[1]);
132 c = sixbit_from_b64(maps, src[2]);
133 d = sixbit_from_b64(maps, src[3]);
135 if ((a == -1) || (b == -1) || (c == -1) || (d == -1)) {
139 dest[0] = (a << 2) | (b >> 4);
140 dest[1] = ((b & 0xf) << 4) | (c >> 2);
141 dest[2] = ((c & 0x3) << 6) | d;
147 int base64_decode_tail_using_maps(const base64_maps_t *maps, char dest[3],
148 const char * src, const size_t srclen)
152 size_t insize = srclen;
154 while (insize != 0 &&
155 src[insize-1] == '=') { /* throw away padding symbols */
162 /* the input is malformed.... */
166 memcpy(longsrc, src, insize);
167 memset(longsrc+insize, 'A', 4-insize);
168 quartet_result = base64_decode_quartet_using_maps(maps, dest, longsrc);
169 if (quartet_result == -1) {
176 ssize_t base64_decode_using_maps(const base64_maps_t *maps,
177 char *dest, const size_t destlen,
178 const char *src, const size_t srclen)
180 ssize_t dest_offset = 0;
184 if (destlen < base64_decoded_length(srclen)) {
189 for(i=0; srclen - i > 4; i+=4) {
190 if (base64_decode_quartet_using_maps(maps, &dest[dest_offset], &src[i]) == -1) {
196 more = base64_decode_tail_using_maps(maps, &dest[dest_offset], &src[i], srclen - i);
202 memset(&dest[dest_offset], '\0', destlen-dest_offset);
211 * base64_maps_rfc4648 - pregenerated maps struct for rfc4648
213 static const base64_maps_t base64_maps_rfc4648 = {
214 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
216 "\xff\xff\xff\xff\xff" /* 0 */ \
217 "\xff\xff\xff\xff\xff" /* 5 */ \
218 "\xff\xff\xff\xff\xff" /* 10 */ \
219 "\xff\xff\xff\xff\xff" /* 15 */ \
220 "\xff\xff\xff\xff\xff" /* 20 */ \
221 "\xff\xff\xff\xff\xff" /* 25 */ \
222 "\xff\xff\xff\xff\xff" /* 30 */ \
223 "\xff\xff\xff\xff\xff" /* 35 */ \
224 "\xff\xff\xff\x3e\xff" /* 40 */ \
225 "\xff\xff\x3f\x34\x35" /* 45 */ \
226 "\x36\x37\x38\x39\x3a" /* 50 */ \
227 "\x3b\x3c\x3d\xff\xff" /* 55 */ \
228 "\xff\xff\xff\xff\xff" /* 60 */ \
229 "\x00\x01\x02\x03\x04" /* 65 A */ \
230 "\x05\x06\x07\x08\x09" /* 70 */ \
231 "\x0a\x0b\x0c\x0d\x0e" /* 75 */ \
232 "\x0f\x10\x11\x12\x13" /* 80 */ \
233 "\x14\x15\x16\x17\x18" /* 85 */ \
234 "\x19\xff\xff\xff\xff" /* 90 */ \
235 "\xff\xff\x1a\x1b\x1c" /* 95 */ \
236 "\x1d\x1e\x1f\x20\x21" /* 100 */ \
237 "\x22\x23\x24\x25\x26" /* 105 */ \
238 "\x27\x28\x29\x2a\x2b" /* 110 */ \
239 "\x2c\x2d\x2e\x2f\x30" /* 115 */ \
240 "\x31\x32\x33\xff\xff" /* 120 */ \
241 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 125 */ \
242 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
243 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
244 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 155 */ \
245 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
246 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
247 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 185 */ \
248 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
249 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
250 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 215 */ \
251 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
252 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" \
253 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 245 */