PolarSSL v1.3.9
base64.c
Go to the documentation of this file.
1/*
2 * RFC 1521 base64 encoding/decoding
3 *
4 * Copyright (C) 2006-2014, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#if !defined(POLARSSL_CONFIG_FILE)
27#include "polarssl/config.h"
28#else
29#include POLARSSL_CONFIG_FILE
30#endif
31
32#if defined(POLARSSL_BASE64_C)
33
34#include "polarssl/base64.h"
35
36#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
37#include <basetsd.h>
38typedef UINT32 uint32_t;
39#else
40#include <inttypes.h>
41#endif
42
43#if defined(POLARSSL_PLATFORM_C)
44#include "polarssl/platform.h"
45#else
46#define polarssl_printf printf
47#endif
48
49static const unsigned char base64_enc_map[64] =
50{
51 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
52 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
53 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
54 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
55 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
56 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
57 '8', '9', '+', '/'
58};
59
60static const unsigned char base64_dec_map[128] =
61{
62 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
63 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
64 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
65 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
66 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
67 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
68 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
69 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
70 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
71 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
72 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
73 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
74 49, 50, 51, 127, 127, 127, 127, 127
75};
76
77/*
78 * Encode a buffer into base64 format
79 */
80int base64_encode( unsigned char *dst, size_t *dlen,
81 const unsigned char *src, size_t slen )
82{
83 size_t i, n;
84 int C1, C2, C3;
85 unsigned char *p;
86
87 if( slen == 0 )
88 return( 0 );
89
90 n = ( slen << 3 ) / 6;
91
92 switch( ( slen << 3 ) - ( n * 6 ) )
93 {
94 case 2: n += 3; break;
95 case 4: n += 2; break;
96 default: break;
97 }
98
99 if( *dlen < n + 1 )
100 {
101 *dlen = n + 1;
103 }
104
105 n = ( slen / 3 ) * 3;
106
107 for( i = 0, p = dst; i < n; i += 3 )
108 {
109 C1 = *src++;
110 C2 = *src++;
111 C3 = *src++;
112
113 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
114 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
115 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
116 *p++ = base64_enc_map[C3 & 0x3F];
117 }
118
119 if( i < slen )
120 {
121 C1 = *src++;
122 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
123
124 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
125 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
126
127 if( ( i + 1 ) < slen )
128 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
129 else *p++ = '=';
130
131 *p++ = '=';
132 }
133
134 *dlen = p - dst;
135 *p = 0;
136
137 return( 0 );
138}
139
140/*
141 * Decode a base64-formatted buffer
142 */
143int base64_decode( unsigned char *dst, size_t *dlen,
144 const unsigned char *src, size_t slen )
145{
146 size_t i, n;
147 uint32_t j, x;
148 unsigned char *p;
149
150 /* First pass: check for validity and get output length */
151 for( i = n = j = 0; i < slen; i++ )
152 {
153 /* Skip spaces before checking for EOL */
154 x = 0;
155 while( i < slen && src[i] == ' ' )
156 {
157 ++i;
158 ++x;
159 }
160
161 /* Spaces at end of buffer are OK */
162 if( i == slen )
163 break;
164
165 if( ( slen - i ) >= 2 &&
166 src[i] == '\r' && src[i + 1] == '\n' )
167 continue;
168
169 if( src[i] == '\n' )
170 continue;
171
172 /* Space inside a line is an error */
173 if( x != 0 )
175
176 if( src[i] == '=' && ++j > 2 )
178
179 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
181
182 if( base64_dec_map[src[i]] < 64 && j != 0 )
184
185 n++;
186 }
187
188 if( n == 0 )
189 return( 0 );
190
191 n = ( ( n * 6 ) + 7 ) >> 3;
192 n -= j;
193
194 if( dst == NULL || *dlen < n )
195 {
196 *dlen = n;
198 }
199
200 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
201 {
202 if( *src == '\r' || *src == '\n' || *src == ' ' )
203 continue;
204
205 j -= ( base64_dec_map[*src] == 64 );
206 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
207
208 if( ++n == 4 )
209 {
210 n = 0;
211 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
212 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
213 if( j > 2 ) *p++ = (unsigned char)( x );
214 }
215 }
216
217 *dlen = p - dst;
218
219 return( 0 );
220}
221
222#if defined(POLARSSL_SELF_TEST)
223
224#include <string.h>
225#include <stdio.h>
226
227static const unsigned char base64_test_dec[64] =
228{
229 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
230 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
231 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
232 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
233 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
234 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
235 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
236 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
237};
238
239static const unsigned char base64_test_enc[] =
240 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
241 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
242
243/*
244 * Checkup routine
245 */
246int base64_self_test( int verbose )
247{
248 size_t len;
249 const unsigned char *src;
250 unsigned char buffer[128];
251
252 if( verbose != 0 )
253 polarssl_printf( " Base64 encoding test: " );
254
255 len = sizeof( buffer );
256 src = base64_test_dec;
257
258 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
259 memcmp( base64_test_enc, buffer, 88 ) != 0 )
260 {
261 if( verbose != 0 )
262 polarssl_printf( "failed\n" );
263
264 return( 1 );
265 }
266
267 if( verbose != 0 )
268 polarssl_printf( "passed\n Base64 decoding test: " );
269
270 len = sizeof( buffer );
271 src = base64_test_enc;
272
273 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
274 memcmp( base64_test_dec, buffer, 64 ) != 0 )
275 {
276 if( verbose != 0 )
277 polarssl_printf( "failed\n" );
278
279 return( 1 );
280 }
281
282 if( verbose != 0 )
283 polarssl_printf( "passed\n\n" );
284
285 return( 0 );
286}
287
288#endif /* POLARSSL_SELF_TEST */
289
290#endif /* POLARSSL_BASE64_C */
RFC 1521 base64 encoding/decoding.
int base64_self_test(int verbose)
Checkup routine.
int base64_encode(unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen)
Encode a buffer into base64 format.
#define POLARSSL_ERR_BASE64_INVALID_CHARACTER
Invalid character in input.
Definition: base64.h:33
#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL
Output buffer too small.
Definition: base64.h:32
int base64_decode(unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen)
Decode a base64-formatted buffer.
Configuration options (set of defines)
PolarSSL Platform abstraction layer.
#define polarssl_printf