]> git.zerfleddert.de Git - proxmark3-svn/blob - common/mbedtls/base64.c
Hitag fixes (#887)
[proxmark3-svn] / common / 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: GPL-2.0
6 *
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.
11 *
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.
16 *
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.
20 *
21 * This file is part of mbed TLS (https://tls.mbed.org)
22 */
23
24 #if !defined(MBEDTLS_CONFIG_FILE)
25 #include "mbedtls/config.h"
26 #else
27 #include MBEDTLS_CONFIG_FILE
28 #endif
29
30 #if defined(MBEDTLS_BASE64_C)
31
32 #include "mbedtls/base64.h"
33
34 #include <stdint.h>
35
36 #if defined(MBEDTLS_SELF_TEST)
37 #include <string.h>
38 #if defined(MBEDTLS_PLATFORM_C)
39 #include "mbedtls/platform.h"
40 #else
41 #include <stdio.h>
42 #define mbedtls_printf printf
43 #endif /* MBEDTLS_PLATFORM_C */
44 #endif /* MBEDTLS_SELF_TEST */
45
46 static const unsigned char base64_enc_map[64] =
47 {
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',
54 '8', '9', '+', '/'
55 };
56
57 static const unsigned char base64_dec_map[128] =
58 {
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
72 };
73
74 #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
75
76 /*
77 * Encode a buffer into base64 format
78 */
79 int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
80 const unsigned char *src, size_t slen )
81 {
82 size_t i, n;
83 int C1, C2, C3;
84 unsigned char *p;
85
86 if( slen == 0 )
87 {
88 *olen = 0;
89 return( 0 );
90 }
91
92 n = slen / 3 + ( slen % 3 != 0 );
93
94 if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
95 {
96 *olen = BASE64_SIZE_T_MAX;
97 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
98 }
99
100 n *= 4;
101
102 if( ( dlen < n + 1 ) || ( NULL == dst ) )
103 {
104 *olen = n + 1;
105 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
106 }
107
108 n = ( slen / 3 ) * 3;
109
110 for( i = 0, p = dst; i < n; i += 3 )
111 {
112 C1 = *src++;
113 C2 = *src++;
114 C3 = *src++;
115
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];
120 }
121
122 if( i < slen )
123 {
124 C1 = *src++;
125 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
126
127 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
128 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
129
130 if( ( i + 1 ) < slen )
131 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
132 else *p++ = '=';
133
134 *p++ = '=';
135 }
136
137 *olen = p - dst;
138 *p = 0;
139
140 return( 0 );
141 }
142
143 /*
144 * Decode a base64-formatted buffer
145 */
146 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
147 const unsigned char *src, size_t slen )
148 {
149 size_t i, n;
150 uint32_t j, x;
151 unsigned char *p;
152
153 /* First pass: check for validity and get output length */
154 for( i = n = j = 0; i < slen; i++ )
155 {
156 /* Skip spaces before checking for EOL */
157 x = 0;
158 while( i < slen && src[i] == ' ' )
159 {
160 ++i;
161 ++x;
162 }
163
164 /* Spaces at end of buffer are OK */
165 if( i == slen )
166 break;
167
168 if( ( slen - i ) >= 2 &&
169 src[i] == '\r' && src[i + 1] == '\n' )
170 continue;
171
172 if( src[i] == '\n' )
173 continue;
174
175 /* Space inside a line is an error */
176 if( x != 0 )
177 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
178
179 if( src[i] == '=' && ++j > 2 )
180 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
181
182 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
183 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
184
185 if( base64_dec_map[src[i]] < 64 && j != 0 )
186 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
187
188 n++;
189 }
190
191 if( n == 0 )
192 {
193 *olen = 0;
194 return( 0 );
195 }
196
197 /* The following expression is to calculate the following formula without
198 * risk of integer overflow in n:
199 * n = ( ( n * 6 ) + 7 ) >> 3;
200 */
201 n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
202 n -= j;
203
204 if( dst == NULL || dlen < n )
205 {
206 *olen = n;
207 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
208 }
209
210 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
211 {
212 if( *src == '\r' || *src == '\n' || *src == ' ' )
213 continue;
214
215 j -= ( base64_dec_map[*src] == 64 );
216 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
217
218 if( ++n == 4 )
219 {
220 n = 0;
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 );
224 }
225 }
226
227 *olen = p - dst;
228
229 return( 0 );
230 }
231
232 #if defined(MBEDTLS_SELF_TEST)
233
234 static const unsigned char base64_test_dec[64] =
235 {
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
244 };
245
246 static const unsigned char base64_test_enc[] =
247 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
248 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
249
250 /*
251 * Checkup routine
252 */
253 int mbedtls_base64_self_test( int verbose )
254 {
255 size_t len;
256 const unsigned char *src;
257 unsigned char buffer[128];
258
259 if( verbose != 0 )
260 mbedtls_printf( " Base64 encoding test: " );
261
262 src = base64_test_dec;
263
264 if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
265 memcmp( base64_test_enc, buffer, 88 ) != 0 )
266 {
267 if( verbose != 0 )
268 mbedtls_printf( "failed\n" );
269
270 return( 1 );
271 }
272
273 if( verbose != 0 )
274 mbedtls_printf( "passed\n Base64 decoding test: " );
275
276 src = base64_test_enc;
277
278 if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
279 memcmp( base64_test_dec, buffer, 64 ) != 0 )
280 {
281 if( verbose != 0 )
282 mbedtls_printf( "failed\n" );
283
284 return( 1 );
285 }
286
287 if( verbose != 0 )
288 mbedtls_printf( "passed\n\n" );
289
290 return( 0 );
291 }
292
293 #endif /* MBEDTLS_SELF_TEST */
294
295 #endif /* MBEDTLS_BASE64_C */
Impressum, Datenschutz