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