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