blob: d08c50cd646a5d1d276fb685a99b34dca571c0bb [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00004 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
5 *
6 * Copyright (C) 2009 Paul Bakker
Paul Bakker5121ce52009-01-03 21:22:43 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Paul Bakker40e46942009-01-03 21:51:57 +000023#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000024
Paul Bakker40e46942009-01-03 21:51:57 +000025#if defined(POLARSSL_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000026
Paul Bakker40e46942009-01-03 21:51:57 +000027#include "polarssl/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000028
29static const unsigned char base64_enc_map[64] =
30{
31 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
32 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
33 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
34 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
35 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
36 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
37 '8', '9', '+', '/'
38};
39
40static const unsigned char base64_dec_map[128] =
41{
42 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
43 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
44 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
45 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
46 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
47 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
48 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
49 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
50 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
51 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
52 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
53 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
54 49, 50, 51, 127, 127, 127, 127, 127
55};
56
57/*
58 * Encode a buffer into base64 format
59 */
60int base64_encode( unsigned char *dst, int *dlen,
61 unsigned char *src, int slen )
62{
63 int i, n;
64 int C1, C2, C3;
65 unsigned char *p;
66
67 if( slen == 0 )
68 return( 0 );
69
70 n = (slen << 3) / 6;
71
72 switch( (slen << 3) - (n * 6) )
73 {
74 case 2: n += 3; break;
75 case 4: n += 2; break;
76 default: break;
77 }
78
79 if( *dlen < n + 1 )
80 {
81 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +000082 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +000083 }
84
85 n = (slen / 3) * 3;
86
87 for( i = 0, p = dst; i < n; i += 3 )
88 {
89 C1 = *src++;
90 C2 = *src++;
91 C3 = *src++;
92
93 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
94 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
95 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
96 *p++ = base64_enc_map[C3 & 0x3F];
97 }
98
99 if( i < slen )
100 {
101 C1 = *src++;
102 C2 = ((i + 1) < slen) ? *src++ : 0;
103
104 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
105 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
106
107 if( (i + 1) < slen )
108 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
109 else *p++ = '=';
110
111 *p++ = '=';
112 }
113
114 *dlen = p - dst;
115 *p = 0;
116
117 return( 0 );
118}
119
120/*
121 * Decode a base64-formatted buffer
122 */
123int base64_decode( unsigned char *dst, int *dlen,
124 unsigned char *src, int slen )
125{
126 int i, j, n;
127 unsigned long x;
128 unsigned char *p;
129
130 for( i = j = n = 0; i < slen; i++ )
131 {
132 if( ( slen - i ) >= 2 &&
133 src[i] == '\r' && src[i + 1] == '\n' )
134 continue;
135
136 if( src[i] == '\n' )
137 continue;
138
139 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000140 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000141
142 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000143 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
145 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000146 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
148 n++;
149 }
150
151 if( n == 0 )
152 return( 0 );
153
154 n = ((n * 6) + 7) >> 3;
155
156 if( *dlen < n )
157 {
158 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000159 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000160 }
161
162 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
163 {
164 if( *src == '\r' || *src == '\n' )
165 continue;
166
167 j -= ( base64_dec_map[*src] == 64 );
168 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
169
170 if( ++n == 4 )
171 {
172 n = 0;
173 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
174 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
175 if( j > 2 ) *p++ = (unsigned char)( x );
176 }
177 }
178
179 *dlen = p - dst;
180
181 return( 0 );
182}
183
Paul Bakker40e46942009-01-03 21:51:57 +0000184#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000185
186#include <string.h>
187#include <stdio.h>
188
189static const unsigned char base64_test_dec[64] =
190{
191 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
192 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
193 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
194 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
195 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
196 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
197 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
198 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
199};
200
201static const unsigned char base64_test_enc[] =
202 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
203 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
204
205/*
206 * Checkup routine
207 */
208int base64_self_test( int verbose )
209{
210 int len;
211 unsigned char *src, buffer[128];
212
213 if( verbose != 0 )
214 printf( " Base64 encoding test: " );
215
216 len = sizeof( buffer );
217 src = (unsigned char *) base64_test_dec;
218
219 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
220 memcmp( base64_test_enc, buffer, 88 ) != 0 )
221 {
222 if( verbose != 0 )
223 printf( "failed\n" );
224
225 return( 1 );
226 }
227
228 if( verbose != 0 )
229 printf( "passed\n Base64 decoding test: " );
230
231 len = sizeof( buffer );
232 src = (unsigned char *) base64_test_enc;
233
234 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
235 memcmp( base64_test_dec, buffer, 64 ) != 0 )
236 {
237 if( verbose != 0 )
238 printf( "failed\n" );
239
240 return( 1 );
241 }
242
243 if( verbose != 0 )
244 printf( "passed\n\n" );
245
246 return( 0 );
247}
248
249#endif
250
251#endif