blob: 2b43a940aef2afc5eb3c930f54de2fead47cb104 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Paul Bakker530927b2015-02-13 14:24:10 +01004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnarde12abf92015-01-28 17:13:45 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
Paul Bakker40e46942009-01-03 21:51:57 +000023#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000024
Paul Bakker40e46942009-01-03 21:51:57 +000025#if defined(POLARSSL_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000026
Paul Bakker40e46942009-01-03 21:51:57 +000027#include "polarssl/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000028
Paul Bakker5c2364c2012-10-01 14:41:15 +000029#ifdef _MSC_VER
30#include <basetsd.h>
31typedef UINT32 uint32_t;
32#else
33#include <inttypes.h>
34#endif
35
Paul Bakker5121ce52009-01-03 21:22:43 +000036static const unsigned char base64_enc_map[64] =
37{
38 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
39 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
40 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
41 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
42 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
43 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
44 '8', '9', '+', '/'
45};
46
47static const unsigned char base64_dec_map[128] =
48{
49 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
50 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
51 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
52 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
53 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
54 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
55 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
56 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
57 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
58 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
59 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
60 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
61 49, 50, 51, 127, 127, 127, 127, 127
62};
63
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +010064#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
65
Paul Bakker5121ce52009-01-03 21:22:43 +000066/*
67 * Encode a buffer into base64 format
68 */
Paul Bakker23986e52011-04-24 08:57:21 +000069int base64_encode( unsigned char *dst, size_t *dlen,
70 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000071{
Paul Bakker23986e52011-04-24 08:57:21 +000072 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000073 int C1, C2, C3;
74 unsigned char *p;
75
76 if( slen == 0 )
Manuel Pégourié-Gonnardf0974002015-01-28 16:49:26 +000077 {
78 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000079 return( 0 );
Manuel Pégourié-Gonnardf0974002015-01-28 16:49:26 +000080 }
Paul Bakker5121ce52009-01-03 21:22:43 +000081
Manuel Pégourié-Gonnarde4e4be72015-09-30 16:30:28 +020082 n = slen / 3 + ( slen % 3 != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +000083
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +010084 if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
Paul Bakker5121ce52009-01-03 21:22:43 +000085 {
Manuel Pégourié-Gonnard42571dd2015-10-05 15:23:11 +010086 *dlen = BASE64_SIZE_T_MAX;
Manuel Pégourié-Gonnarde4e4be72015-09-30 16:30:28 +020087 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +000088 }
89
Manuel Pégourié-Gonnarde4e4be72015-09-30 16:30:28 +020090 n *= 4;
91
Paul Bakker5121ce52009-01-03 21:22:43 +000092 if( *dlen < n + 1 )
93 {
94 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +000095 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +000096 }
97
98 n = (slen / 3) * 3;
99
100 for( i = 0, p = dst; i < n; i += 3 )
101 {
102 C1 = *src++;
103 C2 = *src++;
104 C3 = *src++;
105
106 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
107 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
108 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
109 *p++ = base64_enc_map[C3 & 0x3F];
110 }
111
112 if( i < slen )
113 {
114 C1 = *src++;
115 C2 = ((i + 1) < slen) ? *src++ : 0;
116
117 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
118 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
119
120 if( (i + 1) < slen )
121 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
122 else *p++ = '=';
123
124 *p++ = '=';
125 }
126
127 *dlen = p - dst;
128 *p = 0;
129
130 return( 0 );
131}
132
133/*
134 * Decode a base64-formatted buffer
135 */
Paul Bakker23986e52011-04-24 08:57:21 +0000136int base64_decode( unsigned char *dst, size_t *dlen,
137 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000138{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000139 size_t i, n;
140 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000141 unsigned char *p;
142
Manuel Pégourié-Gonnard0b12d5e2014-10-23 17:00:26 +0200143 /* First pass: check for validity and get output length */
144 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000145 {
Manuel Pégourié-Gonnard0b12d5e2014-10-23 17:00:26 +0200146 /* Skip spaces before checking for EOL */
147 x = 0;
148 while( i < slen && src[i] == ' ' )
149 {
150 ++i;
151 ++x;
152 }
153
154 /* Spaces at end of buffer are OK */
155 if( i == slen )
156 break;
157
Paul Bakker5121ce52009-01-03 21:22:43 +0000158 if( ( slen - i ) >= 2 &&
159 src[i] == '\r' && src[i + 1] == '\n' )
160 continue;
161
162 if( src[i] == '\n' )
163 continue;
164
Manuel Pégourié-Gonnard0b12d5e2014-10-23 17:00:26 +0200165 /* Space inside a line is an error */
166 if( x != 0 )
167 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
168
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000170 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000171
172 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000173 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000174
175 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000176 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000177
178 n++;
179 }
180
181 if( n == 0 )
Manuel Pégourié-Gonnardb73ce452015-09-28 18:27:15 +0200182 {
183 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000184 return( 0 );
Manuel Pégourié-Gonnardb73ce452015-09-28 18:27:15 +0200185 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
187 n = ((n * 6) + 7) >> 3;
Paul Bakkerbbc843f2014-07-08 18:18:38 +0200188 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( *dlen < n )
191 {
192 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000193 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 }
195
196 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
197 {
198 if( *src == '\r' || *src == '\n' )
199 continue;
200
201 j -= ( base64_dec_map[*src] == 64 );
202 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
203
204 if( ++n == 4 )
205 {
206 n = 0;
207 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
208 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
209 if( j > 2 ) *p++ = (unsigned char)( x );
210 }
211 }
212
213 *dlen = p - dst;
214
215 return( 0 );
216}
217
Paul Bakker40e46942009-01-03 21:51:57 +0000218#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
220#include <string.h>
221#include <stdio.h>
222
223static const unsigned char base64_test_dec[64] =
224{
225 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
226 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
227 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
228 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
229 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
230 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
231 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
232 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
233};
234
235static const unsigned char base64_test_enc[] =
236 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
237 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
238
239/*
240 * Checkup routine
241 */
242int base64_self_test( int verbose )
243{
Paul Bakker23986e52011-04-24 08:57:21 +0000244 size_t len;
Paul Bakkereae09db2013-06-06 12:35:54 +0200245 const unsigned char *src;
246 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000247
248 if( verbose != 0 )
249 printf( " Base64 encoding test: " );
250
251 len = sizeof( buffer );
Paul Bakkereae09db2013-06-06 12:35:54 +0200252 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000253
254 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakkereae09db2013-06-06 12:35:54 +0200255 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000256 {
257 if( verbose != 0 )
258 printf( "failed\n" );
259
260 return( 1 );
261 }
262
263 if( verbose != 0 )
264 printf( "passed\n Base64 decoding test: " );
265
266 len = sizeof( buffer );
Paul Bakkereae09db2013-06-06 12:35:54 +0200267 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000268
269 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
270 memcmp( base64_test_dec, buffer, 64 ) != 0 )
271 {
272 if( verbose != 0 )
273 printf( "failed\n" );
274
275 return( 1 );
276 }
277
278 if( verbose != 0 )
279 printf( "passed\n\n" );
280
281 return( 0 );
282}
283
284#endif
285
286#endif