2 * RFC 1521 base64 encoding/decoding
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 #if !defined(MBEDTLS_CONFIG_FILE)
25 #include "mbedtls/config.h"
27 #include MBEDTLS_CONFIG_FILE
30 #if defined(MBEDTLS_BASE64_C)
32 #include "mbedtls/base64.h"
36 #if defined(MBEDTLS_SELF_TEST)
38 #if defined(MBEDTLS_PLATFORM_C)
39 #include "mbedtls/platform.h"
42 #define mbedtls_printf printf
43 #endif /* MBEDTLS_PLATFORM_C */
44 #endif /* MBEDTLS_SELF_TEST */
46 static const unsigned char base64_enc_map
[64] =
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',
57 static const unsigned char base64_dec_map
[128] =
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
74 #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
77 * Encode a buffer into base64 format
79 int mbedtls_base64_encode( unsigned char *dst
, size_t dlen
, size_t *olen
,
80 const unsigned char *src
, size_t slen
)
92 n
= slen
/ 3 + ( slen
% 3 != 0 );
94 if( n
> ( BASE64_SIZE_T_MAX
- 1 ) / 4 )
96 *olen
= BASE64_SIZE_T_MAX
;
97 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
);
102 if( ( dlen
< n
+ 1 ) || ( NULL
== dst
) )
105 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
);
108 n
= ( slen
/ 3 ) * 3;
110 for( i
= 0, p
= dst
; i
< n
; i
+= 3 )
116 *p
++ = base64_enc_map
[(C1
>> 2) & 0x3F];
117 *p
++ = base64_enc_map
[(((C1
& 3) << 4) + (C2
>> 4)) & 0x3F];
118 *p
++ = base64_enc_map
[(((C2
& 15) << 2) + (C3
>> 6)) & 0x3F];
119 *p
++ = base64_enc_map
[C3
& 0x3F];
125 C2
= ( ( i
+ 1 ) < slen
) ? *src
++ : 0;
127 *p
++ = base64_enc_map
[(C1
>> 2) & 0x3F];
128 *p
++ = base64_enc_map
[(((C1
& 3) << 4) + (C2
>> 4)) & 0x3F];
130 if( ( i
+ 1 ) < slen
)
131 *p
++ = base64_enc_map
[((C2
& 15) << 2) & 0x3F];
144 * Decode a base64-formatted buffer
146 int mbedtls_base64_decode( unsigned char *dst
, size_t dlen
, size_t *olen
,
147 const unsigned char *src
, size_t slen
)
153 /* First pass: check for validity and get output length */
154 for( i
= n
= j
= 0; i
< slen
; i
++ )
156 /* Skip spaces before checking for EOL */
158 while( i
< slen
&& src
[i
] == ' ' )
164 /* Spaces at end of buffer are OK */
168 if( ( slen
- i
) >= 2 &&
169 src
[i
] == '\r' && src
[i
+ 1] == '\n' )
175 /* Space inside a line is an error */
177 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER
);
179 if( src
[i
] == '=' && ++j
> 2 )
180 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER
);
182 if( src
[i
] > 127 || base64_dec_map
[src
[i
]] == 127 )
183 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER
);
185 if( base64_dec_map
[src
[i
]] < 64 && j
!= 0 )
186 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER
);
197 /* The following expression is to calculate the following formula without
198 * risk of integer overflow in n:
199 * n = ( ( n * 6 ) + 7 ) >> 3;
201 n
= ( 6 * ( n
>> 3 ) ) + ( ( 6 * ( n
& 0x7 ) + 7 ) >> 3 );
204 if( dst
== NULL
|| dlen
< n
)
207 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
);
210 for( j
= 3, n
= x
= 0, p
= dst
; i
> 0; i
--, src
++ )
212 if( *src
== '\r' || *src
== '\n' || *src
== ' ' )
215 j
-= ( base64_dec_map
[*src
] == 64 );
216 x
= ( x
<< 6 ) | ( base64_dec_map
[*src
] & 0x3F );
221 if( j
> 0 ) *p
++ = (unsigned char)( x
>> 16 );
222 if( j
> 1 ) *p
++ = (unsigned char)( x
>> 8 );
223 if( j
> 2 ) *p
++ = (unsigned char)( x
);
232 #if defined(MBEDTLS_SELF_TEST)
234 static const unsigned char base64_test_dec
[64] =
236 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
237 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
238 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
239 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
240 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
241 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
242 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
243 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
246 static const unsigned char base64_test_enc
[] =
247 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
248 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
253 int mbedtls_base64_self_test( int verbose
)
256 const unsigned char *src
;
257 unsigned char buffer
[128];
260 mbedtls_printf( " Base64 encoding test: " );
262 src
= base64_test_dec
;
264 if( mbedtls_base64_encode( buffer
, sizeof( buffer
), &len
, src
, 64 ) != 0 ||
265 memcmp( base64_test_enc
, buffer
, 88 ) != 0 )
268 mbedtls_printf( "failed\n" );
274 mbedtls_printf( "passed\n Base64 decoding test: " );
276 src
= base64_test_enc
;
278 if( mbedtls_base64_decode( buffer
, sizeof( buffer
), &len
, src
, 88 ) != 0 ||
279 memcmp( base64_test_dec
, buffer
, 64 ) != 0 )
282 mbedtls_printf( "failed\n" );
288 mbedtls_printf( "passed\n\n" );
293 #endif /* MBEDTLS_SELF_TEST */
295 #endif /* MBEDTLS_BASE64_C */