blob: c74351158dca8f30d2abd6be447da18398a3797f [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
78/*
79 * Encode a buffer into base64 format
80 */
Paul Bakker23986e52011-04-24 08:57:21 +000081int base64_encode( unsigned char *dst, size_t *dlen,
82 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000083{
Paul Bakker23986e52011-04-24 08:57:21 +000084 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000085 int C1, C2, C3;
86 unsigned char *p;
87
88 if( slen == 0 )
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +000089 {
90 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000091 return( 0 );
Manuel Pégourié-Gonnard65fc6a82015-01-28 16:49:26 +000092 }
Paul Bakker5121ce52009-01-03 21:22:43 +000093
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +020094 n = slen / 3 + ( slen % 3 != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +000095
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +020096 if( n > ( SIZE_T_MAX - 1 ) / 4 )
Paul Bakker5121ce52009-01-03 21:22:43 +000097 {
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +020098 *dlen = SIZE_T_MAX;
99 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000100 }
101
Manuel Pégourié-Gonnard48ec2c72015-09-30 16:30:28 +0200102 n *= 4;
103
Paul Bakker5121ce52009-01-03 21:22:43 +0000104 if( *dlen < n + 1 )
105 {
106 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +0000107 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000108 }
109
Paul Bakker66d5d072014-06-17 16:39:18 +0200110 n = ( slen / 3 ) * 3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000111
112 for( i = 0, p = dst; i < n; i += 3 )
113 {
114 C1 = *src++;
115 C2 = *src++;
116 C3 = *src++;
117
118 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
119 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
120 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
121 *p++ = base64_enc_map[C3 & 0x3F];
122 }
123
124 if( i < slen )
125 {
126 C1 = *src++;
Paul Bakker66d5d072014-06-17 16:39:18 +0200127 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000128
129 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
130 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
131
Paul Bakker66d5d072014-06-17 16:39:18 +0200132 if( ( i + 1 ) < slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000133 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
134 else *p++ = '=';
135
136 *p++ = '=';
137 }
138
139 *dlen = p - dst;
140 *p = 0;
141
142 return( 0 );
143}
144
145/*
146 * Decode a base64-formatted buffer
147 */
Paul Bakker23986e52011-04-24 08:57:21 +0000148int base64_decode( unsigned char *dst, size_t *dlen,
149 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000150{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000151 size_t i, n;
152 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000153 unsigned char *p;
154
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200155 /* First pass: check for validity and get output length */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200156 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000157 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200158 /* Skip spaces before checking for EOL */
159 x = 0;
160 while( i < slen && src[i] == ' ' )
161 {
162 ++i;
163 ++x;
164 }
165
166 /* Spaces at end of buffer are OK */
167 if( i == slen )
168 break;
169
Paul Bakker5121ce52009-01-03 21:22:43 +0000170 if( ( slen - i ) >= 2 &&
171 src[i] == '\r' && src[i + 1] == '\n' )
172 continue;
173
174 if( src[i] == '\n' )
175 continue;
176
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200177 /* Space inside a line is an error */
178 if( x != 0 )
179 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
180
Paul Bakker5121ce52009-01-03 21:22:43 +0000181 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000182 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
184 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000185 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
187 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000188 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000189
190 n++;
191 }
192
193 if( n == 0 )
Manuel Pégourié-Gonnard9bf29be2015-09-28 18:27:15 +0200194 {
195 *dlen = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 return( 0 );
Manuel Pégourié-Gonnard9bf29be2015-09-28 18:27:15 +0200197 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
Paul Bakker66d5d072014-06-17 16:39:18 +0200199 n = ( ( n * 6 ) + 7 ) >> 3;
Paul Bakkerd5983182014-07-04 13:50:31 +0200200 n -= j;
Paul Bakker5121ce52009-01-03 21:22:43 +0000201
Paul Bakkerf4a14272013-07-05 10:29:12 +0200202 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000203 {
204 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000205 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000206 }
207
208 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
209 {
Manuel Pégourié-Gonnard64938c62014-10-15 21:45:39 +0200210 if( *src == '\r' || *src == '\n' || *src == ' ' )
Paul Bakker5121ce52009-01-03 21:22:43 +0000211 continue;
212
213 j -= ( base64_dec_map[*src] == 64 );
Paul Bakker66d5d072014-06-17 16:39:18 +0200214 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
Paul Bakker5121ce52009-01-03 21:22:43 +0000215
216 if( ++n == 4 )
217 {
218 n = 0;
219 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
220 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
221 if( j > 2 ) *p++ = (unsigned char)( x );
222 }
223 }
224
225 *dlen = p - dst;
226
227 return( 0 );
228}
229
Paul Bakker40e46942009-01-03 21:51:57 +0000230#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
Paul Bakker5121ce52009-01-03 21:22:43 +0000232static const unsigned char base64_test_dec[64] =
233{
234 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
235 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
236 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
237 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
238 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
239 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
240 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
241 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
242};
243
244static const unsigned char base64_test_enc[] =
245 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
246 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
247
248/*
249 * Checkup routine
250 */
251int base64_self_test( int verbose )
252{
Paul Bakker23986e52011-04-24 08:57:21 +0000253 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200254 const unsigned char *src;
255 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000256
257 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100258 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000259
260 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200261 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000262
263 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200264 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000265 {
266 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100267 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000268
269 return( 1 );
270 }
271
272 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100273 polarssl_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000274
275 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200276 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000277
278 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
279 memcmp( base64_test_dec, buffer, 64 ) != 0 )
280 {
281 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100282 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
284 return( 1 );
285 }
286
287 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100288 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
290 return( 0 );
291}
292
Paul Bakker9af723c2014-05-01 13:03:14 +0200293#endif /* POLARSSL_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Paul Bakker9af723c2014-05-01 13:03:14 +0200295#endif /* POLARSSL_BASE64_C */