blob: 8601c94195e2163b1a04cb338bf41b49dbb60d5f [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Paul Bakker84f12b72010-07-18 10:13:04 +00004 * Copyright (C) 2006-2010, Brainspark B.V.
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
Paul Bakker84f12b72010-07-18 10:13:04 +00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakkerb96f1542010-07-18 20:36:00 +00008 *
Paul Bakker77b385e2009-07-28 17:23:11 +00009 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +000010 *
Paul Bakker5121ce52009-01-03 21:22:43 +000011 * 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
Paul Bakker40e46942009-01-03 21:51:57 +000026#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Paul Bakker40e46942009-01-03 21:51:57 +000028#if defined(POLARSSL_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Paul Bakker40e46942009-01-03 21:51:57 +000030#include "polarssl/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000031
32static const unsigned char base64_enc_map[64] =
33{
34 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
35 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
36 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
37 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
38 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
39 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
40 '8', '9', '+', '/'
41};
42
43static const unsigned char base64_dec_map[128] =
44{
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, 127, 127, 127, 127, 127, 127, 127,
48 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
49 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
50 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
51 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
52 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
53 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
54 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
55 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
56 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
57 49, 50, 51, 127, 127, 127, 127, 127
58};
59
60/*
61 * Encode a buffer into base64 format
62 */
Paul Bakker23986e52011-04-24 08:57:21 +000063int base64_encode( unsigned char *dst, size_t *dlen,
64 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000065{
Paul Bakker23986e52011-04-24 08:57:21 +000066 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000067 int C1, C2, C3;
68 unsigned char *p;
69
70 if( slen == 0 )
71 return( 0 );
72
73 n = (slen << 3) / 6;
74
75 switch( (slen << 3) - (n * 6) )
76 {
77 case 2: n += 3; break;
78 case 4: n += 2; break;
79 default: break;
80 }
81
82 if( *dlen < n + 1 )
83 {
84 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +000085 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +000086 }
87
88 n = (slen / 3) * 3;
89
90 for( i = 0, p = dst; i < n; i += 3 )
91 {
92 C1 = *src++;
93 C2 = *src++;
94 C3 = *src++;
95
96 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
97 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
98 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
99 *p++ = base64_enc_map[C3 & 0x3F];
100 }
101
102 if( i < slen )
103 {
104 C1 = *src++;
105 C2 = ((i + 1) < slen) ? *src++ : 0;
106
107 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
108 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
109
110 if( (i + 1) < slen )
111 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
112 else *p++ = '=';
113
114 *p++ = '=';
115 }
116
117 *dlen = p - dst;
118 *p = 0;
119
120 return( 0 );
121}
122
123/*
124 * Decode a base64-formatted buffer
125 */
Paul Bakker23986e52011-04-24 08:57:21 +0000126int base64_decode( unsigned char *dst, size_t *dlen,
127 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000128{
Paul Bakker23986e52011-04-24 08:57:21 +0000129 size_t i, j, n;
Paul Bakker5121ce52009-01-03 21:22:43 +0000130 unsigned long x;
131 unsigned char *p;
132
133 for( i = j = n = 0; i < slen; i++ )
134 {
135 if( ( slen - i ) >= 2 &&
136 src[i] == '\r' && src[i + 1] == '\n' )
137 continue;
138
139 if( src[i] == '\n' )
140 continue;
141
142 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000143 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
145 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000146 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000147
148 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000149 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000150
151 n++;
152 }
153
154 if( n == 0 )
155 return( 0 );
156
157 n = ((n * 6) + 7) >> 3;
158
159 if( *dlen < n )
160 {
161 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000162 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000163 }
164
165 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
166 {
167 if( *src == '\r' || *src == '\n' )
168 continue;
169
170 j -= ( base64_dec_map[*src] == 64 );
171 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
172
173 if( ++n == 4 )
174 {
175 n = 0;
176 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
177 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
178 if( j > 2 ) *p++ = (unsigned char)( x );
179 }
180 }
181
182 *dlen = p - dst;
183
184 return( 0 );
185}
186
Paul Bakker40e46942009-01-03 21:51:57 +0000187#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000188
189#include <string.h>
190#include <stdio.h>
191
192static const unsigned char base64_test_dec[64] =
193{
194 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
195 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
196 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
197 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
198 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
199 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
200 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
201 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
202};
203
204static const unsigned char base64_test_enc[] =
205 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
206 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
207
208/*
209 * Checkup routine
210 */
211int base64_self_test( int verbose )
212{
Paul Bakker23986e52011-04-24 08:57:21 +0000213 size_t len;
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 unsigned char *src, buffer[128];
215
216 if( verbose != 0 )
217 printf( " Base64 encoding test: " );
218
219 len = sizeof( buffer );
220 src = (unsigned char *) base64_test_dec;
221
222 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
223 memcmp( base64_test_enc, buffer, 88 ) != 0 )
224 {
225 if( verbose != 0 )
226 printf( "failed\n" );
227
228 return( 1 );
229 }
230
231 if( verbose != 0 )
232 printf( "passed\n Base64 decoding test: " );
233
234 len = sizeof( buffer );
235 src = (unsigned char *) base64_test_enc;
236
237 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
238 memcmp( base64_test_dec, buffer, 64 ) != 0 )
239 {
240 if( verbose != 0 )
241 printf( "failed\n" );
242
243 return( 1 );
244 }
245
246 if( verbose != 0 )
247 printf( "passed\n\n" );
248
249 return( 0 );
250}
251
252#endif
253
254#endif