xref: /reactos/dll/3rdparty/mbedtls/base64.c (revision 682f85ad)
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 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  *
46  *  This file is part of mbed TLS (https://tls.mbed.org)
47  */
48 
49 #if !defined(MBEDTLS_CONFIG_FILE)
50 #include "mbedtls/config.h"
51 #else
52 #include MBEDTLS_CONFIG_FILE
53 #endif
54 
55 #if defined(MBEDTLS_BASE64_C)
56 
57 #include "mbedtls/base64.h"
58 
59 #include <stdint.h>
60 
61 #if defined(MBEDTLS_SELF_TEST)
62 #include <string.h>
63 #if defined(MBEDTLS_PLATFORM_C)
64 #include "mbedtls/platform.h"
65 #else
66 #include <stdio.h>
67 #define mbedtls_printf printf
68 #endif /* MBEDTLS_PLATFORM_C */
69 #endif /* MBEDTLS_SELF_TEST */
70 
71 static const unsigned char base64_enc_map[64] =
72 {
73     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
74     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
75     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
76     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
77     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
78     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
79     '8', '9', '+', '/'
80 };
81 
82 static const unsigned char base64_dec_map[128] =
83 {
84     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
85     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
86     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
87     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
88     127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
89      54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
90     127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
91       5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
92      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
93      25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
94      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
95      39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
96      49,  50,  51, 127, 127, 127, 127, 127
97 };
98 
99 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
100 
101 /*
102  * Encode a buffer into base64 format
103  */
104 int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
105                    const unsigned char *src, size_t slen )
106 {
107     size_t i, n;
108     int C1, C2, C3;
109     unsigned char *p;
110 
111     if( slen == 0 )
112     {
113         *olen = 0;
114         return( 0 );
115     }
116 
117     n = slen / 3 + ( slen % 3 != 0 );
118 
119     if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
120     {
121         *olen = BASE64_SIZE_T_MAX;
122         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
123     }
124 
125     n *= 4;
126 
127     if( ( dlen < n + 1 ) || ( NULL == dst ) )
128     {
129         *olen = n + 1;
130         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
131     }
132 
133     n = ( slen / 3 ) * 3;
134 
135     for( i = 0, p = dst; i < n; i += 3 )
136     {
137         C1 = *src++;
138         C2 = *src++;
139         C3 = *src++;
140 
141         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
142         *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
143         *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
144         *p++ = base64_enc_map[C3 & 0x3F];
145     }
146 
147     if( i < slen )
148     {
149         C1 = *src++;
150         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
151 
152         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
153         *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
154 
155         if( ( i + 1 ) < slen )
156              *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
157         else *p++ = '=';
158 
159         *p++ = '=';
160     }
161 
162     *olen = p - dst;
163     *p = 0;
164 
165     return( 0 );
166 }
167 
168 /*
169  * Decode a base64-formatted buffer
170  */
171 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
172                    const unsigned char *src, size_t slen )
173 {
174     size_t i, n;
175     uint32_t j, x;
176     unsigned char *p;
177 
178     /* First pass: check for validity and get output length */
179     for( i = n = j = 0; i < slen; i++ )
180     {
181         /* Skip spaces before checking for EOL */
182         x = 0;
183         while( i < slen && src[i] == ' ' )
184         {
185             ++i;
186             ++x;
187         }
188 
189         /* Spaces at end of buffer are OK */
190         if( i == slen )
191             break;
192 
193         if( ( slen - i ) >= 2 &&
194             src[i] == '\r' && src[i + 1] == '\n' )
195             continue;
196 
197         if( src[i] == '\n' )
198             continue;
199 
200         /* Space inside a line is an error */
201         if( x != 0 )
202             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
203 
204         if( src[i] == '=' && ++j > 2 )
205             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
206 
207         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
208             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
209 
210         if( base64_dec_map[src[i]] < 64 && j != 0 )
211             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
212 
213         n++;
214     }
215 
216     if( n == 0 )
217     {
218         *olen = 0;
219         return( 0 );
220     }
221 
222     /* The following expression is to calculate the following formula without
223      * risk of integer overflow in n:
224      *     n = ( ( n * 6 ) + 7 ) >> 3;
225      */
226     n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
227     n -= j;
228 
229     if( dst == NULL || dlen < n )
230     {
231         *olen = n;
232         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
233     }
234 
235    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
236    {
237         if( *src == '\r' || *src == '\n' || *src == ' ' )
238             continue;
239 
240         j -= ( base64_dec_map[*src] == 64 );
241         x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
242 
243         if( ++n == 4 )
244         {
245             n = 0;
246             if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
247             if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
248             if( j > 2 ) *p++ = (unsigned char)( x       );
249         }
250     }
251 
252     *olen = p - dst;
253 
254     return( 0 );
255 }
256 
257 #if defined(MBEDTLS_SELF_TEST)
258 
259 static const unsigned char base64_test_dec[64] =
260 {
261     0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
262     0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
263     0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
264     0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
265     0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
266     0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
267     0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
268     0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
269 };
270 
271 static const unsigned char base64_test_enc[] =
272     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
273     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
274 
275 /*
276  * Checkup routine
277  */
278 int mbedtls_base64_self_test( int verbose )
279 {
280     size_t len;
281     const unsigned char *src;
282     unsigned char buffer[128];
283 
284     if( verbose != 0 )
285         mbedtls_printf( "  Base64 encoding test: " );
286 
287     src = base64_test_dec;
288 
289     if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
290          memcmp( base64_test_enc, buffer, 88 ) != 0 )
291     {
292         if( verbose != 0 )
293             mbedtls_printf( "failed\n" );
294 
295         return( 1 );
296     }
297 
298     if( verbose != 0 )
299         mbedtls_printf( "passed\n  Base64 decoding test: " );
300 
301     src = base64_test_enc;
302 
303     if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
304          memcmp( base64_test_dec, buffer, 64 ) != 0 )
305     {
306         if( verbose != 0 )
307             mbedtls_printf( "failed\n" );
308 
309         return( 1 );
310     }
311 
312     if( verbose != 0 )
313         mbedtls_printf( "passed\n\n" );
314 
315     return( 0 );
316 }
317 
318 #endif /* MBEDTLS_SELF_TEST */
319 
320 #endif /* MBEDTLS_BASE64_C */
321