blob: 1364713d9d44195263424924f62000a67e6f9216 [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
Paul Bakker5c2364c2012-10-01 14:41:15 +000032#ifdef _MSC_VER
33#include <basetsd.h>
34typedef UINT32 uint32_t;
35#else
36#include <inttypes.h>
37#endif
38
Paul Bakker5121ce52009-01-03 21:22:43 +000039static const unsigned char base64_enc_map[64] =
40{
41 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
42 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
43 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
44 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
45 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
46 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
47 '8', '9', '+', '/'
48};
49
50static const unsigned char base64_dec_map[128] =
51{
52 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
53 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
54 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
55 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
56 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
57 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
58 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
59 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
60 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
61 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
62 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
63 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
64 49, 50, 51, 127, 127, 127, 127, 127
65};
66
67/*
68 * Encode a buffer into base64 format
69 */
Paul Bakker23986e52011-04-24 08:57:21 +000070int base64_encode( unsigned char *dst, size_t *dlen,
71 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000072{
Paul Bakker23986e52011-04-24 08:57:21 +000073 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000074 int C1, C2, C3;
75 unsigned char *p;
76
77 if( slen == 0 )
78 return( 0 );
79
80 n = (slen << 3) / 6;
81
82 switch( (slen << 3) - (n * 6) )
83 {
84 case 2: n += 3; break;
85 case 4: n += 2; break;
86 default: break;
87 }
88
89 if( *dlen < n + 1 )
90 {
91 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +000092 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +000093 }
94
95 n = (slen / 3) * 3;
96
97 for( i = 0, p = dst; i < n; i += 3 )
98 {
99 C1 = *src++;
100 C2 = *src++;
101 C3 = *src++;
102
103 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
104 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
105 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
106 *p++ = base64_enc_map[C3 & 0x3F];
107 }
108
109 if( i < slen )
110 {
111 C1 = *src++;
112 C2 = ((i + 1) < slen) ? *src++ : 0;
113
114 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
115 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
116
117 if( (i + 1) < slen )
118 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
119 else *p++ = '=';
120
121 *p++ = '=';
122 }
123
124 *dlen = p - dst;
125 *p = 0;
126
127 return( 0 );
128}
129
130/*
131 * Decode a base64-formatted buffer
132 */
Paul Bakker23986e52011-04-24 08:57:21 +0000133int base64_decode( unsigned char *dst, size_t *dlen,
134 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000135{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000136 size_t i, n;
137 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 unsigned char *p;
139
140 for( i = j = n = 0; i < slen; i++ )
141 {
142 if( ( slen - i ) >= 2 &&
143 src[i] == '\r' && src[i + 1] == '\n' )
144 continue;
145
146 if( src[i] == '\n' )
147 continue;
148
149 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000150 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000151
152 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000153 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000154
155 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000156 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000157
158 n++;
159 }
160
161 if( n == 0 )
162 return( 0 );
163
164 n = ((n * 6) + 7) >> 3;
Paul Bakkerbbc843f2014-07-08 18:18:38 +0200165 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000166
167 if( *dlen < n )
168 {
169 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000170 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000171 }
172
173 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
174 {
175 if( *src == '\r' || *src == '\n' )
176 continue;
177
178 j -= ( base64_dec_map[*src] == 64 );
179 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
180
181 if( ++n == 4 )
182 {
183 n = 0;
184 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
185 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
186 if( j > 2 ) *p++ = (unsigned char)( x );
187 }
188 }
189
190 *dlen = p - dst;
191
192 return( 0 );
193}
194
Paul Bakker40e46942009-01-03 21:51:57 +0000195#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000196
197#include <string.h>
198#include <stdio.h>
199
200static const unsigned char base64_test_dec[64] =
201{
202 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
203 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
204 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
205 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
206 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
207 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
208 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
209 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
210};
211
212static const unsigned char base64_test_enc[] =
213 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
214 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
215
216/*
217 * Checkup routine
218 */
219int base64_self_test( int verbose )
220{
Paul Bakker23986e52011-04-24 08:57:21 +0000221 size_t len;
Paul Bakkereae09db2013-06-06 12:35:54 +0200222 const unsigned char *src;
223 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
225 if( verbose != 0 )
226 printf( " Base64 encoding test: " );
227
228 len = sizeof( buffer );
Paul Bakkereae09db2013-06-06 12:35:54 +0200229 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000230
231 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakkereae09db2013-06-06 12:35:54 +0200232 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000233 {
234 if( verbose != 0 )
235 printf( "failed\n" );
236
237 return( 1 );
238 }
239
240 if( verbose != 0 )
241 printf( "passed\n Base64 decoding test: " );
242
243 len = sizeof( buffer );
Paul Bakkereae09db2013-06-06 12:35:54 +0200244 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000245
246 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
247 memcmp( base64_test_dec, buffer, 64 ) != 0 )
248 {
249 if( verbose != 0 )
250 printf( "failed\n" );
251
252 return( 1 );
253 }
254
255 if( verbose != 0 )
256 printf( "passed\n\n" );
257
258 return( 0 );
259}
260
261#endif
262
263#endif