16c254da92cee6c9478f0b2a957c42e32e59d99f
[reactos.git] / reactos / dll / 3rdparty / mbedtls / base64.c
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 /*
73 * Encode a buffer into base64 format
74 */
75 int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
76 const unsigned char *src, size_t slen )
77 {
78 size_t i, n;
79 int C1, C2, C3;
80 unsigned char *p;
81
82 if( slen == 0 )
83 {
84 *olen = 0;
85 return( 0 );
86 }
87
88 n = ( slen << 3 ) / 6;
89
90 switch( ( slen << 3 ) - ( n * 6 ) )
91 {
92 case 2: n += 3; break;
93 case 4: n += 2; break;
94 default: break;
95 }
96
97 if( dlen < n + 1 )
98 {
99 *olen = n + 1;
100 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
101 }
102
103 n = ( slen / 3 ) * 3;
104
105 for( i = 0, p = dst; i < n; i += 3 )
106 {
107 C1 = *src++;
108 C2 = *src++;
109 C3 = *src++;
110
111 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
112 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
113 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
114 *p++ = base64_enc_map[C3 & 0x3F];
115 }
116
117 if( i < slen )
118 {
119 C1 = *src++;
120 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
121
122 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
123 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
124
125 if( ( i + 1 ) < slen )
126 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
127 else *p++ = '=';
128
129 *p++ = '=';
130 }
131
132 *olen = p - dst;
133 *p = 0;
134
135 return( 0 );
136 }
137
138 /*
139 * Decode a base64-formatted buffer
140 */
141 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
142 const unsigned char *src, size_t slen )
143 {
144 size_t i, n;
145 uint32_t j, x;
146 unsigned char *p;
147
148 /* First pass: check for validity and get output length */
149 for( i = n = j = 0; i < slen; i++ )
150 {
151 /* Skip spaces before checking for EOL */
152 x = 0;
153 while( i < slen && src[i] == ' ' )
154 {
155 ++i;
156 ++x;
157 }
158
159 /* Spaces at end of buffer are OK */
160 if( i == slen )
161 break;
162
163 if( ( slen - i ) >= 2 &&
164 src[i] == '\r' && src[i + 1] == '\n' )
165 continue;
166
167 if( src[i] == '\n' )
168 continue;
169
170 /* Space inside a line is an error */
171 if( x != 0 )
172 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
173
174 if( src[i] == '=' && ++j > 2 )
175 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
176
177 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
178 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
179
180 if( base64_dec_map[src[i]] < 64 && j != 0 )
181 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
182
183 n++;
184 }
185
186 if( n == 0 )
187 return( 0 );
188
189 n = ( ( n * 6 ) + 7 ) >> 3;
190 n -= j;
191
192 if( dst == NULL || dlen < n )
193 {
194 *olen = n;
195 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
196 }
197
198 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
199 {
200 if( *src == '\r' || *src == '\n' || *src == ' ' )
201 continue;
202
203 j -= ( base64_dec_map[*src] == 64 );
204 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
205
206 if( ++n == 4 )
207 {
208 n = 0;
209 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
210 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
211 if( j > 2 ) *p++ = (unsigned char)( x );
212 }
213 }
214
215 *olen = p - dst;
216
217 return( 0 );
218 }
219
220 #if defined(MBEDTLS_SELF_TEST)
221
222 static const unsigned char base64_test_dec[64] =
223 {
224 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
225 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
226 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
227 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
228 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
229 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
230 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
231 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
232 };
233
234 static const unsigned char base64_test_enc[] =
235 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
236 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
237
238 /*
239 * Checkup routine
240 */
241 int mbedtls_base64_self_test( int verbose )
242 {
243 size_t len;
244 const unsigned char *src;
245 unsigned char buffer[128];
246
247 if( verbose != 0 )
248 mbedtls_printf( " Base64 encoding test: " );
249
250 src = base64_test_dec;
251
252 if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
253 memcmp( base64_test_enc, buffer, 88 ) != 0 )
254 {
255 if( verbose != 0 )
256 mbedtls_printf( "failed\n" );
257
258 return( 1 );
259 }
260
261 if( verbose != 0 )
262 mbedtls_printf( "passed\n Base64 decoding test: " );
263
264 src = base64_test_enc;
265
266 if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
267 memcmp( base64_test_dec, buffer, 64 ) != 0 )
268 {
269 if( verbose != 0 )
270 mbedtls_printf( "failed\n" );
271
272 return( 1 );
273 }
274
275 if( verbose != 0 )
276 mbedtls_printf( "passed\n\n" );
277
278 return( 0 );
279 }
280
281 #endif /* MBEDTLS_SELF_TEST */
282
283 #endif /* MBEDTLS_BASE64_C */