2 * RFC 1521 base64 encoding/decoding
4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
6 * This file is part of mbed TLS (https://tls.mbed.org)
8 * 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.
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.
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.
23 #if !defined(POLARSSL_CONFIG_FILE)
24 #include "polarssl/config.h"
26 #include POLARSSL_CONFIG_FILE
29 #if defined(POLARSSL_BASE64_C)
31 #include "polarssl/base64.h"
33 #if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
35 typedef UINT32
uint32_t;
40 #if defined(POLARSSL_SELF_TEST)
42 #if defined(POLARSSL_PLATFORM_C)
43 #include "polarssl/platform.h"
46 #define polarssl_printf printf
47 #endif /* POLARSSL_PLATFORM_C */
48 #endif /* POLARSSL_SELF_TEST */
50 static const unsigned char base64_enc_map
[64] =
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',
61 static const unsigned char base64_dec_map
[128] =
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
79 * Encode a buffer into base64 format
81 int base64_encode( unsigned char *dst
, size_t *dlen
,
82 const unsigned char *src
, size_t slen
)
94 n
= ( slen
<< 3 ) / 6;
96 switch( ( slen
<< 3 ) - ( n
* 6 ) )
98 case 2: n
+= 3; break;
99 case 4: n
+= 2; break;
106 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL
);
109 n
= ( slen
/ 3 ) * 3;
111 for( i
= 0, p
= dst
; i
< n
; i
+= 3 )
117 *p
++ = base64_enc_map
[(C1
>> 2) & 0x3F];
118 *p
++ = base64_enc_map
[(((C1
& 3) << 4) + (C2
>> 4)) & 0x3F];
119 *p
++ = base64_enc_map
[(((C2
& 15) << 2) + (C3
>> 6)) & 0x3F];
120 *p
++ = base64_enc_map
[C3
& 0x3F];
126 C2
= ( ( i
+ 1 ) < slen
) ? *src
++ : 0;
128 *p
++ = base64_enc_map
[(C1
>> 2) & 0x3F];
129 *p
++ = base64_enc_map
[(((C1
& 3) << 4) + (C2
>> 4)) & 0x3F];
131 if( ( i
+ 1 ) < slen
)
132 *p
++ = base64_enc_map
[((C2
& 15) << 2) & 0x3F];
145 * Decode a base64-formatted buffer
147 int base64_decode( unsigned char *dst
, size_t *dlen
,
148 const unsigned char *src
, size_t slen
)
154 /* First pass: check for validity and get output length */
155 for( i
= n
= j
= 0; i
< slen
; i
++ )
157 /* Skip spaces before checking for EOL */
159 while( i
< slen
&& src
[i
] == ' ' )
165 /* Spaces at end of buffer are OK */
169 if( ( slen
- i
) >= 2 &&
170 src
[i
] == '\r' && src
[i
+ 1] == '\n' )
176 /* Space inside a line is an error */
178 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER
);
180 if( src
[i
] == '=' && ++j
> 2 )
181 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER
);
183 if( src
[i
] > 127 || base64_dec_map
[src
[i
]] == 127 )
184 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER
);
186 if( base64_dec_map
[src
[i
]] < 64 && j
!= 0 )
187 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER
);
195 n
= ( ( n
* 6 ) + 7 ) >> 3;
198 if( dst
== NULL
|| *dlen
< n
)
201 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL
);
204 for( j
= 3, n
= x
= 0, p
= dst
; i
> 0; i
--, src
++ )
206 if( *src
== '\r' || *src
== '\n' || *src
== ' ' )
209 j
-= ( base64_dec_map
[*src
] == 64 );
210 x
= ( x
<< 6 ) | ( base64_dec_map
[*src
] & 0x3F );
215 if( j
> 0 ) *p
++ = (unsigned char)( x
>> 16 );
216 if( j
> 1 ) *p
++ = (unsigned char)( x
>> 8 );
217 if( j
> 2 ) *p
++ = (unsigned char)( x
);
226 #if defined(POLARSSL_SELF_TEST)
228 static const unsigned char base64_test_dec
[64] =
230 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
231 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
232 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
233 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
234 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
235 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
236 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
237 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
240 static const unsigned char base64_test_enc
[] =
241 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
242 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
247 int base64_self_test( int verbose
)
250 const unsigned char *src
;
251 unsigned char buffer
[128];
254 polarssl_printf( " Base64 encoding test: " );
256 len
= sizeof( buffer
);
257 src
= base64_test_dec
;
259 if( base64_encode( buffer
, &len
, src
, 64 ) != 0 ||
260 memcmp( base64_test_enc
, buffer
, 88 ) != 0 )
263 polarssl_printf( "failed\n" );
269 polarssl_printf( "passed\n Base64 decoding test: " );
271 len
= sizeof( buffer
);
272 src
= base64_test_enc
;
274 if( base64_decode( buffer
, &len
, src
, 88 ) != 0 ||
275 memcmp( base64_test_dec
, buffer
, 64 ) != 0 )
278 polarssl_printf( "failed\n" );
284 polarssl_printf( "passed\n\n" );
289 #endif /* POLARSSL_SELF_TEST */
291 #endif /* POLARSSL_BASE64_C */