new, smaller, faster and untested version of KLISP
[syren.git] / src / xyssl / base64.c
blobbe6c024148befa7621f9e5fc36941b35b442b23e
1 /*
2 * RFC 1521 base64 encoding/decoding
4 * Copyright (C) 2006-2007 Christophe Devine
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "xyssl/config.h"
23 #if defined(XYSSL_BASE64_C)
25 #include "xyssl/base64.h"
27 static const unsigned char base64_enc_map[64] =
29 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
30 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
31 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
32 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
33 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
34 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
35 '8', '9', '+', '/'
38 static const unsigned char base64_dec_map[128] =
40 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
41 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
42 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
43 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
44 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
45 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
46 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
47 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
48 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
49 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
50 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
51 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
52 49, 50, 51, 127, 127, 127, 127, 127
56 * Encode a buffer into base64 format
58 int base64_encode( unsigned char *dst, int *dlen,
59 unsigned char *src, int slen )
61 int i, n;
62 int C1, C2, C3;
63 unsigned char *p;
65 if( slen == 0 )
66 return( 0 );
68 n = (slen << 3) / 6;
70 switch( (slen << 3) - (n * 6) )
72 case 2: n += 3; break;
73 case 4: n += 2; break;
74 default: break;
77 if( *dlen < n + 1 )
79 *dlen = n + 1;
80 return( XYSSL_ERR_BASE64_BUFFER_TOO_SMALL );
83 n = (slen / 3) * 3;
85 for( i = 0, p = dst; i < n; i += 3 )
87 C1 = *src++;
88 C2 = *src++;
89 C3 = *src++;
91 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
92 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
93 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
94 *p++ = base64_enc_map[C3 & 0x3F];
97 if( i < slen )
99 C1 = *src++;
100 C2 = ((i + 1) < slen) ? *src++ : 0;
102 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
103 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
105 if( (i + 1) < slen )
106 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
107 else *p++ = '=';
109 *p++ = '=';
112 *dlen = p - dst;
113 *p = 0;
115 return( 0 );
119 * Decode a base64-formatted buffer
121 int base64_decode( unsigned char *dst, int *dlen,
122 unsigned char *src, int slen )
124 int i, j, n;
125 unsigned long x;
126 unsigned char *p;
128 for( i = j = n = 0; i < slen; i++ )
130 if( ( slen - i ) >= 2 &&
131 src[i] == '\r' && src[i + 1] == '\n' )
132 continue;
134 if( src[i] == '\n' )
135 continue;
137 if( src[i] == '=' && ++j > 2 )
138 return( XYSSL_ERR_BASE64_INVALID_CHARACTER );
140 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
141 return( XYSSL_ERR_BASE64_INVALID_CHARACTER );
143 if( base64_dec_map[src[i]] < 64 && j != 0 )
144 return( XYSSL_ERR_BASE64_INVALID_CHARACTER );
146 n++;
149 if( n == 0 )
150 return( 0 );
152 n = ((n * 6) + 7) >> 3;
154 if( *dlen < n )
156 *dlen = n;
157 return( XYSSL_ERR_BASE64_BUFFER_TOO_SMALL );
160 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
162 if( *src == '\r' || *src == '\n' )
163 continue;
165 j -= ( base64_dec_map[*src] == 64 );
166 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
168 if( ++n == 4 )
170 n = 0;
171 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
172 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
173 if( j > 2 ) *p++ = (unsigned char)( x );
177 *dlen = p - dst;
179 return( 0 );
182 #if defined(XYSSL_SELF_TEST)
184 #include <string.h>
185 #include <stdio.h>
187 static const unsigned char base64_test_dec[64] =
189 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
190 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
191 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
192 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
193 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
194 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
195 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
196 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
199 static const unsigned char base64_test_enc[] =
200 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
201 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
204 * Checkup routine
206 int base64_self_test( int verbose )
208 int len;
209 unsigned char *src, buffer[128];
211 if( verbose != 0 )
212 printf( " Base64 encoding test: " );
214 len = sizeof( buffer );
215 src = (unsigned char *) base64_test_dec;
217 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
218 memcmp( base64_test_enc, buffer, 88 ) != 0 )
220 if( verbose != 0 )
221 printf( "failed\n" );
223 return( 1 );
226 if( verbose != 0 )
227 printf( "passed\n Base64 decoding test: " );
229 len = sizeof( buffer );
230 src = (unsigned char *) base64_test_enc;
232 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
233 memcmp( base64_test_dec, buffer, 64 ) != 0 )
235 if( verbose != 0 )
236 printf( "failed\n" );
238 return( 1 );
241 if( verbose != 0 )
242 printf( "passed\n\n" );
244 return( 0 );
247 #endif
249 #endif