1 /*
2  *  RFC 1521 base64 encoding/decoding
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  *
19  *  This file is part of mbed TLS (https://tls.mbed.org)
20  */
21 
22 #if !defined(MBEDTLS_CONFIG_FILE)
23 #include "mbedtls/config.h"
24 #else
25 #include MBEDTLS_CONFIG_FILE
26 #endif
27 
28 #if defined(MBEDTLS_BASE64_C)
29 
30 #include "mbedtls/base64.h"
31 
32 #include <stdint.h>
33 
34 #if defined(MBEDTLS_SELF_TEST)
35 #include <string.h>
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
38 #else
39 #include <stdio.h>
40 #define mbedtls_printf printf
41 #endif /* MBEDTLS_PLATFORM_C */
42 #endif /* MBEDTLS_SELF_TEST */
43 
44 static const unsigned char base64_enc_map[64] =
45 {
46     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
47     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
48     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
49     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
50     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
51     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
52     '8', '9', '+', '/'
53 };
54 
55 static const unsigned char base64_dec_map[128] =
56 {
57     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
58     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
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,  62, 127, 127, 127,  63,  52,  53,
62      54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
63     127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
64       5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
65      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
66      25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
67      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
68      39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
69      49,  50,  51, 127, 127, 127, 127, 127
70 };
71 
72 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
73 
74 /*
75  * Encode a buffer into base64 format
76  */
mbedtls_base64_encode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)77 int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
78                    const unsigned char *src, size_t slen )
79 {
80     size_t i, n;
81     int C1, C2, C3;
82     unsigned char *p;
83 
84     if( slen == 0 )
85     {
86         *olen = 0;
87         return( 0 );
88     }
89 
90     n = slen / 3 + ( slen % 3 != 0 );
91 
92     if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
93     {
94         *olen = BASE64_SIZE_T_MAX;
95         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
96     }
97 
98     n *= 4;
99 
100     if( ( dlen < n + 1 ) || ( NULL == dst ) )
101     {
102         *olen = n + 1;
103         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
104     }
105 
106     n = ( slen / 3 ) * 3;
107 
108     for( i = 0, p = dst; i < n; i += 3 )
109     {
110         C1 = *src++;
111         C2 = *src++;
112         C3 = *src++;
113 
114         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
115         *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
116         *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
117         *p++ = base64_enc_map[C3 & 0x3F];
118     }
119 
120     if( i < slen )
121     {
122         C1 = *src++;
123         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
124 
125         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
126         *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
127 
128         if( ( i + 1 ) < slen )
129              *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
130         else *p++ = '=';
131 
132         *p++ = '=';
133     }
134 
135     *olen = p - dst;
136     *p = 0;
137 
138     return( 0 );
139 }
140 
141 /*
142  * Decode a base64-formatted buffer
143  */
mbedtls_base64_decode(unsigned char * dst,size_t dlen,size_t * olen,const unsigned char * src,size_t slen)144 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
145                    const unsigned char *src, size_t slen )
146 {
147     size_t i, n;
148     uint32_t j, x;
149     unsigned char *p;
150 
151     /* First pass: check for validity and get output length */
152     for( i = n = j = 0; i < slen; i++ )
153     {
154         /* Skip spaces before checking for EOL */
155         x = 0;
156         while( i < slen && src[i] == ' ' )
157         {
158             ++i;
159             ++x;
160         }
161 
162         /* Spaces at end of buffer are OK */
163         if( i == slen )
164             break;
165 
166         if( ( slen - i ) >= 2 &&
167             src[i] == '\r' && src[i + 1] == '\n' )
168             continue;
169 
170         if( src[i] == '\n' )
171             continue;
172 
173         /* Space inside a line is an error */
174         if( x != 0 )
175             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
176 
177         if( src[i] == '=' && ++j > 2 )
178             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
179 
180         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
181             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
182 
183         if( base64_dec_map[src[i]] < 64 && j != 0 )
184             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
185 
186         n++;
187     }
188 
189     if( n == 0 )
190     {
191         *olen = 0;
192         return( 0 );
193     }
194 
195     /* The following expression is to calculate the following formula without
196      * risk of integer overflow in n:
197      *     n = ( ( n * 6 ) + 7 ) >> 3;
198      */
199     n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
200     n -= j;
201 
202     if( dst == NULL || dlen < n )
203     {
204         *olen = n;
205         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
206     }
207 
208    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
209    {
210         if( *src == '\r' || *src == '\n' || *src == ' ' )
211             continue;
212 
213         j -= ( base64_dec_map[*src] == 64 );
214         x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
215 
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     *olen = p - dst;
226 
227     return( 0 );
228 }
229 
230 #if defined(MBEDTLS_SELF_TEST)
231 
232 static 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 
244 static const unsigned char base64_test_enc[] =
245     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
246     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
247 
248 /*
249  * Checkup routine
250  */
mbedtls_base64_self_test(int verbose)251 int mbedtls_base64_self_test( int verbose )
252 {
253     size_t len;
254     const unsigned char *src;
255     unsigned char buffer[128];
256 
257     if( verbose != 0 )
258         mbedtls_printf( "  Base64 encoding test: " );
259 
260     src = base64_test_dec;
261 
262     if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
263          memcmp( base64_test_enc, buffer, 88 ) != 0 )
264     {
265         if( verbose != 0 )
266             mbedtls_printf( "failed\n" );
267 
268         return( 1 );
269     }
270 
271     if( verbose != 0 )
272         mbedtls_printf( "passed\n  Base64 decoding test: " );
273 
274     src = base64_test_enc;
275 
276     if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
277          memcmp( base64_test_dec, buffer, 64 ) != 0 )
278     {
279         if( verbose != 0 )
280             mbedtls_printf( "failed\n" );
281 
282         return( 1 );
283     }
284 
285     if( verbose != 0 )
286         mbedtls_printf( "passed\n\n" );
287 
288     return( 0 );
289 }
290 
291 #endif /* MBEDTLS_SELF_TEST */
292 
293 #endif /* MBEDTLS_BASE64_C */
294