blob: 5b1418bdd3258af8f3f1d4b4beaa9d95d35ef459 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Paul Bakker7dc4c442014-02-01 22:50:26 +01004 * Copyright (C) 2006-2014, 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
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020026#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000027#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020028#else
29#include POLARSSL_CONFIG_FILE
30#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakker40e46942009-01-03 21:51:57 +000032#if defined(POLARSSL_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Paul Bakker40e46942009-01-03 21:51:57 +000034#include "polarssl/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Paul Bakkerfa6a6202013-10-28 18:48:30 +010036#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker5c2364c2012-10-01 14:41:15 +000037#include <basetsd.h>
38typedef UINT32 uint32_t;
39#else
40#include <inttypes.h>
41#endif
42
Paul Bakker7dc4c442014-02-01 22:50:26 +010043#if defined(POLARSSL_PLATFORM_C)
44#include "polarssl/platform.h"
45#else
46#define polarssl_printf printf
47#endif
48
Paul Bakker5121ce52009-01-03 21:22:43 +000049static const unsigned char base64_enc_map[64] =
50{
51 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
52 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
53 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
54 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
55 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
56 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
57 '8', '9', '+', '/'
58};
59
60static const unsigned char base64_dec_map[128] =
61{
62 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
63 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
64 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
65 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
66 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
67 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
68 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
69 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
70 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
71 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
72 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
73 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
74 49, 50, 51, 127, 127, 127, 127, 127
75};
76
77/*
78 * Encode a buffer into base64 format
79 */
Paul Bakker23986e52011-04-24 08:57:21 +000080int base64_encode( unsigned char *dst, size_t *dlen,
81 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000082{
Paul Bakker23986e52011-04-24 08:57:21 +000083 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000084 int C1, C2, C3;
85 unsigned char *p;
86
87 if( slen == 0 )
88 return( 0 );
89
Paul Bakker66d5d072014-06-17 16:39:18 +020090 n = ( slen << 3 ) / 6;
Paul Bakker5121ce52009-01-03 21:22:43 +000091
Paul Bakker66d5d072014-06-17 16:39:18 +020092 switch( ( slen << 3 ) - ( n * 6 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000093 {
94 case 2: n += 3; break;
95 case 4: n += 2; break;
96 default: break;
97 }
98
99 if( *dlen < n + 1 )
100 {
101 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +0000102 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000103 }
104
Paul Bakker66d5d072014-06-17 16:39:18 +0200105 n = ( slen / 3 ) * 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
107 for( i = 0, p = dst; i < n; i += 3 )
108 {
109 C1 = *src++;
110 C2 = *src++;
111 C3 = *src++;
112
113 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
114 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
115 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
116 *p++ = base64_enc_map[C3 & 0x3F];
117 }
118
119 if( i < slen )
120 {
121 C1 = *src++;
Paul Bakker66d5d072014-06-17 16:39:18 +0200122 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000123
124 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
125 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
126
Paul Bakker66d5d072014-06-17 16:39:18 +0200127 if( ( i + 1 ) < slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
129 else *p++ = '=';
130
131 *p++ = '=';
132 }
133
134 *dlen = p - dst;
135 *p = 0;
136
137 return( 0 );
138}
139
140/*
141 * Decode a base64-formatted buffer
142 */
Paul Bakker23986e52011-04-24 08:57:21 +0000143int base64_decode( unsigned char *dst, size_t *dlen,
144 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000145{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000146 size_t i, n;
147 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000148 unsigned char *p;
149
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200150 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000151 {
152 if( ( slen - i ) >= 2 &&
153 src[i] == '\r' && src[i + 1] == '\n' )
154 continue;
155
156 if( src[i] == '\n' )
157 continue;
158
159 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000160 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000161
162 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000163 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000164
165 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000166 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000167
168 n++;
169 }
170
171 if( n == 0 )
172 return( 0 );
173
Paul Bakker66d5d072014-06-17 16:39:18 +0200174 n = ( ( n * 6 ) + 7 ) >> 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
Paul Bakkerf4a14272013-07-05 10:29:12 +0200176 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000177 {
178 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000179 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 }
181
182 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
183 {
184 if( *src == '\r' || *src == '\n' )
185 continue;
186
187 j -= ( base64_dec_map[*src] == 64 );
Paul Bakker66d5d072014-06-17 16:39:18 +0200188 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 if( ++n == 4 )
191 {
192 n = 0;
193 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
194 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
195 if( j > 2 ) *p++ = (unsigned char)( x );
196 }
197 }
198
199 *dlen = p - dst;
200
201 return( 0 );
202}
203
Paul Bakker40e46942009-01-03 21:51:57 +0000204#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000205
206#include <string.h>
207#include <stdio.h>
208
209static const unsigned char base64_test_dec[64] =
210{
211 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
212 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
213 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
214 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
215 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
216 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
217 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
218 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
219};
220
221static const unsigned char base64_test_enc[] =
222 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
223 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
224
225/*
226 * Checkup routine
227 */
228int base64_self_test( int verbose )
229{
Paul Bakker23986e52011-04-24 08:57:21 +0000230 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200231 const unsigned char *src;
232 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000233
234 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100235 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000236
237 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200238 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
240 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200241 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 {
243 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100244 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000245
246 return( 1 );
247 }
248
249 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100250 polarssl_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200253 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000254
255 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
256 memcmp( base64_test_dec, buffer, 64 ) != 0 )
257 {
258 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100259 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000260
261 return( 1 );
262 }
263
264 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100265 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
267 return( 0 );
268}
269
Paul Bakker9af723c2014-05-01 13:03:14 +0200270#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000271
Paul Bakker9af723c2014-05-01 13:03:14 +0200272#endif /* POLARSSL_BASE64_C */