Branch data Line data Source code
1 : : /**
2 : : * \file lib/base64.c
3 : : *
4 : : * \brief Implementation of the Base64 encode/decode algorithim.
5 : : */
6 : :
7 : : /* This code was derived from the base64.c part of FFmpeg written
8 : : * by Ryan Martell. (rdm4@martellventures.com).
9 : : *
10 : : * Copyright (C) Ryan Martell. (rdm4@martellventures.com)
11 : : *
12 : : * Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
13 : : * Copyright (C) 2009-2015 fwknop developers and contributors. For a full
14 : : * list of contributors, see the file 'CREDITS'.
15 : : *
16 : : * License (GNU General Public License):
17 : : *
18 : : * This library is free software; you can redistribute it and/or
19 : : * modify it under the terms of the GNU General Public License
20 : : * as published by the Free Software Foundation; either version 2
21 : : * of the License, or (at your option) any later version.
22 : : *
23 : : * This program is distributed in the hope that it will be useful,
24 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 : : * GNU General Public License for more details.
27 : : *
28 : : * You should have received a copy of the GNU General Public License
29 : : * along with this program; if not, write to the Free Software
30 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 : : * USA
32 : : *
33 : : *****************************************************************************
34 : : */
35 : : #include "base64.h"
36 : : #include "fko_common.h"
37 : :
38 : : #if !AFL_FUZZING
39 : : static unsigned char map2[] =
40 : : {
41 : : 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
42 : : 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
43 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
44 : : 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
45 : : 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
46 : : 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
47 : : 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
48 : : 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
49 : : 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
50 : : 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
51 : : };
52 : : #endif
53 : :
54 : : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
55 : : #include "cunit_common.h"
56 : : DECLARE_TEST_SUITE(base64_test, "Utility functions test suite");
57 : : #endif /* LCOV_EXCL_STOP */
58 : :
59 : : int
60 : 2949918 : b64_decode(const char *in, unsigned char *out)
61 : : {
62 : : int i;
63 : 2949918 : unsigned char *dst = out;
64 : : #if ! AFL_FUZZING
65 : : int v;
66 : : #endif
67 : :
68 : : #if AFL_FUZZING
69 : : /* short circuit base64 decoding in AFL fuzzing mode - just copy
70 : : * data as-is.
71 : : */
72 : : for (i = 0; in[i]; i++)
73 : : *dst++ = in[i];
74 : : #else
75 : 2949918 : v = 0;
76 [ + + ]: 583932011 : for (i = 0; in[i] && in[i] != '='; i++) {
77 : 580993273 : unsigned int index= in[i]-43;
78 : :
79 [ + + ][ + + ]: 580993273 : if (index>=(sizeof(map2)/sizeof(map2[0])) || map2[index] == 0xff)
80 : : return(-1);
81 : :
82 : 580982093 : v = (v << 6) + map2[index];
83 : :
84 [ + + ]: 580982093 : if (i & 3)
85 : 434823139 : *dst++ = v >> (6 - 2 * (i & 3));
86 : : }
87 : : #endif
88 : :
89 : 2938738 : *dst = '\0';
90 : :
91 : 2938738 : return(dst - out);
92 : : }
93 : :
94 : : /*****************************************************************************
95 : : * b64_encode: Stolen from VLC's http.c
96 : : * Simplified by michael
97 : : * fixed edge cases and made it work from data (vs. strings) by ryan.
98 : : *****************************************************************************
99 : : */
100 : : int
101 : 4019443 : b64_encode(unsigned char *in, char *out, int in_len)
102 : : {
103 : : static const char b64[] =
104 : : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
105 : 4019443 : unsigned i_bits = 0;
106 : 4019443 : int i_shift = 0;
107 : 4019443 : int bytes_remaining = in_len;
108 : :
109 : 4019443 : char *dst = out;
110 : :
111 [ + + ]: 4019443 : if (in_len > 0) { /* Special edge case, what should we really do here? */
112 [ + + ]: 368303623 : while (bytes_remaining) {
113 : 364284181 : i_bits = (i_bits << 8) + *in++;
114 : 364284181 : bytes_remaining--;
115 : 487050632 : i_shift += 8;
116 : :
117 : : do {
118 : 487050632 : *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
119 : 487050632 : i_shift -= 6;
120 [ + + ][ + + ]: 491070074 : } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
121 : : }
122 [ + + ]: 8034614 : while ((dst - out) & 3)
123 : 4015172 : *dst++ = '=';
124 : : }
125 : :
126 : 4019443 : *dst = '\0';
127 : :
128 : 4019443 : return(dst - out);
129 : : }
130 : :
131 : : /* Strip trailing equals ("=") charcters from a base64-encoded
132 : : * message digest.
133 : : */
134 : : void
135 : 4018994 : strip_b64_eq(char *data)
136 : : {
137 : : char *ndx;
138 : :
139 [ + + ]: 4018994 : if((ndx = strchr(data, '=')) != NULL)
140 : 3742588 : *ndx = '\0';
141 : 4018994 : }
142 : :
143 : : #ifdef HAVE_C_UNIT_TESTS /* LCOV_EXCL_START */
144 : : DECLARE_UTEST(test_base64_encode, "test base64 encoding functions")
145 : : {
146 : : char test_str[32] = {0};
147 : : char test_out[32] = {0};
148 : : char expected_out1[32] = {0};
149 : : char expected_out2[32] = {0};
150 : : char expected_out3[32] = {0};
151 : : char expected_out4[32] = {0};
152 : : char expected_out5[32] = {0};
153 : : char expected_out6[32] = {0};
154 : : char expected_out7[32] = {0};
155 : :
156 : : strcpy(expected_out1, "");
157 : : strcpy(expected_out2, "Zg==");
158 : : strcpy(expected_out3, "Zm8=");
159 : : strcpy(expected_out4, "Zm9v");
160 : : strcpy(expected_out5, "Zm9vYg==");
161 : : strcpy(expected_out6, "Zm9vYmE=");
162 : : strcpy(expected_out7, "Zm9vYmFy");
163 : :
164 : : strcpy(test_str, "");
165 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
166 : : CU_ASSERT(strcmp(test_out, expected_out1) == 0);
167 : :
168 : : strcpy(test_str, "f");
169 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
170 : : CU_ASSERT(strcmp(test_out, expected_out2) == 0);
171 : :
172 : : strcpy(test_str, "fo");
173 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
174 : : CU_ASSERT(strcmp(test_out, expected_out3) == 0);
175 : :
176 : : strcpy(test_str, "foo");
177 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
178 : : CU_ASSERT(strcmp(test_out, expected_out4) == 0);
179 : :
180 : : strcpy(test_str, "foob");
181 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
182 : : CU_ASSERT(strcmp(test_out, expected_out5) == 0);
183 : :
184 : : strcpy(test_str, "fooba");
185 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
186 : : CU_ASSERT(strcmp(test_out, expected_out6) == 0);
187 : :
188 : : strcpy(test_str, "foobar");
189 : : b64_encode((unsigned char *)test_str, test_out, strlen(test_str));
190 : : CU_ASSERT(strcmp(test_out, expected_out7) == 0);
191 : :
192 : : }
193 : :
194 : : DECLARE_UTEST(test_base64_decode, "test base64 decoding functions")
195 : : {
196 : : char test_str[32] = {0};
197 : : char test_out[32] = {0};
198 : : char expected_out1[32] = {0};
199 : : char expected_out2[32] = {0};
200 : : char expected_out3[32] = {0};
201 : : char expected_out4[32] = {0};
202 : : char expected_out5[32] = {0};
203 : : char expected_out6[32] = {0};
204 : : char expected_out7[32] = {0};
205 : :
206 : : strcpy(expected_out1, "");
207 : : strcpy(expected_out2, "f");
208 : : strcpy(expected_out3, "fo");
209 : : strcpy(expected_out4, "foo");
210 : : strcpy(expected_out5, "foob");
211 : : strcpy(expected_out6, "fooba");
212 : : strcpy(expected_out7, "foobar");
213 : :
214 : : strcpy(test_str, "");
215 : : b64_decode(test_str, (unsigned char *)test_out);
216 : : CU_ASSERT(strcmp(test_out, expected_out1) == 0);
217 : :
218 : : strcpy(test_str, "Zg==");
219 : : b64_decode(test_str, (unsigned char *)test_out);
220 : : CU_ASSERT(strcmp(test_out, expected_out2) == 0);
221 : :
222 : : strcpy(test_str, "Zm8=");
223 : : b64_decode(test_str, (unsigned char *)test_out);
224 : : CU_ASSERT(strcmp(test_out, expected_out3) == 0);
225 : :
226 : : strcpy(test_str, "Zm9v");
227 : : b64_decode(test_str, (unsigned char *)test_out);
228 : : CU_ASSERT(strcmp(test_out, expected_out4) == 0);
229 : :
230 : : strcpy(test_str, "Zm9vYg==");
231 : : b64_decode(test_str, (unsigned char *)test_out);
232 : : CU_ASSERT(strcmp(test_out, expected_out5) == 0);
233 : :
234 : : strcpy(test_str, "Zm9vYmE=");
235 : : b64_decode(test_str, (unsigned char *)test_out);
236 : : CU_ASSERT(strcmp(test_out, expected_out6) == 0);
237 : :
238 : : strcpy(test_str, "Zm9vYmFy");
239 : : b64_decode(test_str, (unsigned char *)test_out);
240 : : CU_ASSERT(strcmp(test_out, expected_out7) == 0);
241 : : }
242 : :
243 : : int register_base64_test(void)
244 : : {
245 : : ts_init(&TEST_SUITE(base64_test), TEST_SUITE_DESCR(base64_test), NULL, NULL);
246 : : ts_add_utest(&TEST_SUITE(base64_test), UTEST_FCT(test_base64_encode), UTEST_DESCR(test_base64_encode));
247 : : ts_add_utest(&TEST_SUITE(base64_test), UTEST_FCT(test_base64_decode), UTEST_DESCR(test_base64_decode));
248 : :
249 : : return register_ts(&TEST_SUITE(base64_test));
250 : : }
251 : : #endif /* LCOV_EXCL_STOP */
252 : : /***EOF***/
|