blob: d3814d63fde1af9fddc05b7e543444b00c26d3ba [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é-Gonnard085ab042015-01-23 11:06:27 +00006 * This file is part of mbed TLS (https://www.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 )
85 return( 0 );
86
Paul Bakker66d5d072014-06-17 16:39:18 +020087 n = ( slen << 3 ) / 6;
Paul Bakker5121ce52009-01-03 21:22:43 +000088
Paul Bakker66d5d072014-06-17 16:39:18 +020089 switch( ( slen << 3 ) - ( n * 6 ) )
Paul Bakker5121ce52009-01-03 21:22:43 +000090 {
91 case 2: n += 3; break;
92 case 4: n += 2; break;
93 default: break;
94 }
95
96 if( *dlen < n + 1 )
97 {
98 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +000099 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 }
101
Paul Bakker66d5d072014-06-17 16:39:18 +0200102 n = ( slen / 3 ) * 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000103
104 for( i = 0, p = dst; i < n; i += 3 )
105 {
106 C1 = *src++;
107 C2 = *src++;
108 C3 = *src++;
109
110 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
111 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
112 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
113 *p++ = base64_enc_map[C3 & 0x3F];
114 }
115
116 if( i < slen )
117 {
118 C1 = *src++;
Paul Bakker66d5d072014-06-17 16:39:18 +0200119 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
121 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
122 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
123
Paul Bakker66d5d072014-06-17 16:39:18 +0200124 if( ( i + 1 ) < slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000125 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
126 else *p++ = '=';
127
128 *p++ = '=';
129 }
130
131 *dlen = p - dst;
132 *p = 0;
133
134 return( 0 );
135}
136
137/*
138 * Decode a base64-formatted buffer
139 */
Paul Bakker23986e52011-04-24 08:57:21 +0000140int base64_decode( unsigned char *dst, size_t *dlen,
141 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000142{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000143 size_t i, n;
144 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000145 unsigned char *p;
146
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200147 /* First pass: check for validity and get output length */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200148 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000149 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200150 /* Skip spaces before checking for EOL */
151 x = 0;
152 while( i < slen && src[i] == ' ' )
153 {
154 ++i;
155 ++x;
156 }
157
158 /* Spaces at end of buffer are OK */
159 if( i == slen )
160 break;
161
Paul Bakker5121ce52009-01-03 21:22:43 +0000162 if( ( slen - i ) >= 2 &&
163 src[i] == '\r' && src[i + 1] == '\n' )
164 continue;
165
166 if( src[i] == '\n' )
167 continue;
168
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200169 /* Space inside a line is an error */
170 if( x != 0 )
171 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
172
Paul Bakker5121ce52009-01-03 21:22:43 +0000173 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000174 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
176 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000177 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000178
179 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000180 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000181
182 n++;
183 }
184
185 if( n == 0 )
186 return( 0 );
187
Paul Bakker66d5d072014-06-17 16:39:18 +0200188 n = ( ( n * 6 ) + 7 ) >> 3;
Paul Bakkerd5983182014-07-04 13:50:31 +0200189 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000190
Paul Bakkerf4a14272013-07-05 10:29:12 +0200191 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192 {
193 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000194 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000195 }
196
197 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
198 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200199 if( *src == '\r' || *src == '\n' || *src == ' ' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000200 continue;
201
202 j -= ( base64_dec_map[*src] == 64 );
Paul Bakker66d5d072014-06-17 16:39:18 +0200203 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
Paul Bakker5121ce52009-01-03 21:22:43 +0000204
205 if( ++n == 4 )
206 {
207 n = 0;
208 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
209 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
210 if( j > 2 ) *p++ = (unsigned char)( x );
211 }
212 }
213
214 *dlen = p - dst;
215
216 return( 0 );
217}
218
Paul Bakker40e46942009-01-03 21:51:57 +0000219#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000220
221#include <string.h>
222#include <stdio.h>
223
224static const unsigned char base64_test_dec[64] =
225{
226 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
227 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
228 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
229 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
230 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
231 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
232 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
233 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
234};
235
236static const unsigned char base64_test_enc[] =
237 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
238 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
239
240/*
241 * Checkup routine
242 */
243int base64_self_test( int verbose )
244{
Paul Bakker23986e52011-04-24 08:57:21 +0000245 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200246 const unsigned char *src;
247 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
249 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100250 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200253 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000254
255 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200256 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000257 {
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 Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
267 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200268 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
270 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
271 memcmp( base64_test_dec, buffer, 64 ) != 0 )
272 {
273 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100274 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000275
276 return( 1 );
277 }
278
279 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100280 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
282 return( 0 );
283}
284
Paul Bakker9af723c2014-05-01 13:03:14 +0200285#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000286
Paul Bakker9af723c2014-05-01 13:03:14 +0200287#endif /* POLARSSL_BASE64_C */