blob: 39a8323e8391e6c435bd0bd6150068b03c85f23e [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 Bakkerd5983182014-07-04 13:50:31 +0200175 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000176
Paul Bakkerf4a14272013-07-05 10:29:12 +0200177 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 {
179 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000180 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000181 }
182
183 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
184 {
185 if( *src == '\r' || *src == '\n' )
186 continue;
187
188 j -= ( base64_dec_map[*src] == 64 );
Paul Bakker66d5d072014-06-17 16:39:18 +0200189 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
Paul Bakker5121ce52009-01-03 21:22:43 +0000190
191 if( ++n == 4 )
192 {
193 n = 0;
194 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
195 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
196 if( j > 2 ) *p++ = (unsigned char)( x );
197 }
198 }
199
200 *dlen = p - dst;
201
202 return( 0 );
203}
204
Paul Bakker40e46942009-01-03 21:51:57 +0000205#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000206
207#include <string.h>
208#include <stdio.h>
209
210static const unsigned char base64_test_dec[64] =
211{
212 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
213 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
214 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
215 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
216 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
217 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
218 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
219 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
220};
221
222static const unsigned char base64_test_enc[] =
223 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
224 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
225
226/*
227 * Checkup routine
228 */
229int base64_self_test( int verbose )
230{
Paul Bakker23986e52011-04-24 08:57:21 +0000231 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200232 const unsigned char *src;
233 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
235 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100236 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
238 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200239 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000240
241 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200242 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000243 {
244 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100245 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000246
247 return( 1 );
248 }
249
250 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100251 polarssl_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000252
253 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200254 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000255
256 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
257 memcmp( base64_test_dec, buffer, 64 ) != 0 )
258 {
259 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100260 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000261
262 return( 1 );
263 }
264
265 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100266 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
268 return( 0 );
269}
270
Paul Bakker9af723c2014-05-01 13:03:14 +0200271#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000272
Paul Bakker9af723c2014-05-01 13:03:14 +0200273#endif /* POLARSSL_BASE64_C */