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