blob: 4b823b2973564c47506c047ad6d56178e36569a2 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Paul Bakkerf4a14272013-07-05 10:29:12 +02004 * Copyright (C) 2006-2013, 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;
165
Paul Bakkerf4a14272013-07-05 10:29:12 +0200166 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000167 {
168 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000169 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000170 }
171
172 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
173 {
174 if( *src == '\r' || *src == '\n' )
175 continue;
176
177 j -= ( base64_dec_map[*src] == 64 );
178 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
179
180 if( ++n == 4 )
181 {
182 n = 0;
183 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
184 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
185 if( j > 2 ) *p++ = (unsigned char)( x );
186 }
187 }
188
189 *dlen = p - dst;
190
191 return( 0 );
192}
193
Paul Bakker40e46942009-01-03 21:51:57 +0000194#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
196#include <string.h>
197#include <stdio.h>
198
199static const unsigned char base64_test_dec[64] =
200{
201 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
202 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
203 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
204 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
205 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
206 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
207 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
208 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
209};
210
211static const unsigned char base64_test_enc[] =
212 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
213 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
214
215/*
216 * Checkup routine
217 */
218int base64_self_test( int verbose )
219{
Paul Bakker23986e52011-04-24 08:57:21 +0000220 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200221 const unsigned char *src;
222 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
224 if( verbose != 0 )
225 printf( " Base64 encoding test: " );
226
227 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200228 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000229
230 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200231 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 {
233 if( verbose != 0 )
234 printf( "failed\n" );
235
236 return( 1 );
237 }
238
239 if( verbose != 0 )
240 printf( "passed\n Base64 decoding test: " );
241
242 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200243 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
245 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
246 memcmp( base64_test_dec, buffer, 64 ) != 0 )
247 {
248 if( verbose != 0 )
249 printf( "failed\n" );
250
251 return( 1 );
252 }
253
254 if( verbose != 0 )
255 printf( "passed\n\n" );
256
257 return( 0 );
258}
259
260#endif
261
262#endif