blob: 21cd3a6ce306e7677474ce26aa874a2d3f01aa25 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
Manuel Pégourié-Gonnard860b5162015-01-28 17:12:07 +00006 * This file is part of mbed TLS (https://polarssl.org)
Paul Bakkerb96f1542010-07-18 20:36:00 +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
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020023#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker40e46942009-01-03 21:51:57 +000024#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020025#else
26#include POLARSSL_CONFIG_FILE
27#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000028
Paul Bakker40e46942009-01-03 21:51:57 +000029#if defined(POLARSSL_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000030
Paul Bakker40e46942009-01-03 21:51:57 +000031#include "polarssl/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000032
Paul Bakkerfa6a6202013-10-28 18:48:30 +010033#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker5c2364c2012-10-01 14:41:15 +000034#include <basetsd.h>
35typedef UINT32 uint32_t;
36#else
37#include <inttypes.h>
38#endif
39
Paul Bakker7dc4c442014-02-01 22:50:26 +010040#if defined(POLARSSL_PLATFORM_C)
41#include "polarssl/platform.h"
42#else
43#define polarssl_printf printf
44#endif
45
Paul Bakker5121ce52009-01-03 21:22:43 +000046static const unsigned char base64_enc_map[64] =
47{
48 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
49 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
50 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
51 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
52 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
53 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
54 '8', '9', '+', '/'
55};
56
57static const unsigned char base64_dec_map[128] =
58{
59 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
60 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
61 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
62 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
63 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
64 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
65 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
66 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
67 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
68 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
69 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
70 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
71 49, 50, 51, 127, 127, 127, 127, 127
72};
73
74/*
75 * Encode a buffer into base64 format
76 */
Paul Bakker23986e52011-04-24 08:57:21 +000077int base64_encode( unsigned char *dst, size_t *dlen,
78 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000079{
Paul Bakker23986e52011-04-24 08:57:21 +000080 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000081 int C1, C2, C3;
82 unsigned char *p;
83
84 if( slen == 0 )
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +000085 {
86 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000087 return( 0 );
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +000088 }
Paul Bakker5121ce52009-01-03 21:22:43 +000089
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
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200150 /* First pass: check for validity and get output length */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200151 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000152 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200153 /* Skip spaces before checking for EOL */
154 x = 0;
155 while( i < slen && src[i] == ' ' )
156 {
157 ++i;
158 ++x;
159 }
160
161 /* Spaces at end of buffer are OK */
162 if( i == slen )
163 break;
164
Paul Bakker5121ce52009-01-03 21:22:43 +0000165 if( ( slen - i ) >= 2 &&
166 src[i] == '\r' && src[i + 1] == '\n' )
167 continue;
168
169 if( src[i] == '\n' )
170 continue;
171
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200172 /* Space inside a line is an error */
173 if( x != 0 )
174 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
175
Paul Bakker5121ce52009-01-03 21:22:43 +0000176 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000177 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000178
179 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000180 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000181
182 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000183 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
185 n++;
186 }
187
188 if( n == 0 )
189 return( 0 );
190
Paul Bakker66d5d072014-06-17 16:39:18 +0200191 n = ( ( n * 6 ) + 7 ) >> 3;
Paul Bakkerd5983182014-07-04 13:50:31 +0200192 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000193
Paul Bakkerf4a14272013-07-05 10:29:12 +0200194 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000195 {
196 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000197 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198 }
199
200 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
201 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200202 if( *src == '\r' || *src == '\n' || *src == ' ' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000203 continue;
204
205 j -= ( base64_dec_map[*src] == 64 );
Paul Bakker66d5d072014-06-17 16:39:18 +0200206 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
208 if( ++n == 4 )
209 {
210 n = 0;
211 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
212 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
213 if( j > 2 ) *p++ = (unsigned char)( x );
214 }
215 }
216
217 *dlen = p - dst;
218
219 return( 0 );
220}
221
Paul Bakker40e46942009-01-03 21:51:57 +0000222#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000223
224#include <string.h>
225#include <stdio.h>
226
227static const unsigned char base64_test_dec[64] =
228{
229 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
230 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
231 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
232 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
233 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
234 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
235 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
236 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
237};
238
239static const unsigned char base64_test_enc[] =
240 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
241 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
242
243/*
244 * Checkup routine
245 */
246int base64_self_test( int verbose )
247{
Paul Bakker23986e52011-04-24 08:57:21 +0000248 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200249 const unsigned char *src;
250 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100253 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000254
255 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200256 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000257
258 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200259 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000260 {
261 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100262 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000263
264 return( 1 );
265 }
266
267 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100268 polarssl_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
270 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200271 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000272
273 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
274 memcmp( base64_test_dec, buffer, 64 ) != 0 )
275 {
276 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100277 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000278
279 return( 1 );
280 }
281
282 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100283 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000284
285 return( 0 );
286}
287
Paul Bakker9af723c2014-05-01 13:03:14 +0200288#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
Paul Bakker9af723c2014-05-01 13:03:14 +0200290#endif /* POLARSSL_BASE64_C */