naev 0.11.5
base64.c
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
4/*
5 * compliant with rfc3548
6 */
8#include <stdint.h>
9#include <stdlib.h>
12#include "base64.h"
13
14#include "nstring.h"
15
16/* encode table - base 64 alphabet as defined by the rfc */
17static const char cb64[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18/* generate decode table at compile time */
19#define B64(_) \
20 ((_) == 'A' ? 0 \
21 : (_) == 'B' ? 1 \
22 : (_) == 'C' ? 2 \
23 : (_) == 'D' ? 3 \
24 : (_) == 'E' ? 4 \
25 : (_) == 'F' ? 5 \
26 : (_) == 'G' ? 6 \
27 : (_) == 'H' ? 7 \
28 : (_) == 'I' ? 8 \
29 : (_) == 'J' ? 9 \
30 : (_) == 'K' ? 10 \
31 : (_) == 'L' ? 11 \
32 : (_) == 'M' ? 12 \
33 : (_) == 'N' ? 13 \
34 : (_) == 'O' ? 14 \
35 : (_) == 'P' ? 15 \
36 : (_) == 'Q' ? 16 \
37 : (_) == 'R' ? 17 \
38 : (_) == 'S' ? 18 \
39 : (_) == 'T' ? 19 \
40 : (_) == 'U' ? 20 \
41 : (_) == 'V' ? 21 \
42 : (_) == 'W' ? 22 \
43 : (_) == 'X' ? 23 \
44 : (_) == 'Y' ? 24 \
45 : (_) == 'Z' ? 25 \
46 : (_) == 'a' ? 26 \
47 : (_) == 'b' ? 27 \
48 : (_) == 'c' ? 28 \
49 : (_) == 'd' ? 29 \
50 : (_) == 'e' ? 30 \
51 : (_) == 'f' ? 31 \
52 : (_) == 'g' ? 32 \
53 : (_) == 'h' ? 33 \
54 : (_) == 'i' ? 34 \
55 : (_) == 'j' ? 35 \
56 : (_) == 'k' ? 36 \
57 : (_) == 'l' ? 37 \
58 : (_) == 'm' ? 38 \
59 : (_) == 'n' ? 39 \
60 : (_) == 'o' ? 40 \
61 : (_) == 'p' ? 41 \
62 : (_) == 'q' ? 42 \
63 : (_) == 'r' ? 43 \
64 : (_) == 's' ? 44 \
65 : (_) == 't' ? 45 \
66 : (_) == 'u' ? 46 \
67 : (_) == 'v' ? 47 \
68 : (_) == 'w' ? 48 \
69 : (_) == 'x' ? 49 \
70 : (_) == 'y' ? 50 \
71 : (_) == 'z' ? 51 \
72 : (_) == '0' ? 52 \
73 : (_) == '1' ? 53 \
74 : (_) == '2' ? 54 \
75 : (_) == '3' ? 55 \
76 : (_) == '4' ? 56 \
77 : (_) == '5' ? 57 \
78 : (_) == '6' ? 58 \
79 : (_) == '7' ? 59 \
80 : (_) == '8' ? 60 \
81 : (_) == '9' ? 61 \
82 : (_) == '+' ? 62 \
83 : (_) == '/' ? 63 \
84 : -1)
85static const signed char cd64[256] = { /* makes it much faster */
86 B64 (0), B64 (1), B64 (2), B64 (3),
87 B64 (4), B64 (5), B64 (6), B64 (7),
88 B64 (8), B64 (9), B64 (10), B64 (11),
89 B64 (12), B64 (13), B64 (14), B64 (15),
90 B64 (16), B64 (17), B64 (18), B64 (19),
91 B64 (20), B64 (21), B64 (22), B64 (23),
92 B64 (24), B64 (25), B64 (26), B64 (27),
93 B64 (28), B64 (29), B64 (30), B64 (31),
94 B64 (32), B64 (33), B64 (34), B64 (35),
95 B64 (36), B64 (37), B64 (38), B64 (39),
96 B64 (40), B64 (41), B64 (42), B64 (43),
97 B64 (44), B64 (45), B64 (46), B64 (47),
98 B64 (48), B64 (49), B64 (50), B64 (51),
99 B64 (52), B64 (53), B64 (54), B64 (55),
100 B64 (56), B64 (57), B64 (58), B64 (59),
101 B64 (60), B64 (61), B64 (62), B64 (63),
102 B64 (64), B64 (65), B64 (66), B64 (67),
103 B64 (68), B64 (69), B64 (70), B64 (71),
104 B64 (72), B64 (73), B64 (74), B64 (75),
105 B64 (76), B64 (77), B64 (78), B64 (79),
106 B64 (80), B64 (81), B64 (82), B64 (83),
107 B64 (84), B64 (85), B64 (86), B64 (87),
108 B64 (88), B64 (89), B64 (90), B64 (91),
109 B64 (92), B64 (93), B64 (94), B64 (95),
110 B64 (96), B64 (97), B64 (98), B64 (99),
111 B64 (100), B64 (101), B64 (102), B64 (103),
112 B64 (104), B64 (105), B64 (106), B64 (107),
113 B64 (108), B64 (109), B64 (110), B64 (111),
114 B64 (112), B64 (113), B64 (114), B64 (115),
115 B64 (116), B64 (117), B64 (118), B64 (119),
116 B64 (120), B64 (121), B64 (122), B64 (123),
117 B64 (124), B64 (125), B64 (126), B64 (127),
118 B64 (128), B64 (129), B64 (130), B64 (131),
119 B64 (132), B64 (133), B64 (134), B64 (135),
120 B64 (136), B64 (137), B64 (138), B64 (139),
121 B64 (140), B64 (141), B64 (142), B64 (143),
122 B64 (144), B64 (145), B64 (146), B64 (147),
123 B64 (148), B64 (149), B64 (150), B64 (151),
124 B64 (152), B64 (153), B64 (154), B64 (155),
125 B64 (156), B64 (157), B64 (158), B64 (159),
126 B64 (160), B64 (161), B64 (162), B64 (163),
127 B64 (164), B64 (165), B64 (166), B64 (167),
128 B64 (168), B64 (169), B64 (170), B64 (171),
129 B64 (172), B64 (173), B64 (174), B64 (175),
130 B64 (176), B64 (177), B64 (178), B64 (179),
131 B64 (180), B64 (181), B64 (182), B64 (183),
132 B64 (184), B64 (185), B64 (186), B64 (187),
133 B64 (188), B64 (189), B64 (190), B64 (191),
134 B64 (192), B64 (193), B64 (194), B64 (195),
135 B64 (196), B64 (197), B64 (198), B64 (199),
136 B64 (200), B64 (201), B64 (202), B64 (203),
137 B64 (204), B64 (205), B64 (206), B64 (207),
138 B64 (208), B64 (209), B64 (210), B64 (211),
139 B64 (212), B64 (213), B64 (214), B64 (215),
140 B64 (216), B64 (217), B64 (218), B64 (219),
141 B64 (220), B64 (221), B64 (222), B64 (223),
142 B64 (224), B64 (225), B64 (226), B64 (227),
143 B64 (228), B64 (229), B64 (230), B64 (231),
144 B64 (232), B64 (233), B64 (234), B64 (235),
145 B64 (236), B64 (237), B64 (238), B64 (239),
146 B64 (240), B64 (241), B64 (242), B64 (243),
147 B64 (244), B64 (245), B64 (246), B64 (247),
148 B64 (248), B64 (249), B64 (250), B64 (251),
149 B64 (252), B64 (253), B64 (254), B64 (255)
150};
151
152/*
153 * encodes src of sz length storing the new length in len
154 */
155char* base64_encode( size_t *len, const char *src, size_t sz )
156{
157 char *r;
158 size_t i, c;
159 uint32_t n;
160 uint8_t ch[4], pad;
161
162 /* create r */
163 c = (sz+2) / 3 * 4;
164 c += (c-1) / 76 + 1; /* newlines, null byte */
165 r = malloc( c );
166
167 /* setup padding */
168 pad = ((sz % 3) == 0) ? 0 : 3 - sz % 3;
169
170 /* time to do the bulk work */
171 i = 0;
172 for (c=0; c<sz; c+=3) {
173
174 /* specification wants newline after every 76 characters */
175 if ((c > 0) && ((c / 3 * 4) % 76 == 0))
176 r[i++] = '\n';
177
178 /* n is 24 bits */
179 n = ((uint8_t)src[c] << 16);
180 n += (c+1<sz) ? ((uint8_t)src[c+1] << 8) : 0; /* may be out of range */
181 n += (c+2<sz) ? ((uint8_t)src[c+2] << 0) : 0; /* may be out of range */
182
183 /* ch[0-3] are 6 bits each */
184 ch[0] = (n >> 18) & 63;
185 ch[1] = (n >> 12) & 63;
186 ch[2] = (n >> 6) & 63;
187 ch[3] = (n >> 0) & 63;
188
189 /* add to str */
190 r[i++] = cb64[ ch[0] ];
191 r[i++] = cb64[ ch[1] ];
192 r[i++] = cb64[ ch[2] ];
193 r[i++] = cb64[ ch[3] ];
194 }
195
196 for (c=0; c<pad; c++)
197 r[i-c-1] = '=';
198 r[i] = '\0'; /* it'll be a valid string */
199 (*len) = i;
200
201 return r;
202}
203
204/*
205 * decode the buffer, same syntax as base64_encode
206 */
207#define dec_valid(inp) (cd64[(int)inp] == -1) ? 0 : 1
208#define dec_ch(inp) cd64[(int)inp]
209char* base64_decode( size_t *len, const char *src, size_t sz )
210{
211 char *r, *dat, pad;
212 size_t c,i,j;
213
214 /* allocate r */
215 c = sz * 3 / 4 + 2;
216 r = malloc( c );
217
218 /* create a clean version of the text */
219 pad = 0;
220 dat = malloc( sz );
221 j = 0;
222 for (i=0; i<sz; i++) {
223 if (src[i] == '=') /* control padding */
224 pad++;
225 if (dec_valid( src[i] )) /* only allow valid characters */
226 dat[j++] = src[i];
227 }
228
229 /* fill r */
230 i = 0;
231 for (c=0; c<j; c+=4) {
232 /* process the input from base 64 */
233 uint32_t n = dec_ch( dat[c+0] ) << 18; /* guaranteed to be valid */
234 n += (c+1<j) ? (dec_ch( dat[c+1] ) << 12) : 0; /* check if inbounds */
235 n += (c+2<j) ? (dec_ch( dat[c+2] ) << 6) : 0;
236 n += (c+3<j) ? (dec_ch( dat[c+3] ) << 0) : 0;
237
238 /* convert the 24 bits of encoded data into 3 8 bit chunks */
239 r[i++] = (n >> 16) & 255;
240 r[i++] = (n >> 8) & 255;
241 r[i++] = (n >> 0) & 255;
242 }
243
244 /* cleanup */
245 free(dat);
246
247 (*len) = i - pad; /* must decount the padding */
248 return r;
249}
250
251/*
252 * encodes src of sz length storing the new length in len
253 */
254char* base64_encode_to_cstr( const char *src, size_t sz )
255{
256 size_t len;
257 return base64_encode( &len, src, sz );
258}
259
260/*
261 * encodes src of sz length storing the new length in len
262 */
263char* base64_decode_cstr( size_t *len, const char *src )
264{
265 return base64_decode( len, src, strlen( src ) );
266}
static const double c[]
Definition rng.c:264