All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
base64.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006 Free Software
3  * Foundation, Inc.
4  *
5  * This program is left software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  * @brief Encode/decode binary data using printable characters.
22  * @author Simon Josefsson.
23  * @see RFC 3548 <http://www.ietf.org/rfc/rfc3548.txt>.
24  */
25 RCSID("$Id: 6ace506b70494c88573fd4ed7c67ce749b3939ea $")
26 
27 #include <freeradius-devel/libradius.h>
28 #include <freeradius-devel/base64.h>
29 
30 #define us(x) (uint8_t) x
31 
32 /** Base 64 encode binary data
33  *
34  * Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
35  *
36  * @param[out] out Where to write Base64 string.
37  * @param[in] outlen size of buffer including NULL byte.
38  * @param[in] in Data to encode.
39  * @param[in] inlen Length of data to encode.
40  * @return
41  * - Amount of data we wrote to the buffer.
42  * - -1 if output buffer was too small.
43  */
44 size_t fr_base64_encode(char *out, size_t outlen, uint8_t const *in, size_t inlen)
45 {
46  static char const b64str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
47 
48  char *p = out;
49  if (outlen < (FR_BASE64_ENC_LENGTH(inlen) + 1)) {
50  *out = '\0';
51  return -1;
52  }
53 
54  while (inlen) {
55  *p++ = b64str[(in[0] >> 2) & 0x3f];
56  *p++ = b64str[((in[0] << 4) + (--inlen ? in[1] >> 4 : 0)) & 0x3f];
57  *p++ = (inlen ? b64str[((in[1] << 2) + (--inlen ? in[2] >> 6 : 0)) & 0x3f] : '=');
58  *p++ = inlen ? b64str[in[2] & 0x3f] : '=';
59 
60  if (inlen) inlen--;
61  if (inlen) in += 3;
62  }
63 
64  p[0] = '\0';
65 
66  return p - out;
67 }
68 
69 /*
70  * With this approach this file works independent of the charset used
71  * (think EBCDIC). However, it does assume that the characters in the
72  * Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
73  * 1003.1-2001 require that char and unsigned char are 8-bit
74  * quantities, though, taking care of that problem. But this may be a
75  * potential problem on non-POSIX C99 platforms.
76  *
77  * IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
78  * as the formal parameter rather than "x".
79  */
80 #define B64(_) \
81  ((_) == 'A' ? 0 \
82  : (_) == 'B' ? 1 \
83  : (_) == 'C' ? 2 \
84  : (_) == 'D' ? 3 \
85  : (_) == 'E' ? 4 \
86  : (_) == 'F' ? 5 \
87  : (_) == 'G' ? 6 \
88  : (_) == 'H' ? 7 \
89  : (_) == 'I' ? 8 \
90  : (_) == 'J' ? 9 \
91  : (_) == 'K' ? 10 \
92  : (_) == 'L' ? 11 \
93  : (_) == 'M' ? 12 \
94  : (_) == 'N' ? 13 \
95  : (_) == 'O' ? 14 \
96  : (_) == 'P' ? 15 \
97  : (_) == 'Q' ? 16 \
98  : (_) == 'R' ? 17 \
99  : (_) == 'S' ? 18 \
100  : (_) == 'T' ? 19 \
101  : (_) == 'U' ? 20 \
102  : (_) == 'V' ? 21 \
103  : (_) == 'W' ? 22 \
104  : (_) == 'X' ? 23 \
105  : (_) == 'Y' ? 24 \
106  : (_) == 'Z' ? 25 \
107  : (_) == 'a' ? 26 \
108  : (_) == 'b' ? 27 \
109  : (_) == 'c' ? 28 \
110  : (_) == 'd' ? 29 \
111  : (_) == 'e' ? 30 \
112  : (_) == 'f' ? 31 \
113  : (_) == 'g' ? 32 \
114  : (_) == 'h' ? 33 \
115  : (_) == 'i' ? 34 \
116  : (_) == 'j' ? 35 \
117  : (_) == 'k' ? 36 \
118  : (_) == 'l' ? 37 \
119  : (_) == 'm' ? 38 \
120  : (_) == 'n' ? 39 \
121  : (_) == 'o' ? 40 \
122  : (_) == 'p' ? 41 \
123  : (_) == 'q' ? 42 \
124  : (_) == 'r' ? 43 \
125  : (_) == 's' ? 44 \
126  : (_) == 't' ? 45 \
127  : (_) == 'u' ? 46 \
128  : (_) == 'v' ? 47 \
129  : (_) == 'w' ? 48 \
130  : (_) == 'x' ? 49 \
131  : (_) == 'y' ? 50 \
132  : (_) == 'z' ? 51 \
133  : (_) == '0' ? 52 \
134  : (_) == '1' ? 53 \
135  : (_) == '2' ? 54 \
136  : (_) == '3' ? 55 \
137  : (_) == '4' ? 56 \
138  : (_) == '5' ? 57 \
139  : (_) == '6' ? 58 \
140  : (_) == '7' ? 59 \
141  : (_) == '8' ? 60 \
142  : (_) == '9' ? 61 \
143  : (_) == '+' ? 62 \
144  : (_) == '/' ? 63 \
145  : -1)
146 
147 static const signed char b64[0x100] = {
148  B64 (0), B64 (1), B64 (2), B64 (3),
149  B64 (4), B64 (5), B64 (6), B64 (7),
150  B64 (8), B64 (9), B64 (10), B64 (11),
151  B64 (12), B64 (13), B64 (14), B64 (15),
152  B64 (16), B64 (17), B64 (18), B64 (19),
153  B64 (20), B64 (21), B64 (22), B64 (23),
154  B64 (24), B64 (25), B64 (26), B64 (27),
155  B64 (28), B64 (29), B64 (30), B64 (31),
156  B64 (32), B64 (33), B64 (34), B64 (35),
157  B64 (36), B64 (37), B64 (38), B64 (39),
158  B64 (40), B64 (41), B64 (42), B64 (43),
159  B64 (44), B64 (45), B64 (46), B64 (47),
160  B64 (48), B64 (49), B64 (50), B64 (51),
161  B64 (52), B64 (53), B64 (54), B64 (55),
162  B64 (56), B64 (57), B64 (58), B64 (59),
163  B64 (60), B64 (61), B64 (62), B64 (63),
164  B64 (64), B64 (65), B64 (66), B64 (67),
165  B64 (68), B64 (69), B64 (70), B64 (71),
166  B64 (72), B64 (73), B64 (74), B64 (75),
167  B64 (76), B64 (77), B64 (78), B64 (79),
168  B64 (80), B64 (81), B64 (82), B64 (83),
169  B64 (84), B64 (85), B64 (86), B64 (87),
170  B64 (88), B64 (89), B64 (90), B64 (91),
171  B64 (92), B64 (93), B64 (94), B64 (95),
172  B64 (96), B64 (97), B64 (98), B64 (99),
173  B64 (100), B64 (101), B64 (102), B64 (103),
174  B64 (104), B64 (105), B64 (106), B64 (107),
175  B64 (108), B64 (109), B64 (110), B64 (111),
176  B64 (112), B64 (113), B64 (114), B64 (115),
177  B64 (116), B64 (117), B64 (118), B64 (119),
178  B64 (120), B64 (121), B64 (122), B64 (123),
179  B64 (124), B64 (125), B64 (126), B64 (127),
180  B64 (128), B64 (129), B64 (130), B64 (131),
181  B64 (132), B64 (133), B64 (134), B64 (135),
182  B64 (136), B64 (137), B64 (138), B64 (139),
183  B64 (140), B64 (141), B64 (142), B64 (143),
184  B64 (144), B64 (145), B64 (146), B64 (147),
185  B64 (148), B64 (149), B64 (150), B64 (151),
186  B64 (152), B64 (153), B64 (154), B64 (155),
187  B64 (156), B64 (157), B64 (158), B64 (159),
188  B64 (160), B64 (161), B64 (162), B64 (163),
189  B64 (164), B64 (165), B64 (166), B64 (167),
190  B64 (168), B64 (169), B64 (170), B64 (171),
191  B64 (172), B64 (173), B64 (174), B64 (175),
192  B64 (176), B64 (177), B64 (178), B64 (179),
193  B64 (180), B64 (181), B64 (182), B64 (183),
194  B64 (184), B64 (185), B64 (186), B64 (187),
195  B64 (188), B64 (189), B64 (190), B64 (191),
196  B64 (192), B64 (193), B64 (194), B64 (195),
197  B64 (196), B64 (197), B64 (198), B64 (199),
198  B64 (200), B64 (201), B64 (202), B64 (203),
199  B64 (204), B64 (205), B64 (206), B64 (207),
200  B64 (208), B64 (209), B64 (210), B64 (211),
201  B64 (212), B64 (213), B64 (214), B64 (215),
202  B64 (216), B64 (217), B64 (218), B64 (219),
203  B64 (220), B64 (221), B64 (222), B64 (223),
204  B64 (224), B64 (225), B64 (226), B64 (227),
205  B64 (228), B64 (229), B64 (230), B64 (231),
206  B64 (232), B64 (233), B64 (234), B64 (235),
207  B64 (236), B64 (237), B64 (238), B64 (239),
208  B64 (240), B64 (241), B64 (242), B64 (243),
209  B64 (244), B64 (245), B64 (246), B64 (247),
210  B64 (248), B64 (249), B64 (250), B64 (251),
211  B64 (252), B64 (253), B64 (254), B64 (255)
212 };
213 
214 /** Check if char is in Base64 alphabet
215  *
216  * Note that '=' is padding and not considered to be part of the alphabet.
217  *
218  * @param c char to check.
219  * @return
220  * - true if c is a character from the Base64 alphabet.
221  * - false if character is not in the Base64 alphabet.
222  */
223 bool fr_is_base64(char c)
224 {
225  return b64[us(c)] >= 0;
226 }
227 
228 /* Decode base64 encoded input array.
229  *
230  * Decode base64 encoded input array IN of length INLEN to output array OUT that
231  * can hold *OUTLEN bytes. Return true if decoding was successful, i.e.
232  * if the input was valid base64 data, -1 otherwise.
233  *
234  * If *OUTLEN is too small, as many bytes as possible will be written to OUT.
235  * On return, *OUTLEN holds the length of decoded bytes in OUT.
236  *
237  * Note that as soon as any non-alphabet characters are encountered,
238  * decoding is stopped and -1 is returned.
239  *
240  * This means that, when applicable, you must remove any line terminators
241  * that is part of the data stream before calling this function.
242  *
243  * @param[out] out Where to write the decoded data.
244  * @param[in] outlen The length of the output buffer.
245  * @param[in] in Base64 string to decode.
246  * @param[in] inlen length of Base64 string.
247  * @return
248  * - -1 on failure.
249  * - Length of decoded data.
250  */
251 ssize_t fr_base64_decode(uint8_t *out, size_t outlen, char const *in, size_t inlen)
252 {
253  uint8_t *p = out;
254 
255  if (outlen < FR_BASE64_DEC_LENGTH(inlen)) {
256  return -1;
257  }
258 
259  while (inlen >= 2) {
260  if (!fr_is_base64(in[0]) || !fr_is_base64(in[1])) {
261  break;
262  }
263 
264  *p++ = ((b64[us(in[0])] << 2) | (b64[us(in[1])] >> 4));
265 
266  if (inlen == 2) break;
267 
268  if (in[2] == '=') {
269  if ((inlen != 4) || (in[3] != '=')) break;
270  } else {
271  if (!fr_is_base64(in[2])) break;
272 
273  *p++ = ((b64[us(in[1])] << 4) & 0xf0) | (b64[us(in[2])] >> 2);
274 
275  if (inlen == 3) break;
276 
277  if (in[3] == '=') {
278  if (inlen != 4) break;
279  } else {
280  if (!fr_is_base64(in[3])) break;
281 
282  *p++ = ((b64[us(in[2])] << 6) & 0xc0) | b64[us(in[3])];
283  }
284  }
285 
286  in += 4;
287  inlen -= 4;
288  }
289 
290  if (inlen != 0) {
291  return -1;
292  }
293 
294  return p - out;
295 }
size_t fr_base64_encode(char *out, size_t outlen, uint8_t const *in, size_t inlen)
Base 64 encode binary data.
Definition: base64.c:44
bool fr_is_base64(char c)
Check if char is in Base64 alphabet.
Definition: base64.c:223
#define FR_BASE64_ENC_LENGTH(inlen)
Definition: base64.h:38
ssize_t fr_base64_decode(uint8_t *out, size_t outlen, char const *in, size_t inlen)
Definition: base64.c:251
#define B64(_)
Definition: base64.c:80
#define FR_BASE64_DEC_LENGTH(inlen)
Definition: base64.h:39
#define RCSID(id)
Definition: build.h:135
static const signed char b64[0x100]
Definition: base64.c:147
#define us(x)
Encode/decode binary data using printable characters.
Definition: base64.c:30