Line data Source code
1 : /*
2 : * Base64 encoding/decoding (RFC1341)
3 : * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include <stdlib.h>
10 : #include <string.h>
11 :
12 : #include "base64.h"
13 :
14 : static const unsigned char base64_table[65] =
15 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
16 :
17 : /*
18 : * Calculated using:
19 : * memset(dtable, 0x80, 256);
20 : * for (i = 0; i < sizeof(base64_table) - 1; i++)
21 : * dtable[base64_table[i]] = (unsigned char) i;
22 : * dtable['='] = 0;
23 : */
24 : static const unsigned char base64_decode_table[256] = {
25 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
26 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
27 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
28 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f,
29 : 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80,
30 : 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
31 : 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
32 : 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80,
33 : 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
34 : 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
35 : 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
36 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
37 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
38 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
39 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
40 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
41 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
42 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
43 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
44 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
45 : 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
46 : 0x80, 0x80, 0x80, 0x80};
47 :
48 : bool
49 0 : base64_validate(const unsigned char *src, size_t len)
50 : {
51 0 : for (size_t i = 0; i < len; i++) {
52 0 : if (base64_decode_table[src[i]] == 0x80)
53 0 : return false;
54 : }
55 :
56 0 : return true;
57 : }
58 :
59 : /**
60 : * base64_encode - Base64 encode
61 : * @src: Data to be encoded
62 : * @len: Length of the data to be encoded
63 : * @out_len: Pointer to output length variable, or %NULL if not used
64 : * Returns: Allocated buffer of out_len bytes of encoded data,
65 : * or %NULL on failure
66 : *
67 : * Caller is responsible for freeing the returned buffer. Returned buffer is
68 : * nul terminated to make it easier to use as a C string. The nul terminator is
69 : * not included in out_len.
70 : */
71 : unsigned char *
72 0 : base64_encode(const unsigned char *src, size_t len, size_t *out_len)
73 : {
74 : unsigned char *out, *pos;
75 : const unsigned char *end, *in;
76 : size_t olen;
77 :
78 0 : olen = base64_encoded_len(len) + 1 /* for NUL termination */;
79 0 : if (olen < len)
80 0 : return NULL; /* integer overflow */
81 :
82 0 : out = malloc(olen);
83 0 : if (out == NULL)
84 0 : return NULL;
85 :
86 0 : end = src + len;
87 0 : in = src;
88 0 : pos = out;
89 0 : while (end - in >= 3) {
90 0 : *pos++ = base64_table[in[0] >> 2];
91 0 : *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
92 0 : *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
93 0 : *pos++ = base64_table[in[2] & 0x3f];
94 0 : in += 3;
95 : }
96 :
97 0 : if (end - in) {
98 0 : *pos++ = base64_table[in[0] >> 2];
99 0 : if (end - in == 1) {
100 0 : *pos++ = base64_table[(in[0] & 0x03) << 4];
101 0 : *pos++ = '=';
102 : } else {
103 0 : *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
104 0 : *pos++ = base64_table[(in[1] & 0x0f) << 2];
105 : }
106 0 : *pos++ = '=';
107 : }
108 :
109 0 : *pos = '\0';
110 0 : if (out_len)
111 0 : *out_len = (size_t)(pos - out);
112 0 : return out;
113 : }
114 :
115 : /**
116 : * base64_decode - Base64 decode
117 : * @src: Data to be decoded
118 : * @len: Length of the data to be decoded
119 : * @out_len: Pointer to output length variable
120 : * Returns: Allocated buffer of out_len bytes of decoded data,
121 : * or %NULL on failure
122 : *
123 : * Caller is responsible for freeing the returned buffer.
124 : */
125 : unsigned char *
126 3 : base64_decode(const unsigned char *src, size_t len, size_t *out_len)
127 : {
128 : unsigned char *out, *pos, block[4];
129 : size_t i, count, olen;
130 3 : int pad = 0;
131 :
132 3 : count = 0;
133 55 : for (i = 0; i < len; i++) {
134 52 : if (base64_decode_table[src[i]] != 0x80)
135 52 : count++;
136 : }
137 :
138 3 : if (count == 0 || count % 4)
139 0 : return NULL;
140 :
141 3 : olen = (count / 4 * 3) + 1;
142 3 : pos = out = malloc(olen);
143 3 : if (out == NULL)
144 0 : return NULL;
145 :
146 3 : count = 0;
147 52 : for (i = 0; i < len; i++) {
148 52 : unsigned char tmp = base64_decode_table[src[i]];
149 52 : if (tmp == 0x80)
150 0 : continue;
151 :
152 52 : if (src[i] == '=')
153 3 : pad++;
154 52 : block[count] = tmp;
155 52 : count++;
156 52 : if (count == 4) {
157 13 : *pos++ = (unsigned char)((block[0] << 2) | (block[1] >> 4));
158 13 : *pos++ = (unsigned char)((block[1] << 4) | (block[2] >> 2));
159 13 : *pos++ = (unsigned char)((block[2] << 6) | block[3]);
160 13 : count = 0;
161 13 : if (pad) {
162 3 : if (pad == 1)
163 3 : pos--;
164 0 : else if (pad == 2)
165 0 : pos -= 2;
166 : else {
167 : /* Invalid padding */
168 0 : free(out);
169 0 : return NULL;
170 : }
171 3 : break;
172 : }
173 : }
174 : }
175 3 : *pos = '\0';
176 :
177 3 : *out_len = (size_t)(pos - out);
178 3 : return out;
179 : }
|