blob: ba6926083b15b901ba002673f1ad371ed8cd3df0 [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é-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.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
Rich Evans00ab4702015-02-06 13:43:58 +000040#if defined(POLARSSL_SELF_TEST)
41#include <string.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010042#if defined(POLARSSL_PLATFORM_C)
43#include "polarssl/platform.h"
44#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#define polarssl_printf printf
Rich Evans00ab4702015-02-06 13:43:58 +000047#endif /* POLARSSL_PLATFORM_C */
48#endif /* POLARSSL_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010049
Paul Bakker5121ce52009-01-03 21:22:43 +000050static const unsigned char base64_enc_map[64] =
51{
52 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
53 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
54 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
55 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
56 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
57 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
58 '8', '9', '+', '/'
59};
60
61static const unsigned char base64_dec_map[128] =
62{
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, 127, 127, 127, 127, 127, 127, 127,
67 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
68 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
69 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
70 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
71 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
72 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
73 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
74 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
75 49, 50, 51, 127, 127, 127, 127, 127
76};
77
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +010078#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
79
Paul Bakker5121ce52009-01-03 21:22:43 +000080/*
81 * Encode a buffer into base64 format
82 */
Paul Bakker23986e52011-04-24 08:57:21 +000083int base64_encode( unsigned char *dst, size_t *dlen,
84 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000085{
Paul Bakker23986e52011-04-24 08:57:21 +000086 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000087 int C1, C2, C3;
88 unsigned char *p;
89
90 if( slen == 0 )
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +000091 {
92 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000093 return( 0 );
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +000094 }
Paul Bakker5121ce52009-01-03 21:22:43 +000095
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +020096 n = slen / 3 + ( slen % 3 != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +000097
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +010098 if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
Paul Bakker5121ce52009-01-03 21:22:43 +000099 {
Manuel Pégourié-Gonnardfa647a72015-10-05 15:23:11 +0100100 *dlen = BASE64_SIZE_T_MAX;
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +0200101 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000102 }
103
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +0200104 n *= 4;
105
Paul Bakker5121ce52009-01-03 21:22:43 +0000106 if( *dlen < n + 1 )
107 {
108 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +0000109 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 }
111
Paul Bakker66d5d072014-06-17 16:39:18 +0200112 n = ( slen / 3 ) * 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
114 for( i = 0, p = dst; i < n; i += 3 )
115 {
116 C1 = *src++;
117 C2 = *src++;
118 C3 = *src++;
119
120 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
121 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
122 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
123 *p++ = base64_enc_map[C3 & 0x3F];
124 }
125
126 if( i < slen )
127 {
128 C1 = *src++;
Paul Bakker66d5d072014-06-17 16:39:18 +0200129 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
131 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
132 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
133
Paul Bakker66d5d072014-06-17 16:39:18 +0200134 if( ( i + 1 ) < slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000135 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
136 else *p++ = '=';
137
138 *p++ = '=';
139 }
140
141 *dlen = p - dst;
142 *p = 0;
143
144 return( 0 );
145}
146
147/*
148 * Decode a base64-formatted buffer
149 */
Paul Bakker23986e52011-04-24 08:57:21 +0000150int base64_decode( unsigned char *dst, size_t *dlen,
151 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000152{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000153 size_t i, n;
154 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000155 unsigned char *p;
156
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200157 /* First pass: check for validity and get output length */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200158 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000159 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200160 /* Skip spaces before checking for EOL */
161 x = 0;
162 while( i < slen && src[i] == ' ' )
163 {
164 ++i;
165 ++x;
166 }
167
168 /* Spaces at end of buffer are OK */
169 if( i == slen )
170 break;
171
Paul Bakker5121ce52009-01-03 21:22:43 +0000172 if( ( slen - i ) >= 2 &&
173 src[i] == '\r' && src[i + 1] == '\n' )
174 continue;
175
176 if( src[i] == '\n' )
177 continue;
178
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200179 /* Space inside a line is an error */
180 if( x != 0 )
181 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
182
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000184 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000185
186 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000187 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000188
189 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000190 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
192 n++;
193 }
194
195 if( n == 0 )
Manuel Pégourié-Gonnard9bf29be2015-09-28 18:27:15 +0200196 {
197 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000198 return( 0 );
Manuel Pégourié-Gonnard9bf29be2015-09-28 18:27:15 +0200199 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000200
Simon Butcher746edf42017-02-02 08:46:53 +0000201 /* The following expression is to calculate the following formula without
202 * risk of integer overflow in n:
203 * n = ( ( n * 6 ) + 7 ) >> 3;
204 */
Andres AG59abd302017-01-18 17:21:03 +0000205 n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
Paul Bakkerd5983182014-07-04 13:50:31 +0200206 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000207
Paul Bakkerf4a14272013-07-05 10:29:12 +0200208 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209 {
210 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000211 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 }
213
214 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
215 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200216 if( *src == '\r' || *src == '\n' || *src == ' ' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 continue;
218
219 j -= ( base64_dec_map[*src] == 64 );
Paul Bakker66d5d072014-06-17 16:39:18 +0200220 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 if( ++n == 4 )
223 {
224 n = 0;
225 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
226 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
227 if( j > 2 ) *p++ = (unsigned char)( x );
228 }
229 }
230
231 *dlen = p - dst;
232
233 return( 0 );
234}
235
Paul Bakker40e46942009-01-03 21:51:57 +0000236#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
Paul Bakker5121ce52009-01-03 21:22:43 +0000238static const unsigned char base64_test_dec[64] =
239{
240 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
241 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
242 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
243 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
244 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
245 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
246 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
247 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
248};
249
250static const unsigned char base64_test_enc[] =
251 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
252 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
253
254/*
255 * Checkup routine
256 */
257int base64_self_test( int verbose )
258{
Paul Bakker23986e52011-04-24 08:57:21 +0000259 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200260 const unsigned char *src;
261 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000262
263 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100264 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000265
266 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200267 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000268
269 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200270 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000271 {
272 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100273 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000274
275 return( 1 );
276 }
277
278 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100279 polarssl_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000280
281 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200282 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
284 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
285 memcmp( base64_test_dec, buffer, 64 ) != 0 )
286 {
287 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100288 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
290 return( 1 );
291 }
292
293 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100294 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
296 return( 0 );
297}
298
Paul Bakker9af723c2014-05-01 13:03:14 +0200299#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
Paul Bakker9af723c2014-05-01 13:03:14 +0200301#endif /* POLARSSL_BASE64_C */