initial commit; it works
[psslcertgen.git] / src / libpolarssl / base64.c
blob0f8b5b2bd6bbe5e5fc43afe057ec42af3ff0f942
1 /*
2 * RFC 1521 base64 encoding/decoding
4 * Copyright (C) 2006-2010, Brainspark B.V.
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
9 * All rights reserved.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #if defined(POLARSSL_BASE64_C)
30 #include "base64.h"
32 #ifdef _MSC_VER
33 #include <basetsd.h>
34 typedef UINT32 uint32_t;
35 #else
36 #include <inttypes.h>
37 #endif
39 static const unsigned char base64_enc_map[64] =
41 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
42 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
43 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
44 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
45 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
46 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
47 '8', '9', '+', '/'
50 static const unsigned char base64_dec_map[128] =
52 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
53 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
54 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
55 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
56 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
57 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
58 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
59 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
60 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
61 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
62 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
63 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
64 49, 50, 51, 127, 127, 127, 127, 127
68 * Encode a buffer into base64 format
70 int base64_encode( unsigned char *dst, size_t *dlen,
71 const unsigned char *src, size_t slen )
73 size_t i, n;
74 int C1, C2, C3;
75 unsigned char *p;
77 if( slen == 0 )
78 return( 0 );
80 n = (slen << 3) / 6;
82 switch( (slen << 3) - (n * 6) )
84 case 2: n += 3; break;
85 case 4: n += 2; break;
86 default: break;
89 if( *dlen < n + 1 )
91 *dlen = n + 1;
92 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
95 n = (slen / 3) * 3;
97 for( i = 0, p = dst; i < n; i += 3 )
99 C1 = *src++;
100 C2 = *src++;
101 C3 = *src++;
103 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
104 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
105 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
106 *p++ = base64_enc_map[C3 & 0x3F];
109 if( i < slen )
111 C1 = *src++;
112 C2 = ((i + 1) < slen) ? *src++ : 0;
114 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
115 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
117 if( (i + 1) < slen )
118 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
119 else *p++ = '=';
121 *p++ = '=';
124 *dlen = p - dst;
125 *p = 0;
127 return( 0 );
131 * Decode a base64-formatted buffer
133 int base64_decode( unsigned char *dst, size_t *dlen,
134 const unsigned char *src, size_t slen )
136 size_t i, n;
137 uint32_t j, x;
138 unsigned char *p;
140 for( i = j = n = 0; i < slen; i++ )
142 if( ( slen - i ) >= 2 &&
143 src[i] == '\r' && src[i + 1] == '\n' )
144 continue;
146 if( src[i] == '\n' )
147 continue;
149 if( src[i] == '=' && ++j > 2 )
150 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
152 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
153 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
155 if( base64_dec_map[src[i]] < 64 && j != 0 )
156 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
158 n++;
161 if( n == 0 )
162 return( 0 );
164 n = ((n * 6) + 7) >> 3;
166 if( *dlen < n )
168 *dlen = n;
169 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
172 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
174 if( *src == '\r' || *src == '\n' )
175 continue;
177 j -= ( base64_dec_map[*src] == 64 );
178 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
180 if( ++n == 4 )
182 n = 0;
183 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
184 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
185 if( j > 2 ) *p++ = (unsigned char)( x );
189 *dlen = p - dst;
191 return( 0 );
194 #if defined(POLARSSL_SELF_TEST)
196 #include <string.h>
197 #include <stdio.h>
199 static const unsigned char base64_test_dec[64] =
201 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
202 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
203 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
204 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
205 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
206 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
207 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
208 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
211 static const unsigned char base64_test_enc[] =
212 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
213 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
216 * Checkup routine
218 int base64_self_test( int verbose )
220 size_t len;
221 const unsigned char *src;
222 unsigned char buffer[128];
224 if( verbose != 0 )
225 printf( " Base64 encoding test: " );
227 len = sizeof( buffer );
228 src = base64_test_dec;
230 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
231 memcmp( base64_test_enc, buffer, 88 ) != 0 )
233 if( verbose != 0 )
234 printf( "failed\n" );
236 return( 1 );
239 if( verbose != 0 )
240 printf( "passed\n Base64 decoding test: " );
242 len = sizeof( buffer );
243 src = base64_test_enc;
245 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
246 memcmp( base64_test_dec, buffer, 64 ) != 0 )
248 if( verbose != 0 )
249 printf( "failed\n" );
251 return( 1 );
254 if( verbose != 0 )
255 printf( "passed\n\n" );
257 return( 0 );
260 #endif
262 #endif