update to pre-4.87 master
[exim.git] / src / src / pdkim / base64.c
1 /*
2 * RFC 1521 base64 encoding/decoding
3 *
4 * Copyright (C) 2006-2010, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
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.
15 *
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.
20 *
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.
24 */
25
26 #include "polarssl/config.h"
27
28 #if defined(POLARSSL_BASE64_C)
29
30 #include "polarssl/base64.h"
31
32 static const unsigned char base64_enc_map[64] =
33 {
34 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
35 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
36 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
37 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
38 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
39 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
40 '8', '9', '+', '/'
41 };
42
43 static const unsigned char base64_dec_map[128] =
44 {
45 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
46 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
47 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
48 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
49 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
50 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
51 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
52 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
53 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
54 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
55 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
56 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
57 49, 50, 51, 127, 127, 127, 127, 127
58 };
59
60 /*
61 * Encode a buffer into base64 format
62 */
63 int base64_encode( unsigned char *dst, int *dlen,
64 const unsigned char *src, int slen )
65 {
66 int i, n;
67 int C1, C2, C3;
68 unsigned char *p;
69
70 if( slen == 0 )
71 return( 0 );
72
73 n = (slen << 3) / 6;
74
75 switch( (slen << 3) - (n * 6) )
76 {
77 case 2: n += 3; break;
78 case 4: n += 2; break;
79 default: break;
80 }
81
82 if( *dlen < n + 1 )
83 {
84 *dlen = n + 1;
85 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
86 }
87
88 n = (slen / 3) * 3;
89
90 for( i = 0, p = dst; i < n; i += 3 )
91 {
92 C1 = *src++;
93 C2 = *src++;
94 C3 = *src++;
95
96 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
97 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
98 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
99 *p++ = base64_enc_map[C3 & 0x3F];
100 }
101
102 if( i < slen )
103 {
104 C1 = *src++;
105 C2 = ((i + 1) < slen) ? *src++ : 0;
106
107 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
108 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
109
110 if( (i + 1) < slen )
111 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
112 else *p++ = '=';
113
114 *p++ = '=';
115 }
116
117 *dlen = p - dst;
118 *p = 0;
119
120 return( 0 );
121 }
122
123 /*
124 * Decode a base64-formatted buffer
125 */
126 int base64_decode( unsigned char *dst, int *dlen,
127 const unsigned char *src, int slen )
128 {
129 int i, j, n;
130 unsigned long x;
131 unsigned char *p;
132
133 for( i = j = n = 0; i < slen; i++ )
134 {
135 unsigned char c = src[i];
136
137 if( ( slen - i ) >= 2 &&
138 c == '\r' && src[i + 1] == '\n' )
139 continue;
140
141 if( c == '\n' || c == ' ' || c == '\t' )
142 continue;
143
144 if( c == '=' && ++j > 2 )
145 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
146
147 if( c > 127 || base64_dec_map[src[i]] == 127 )
148 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
149
150 if( base64_dec_map[c] < 64 && j != 0 )
151 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
152
153 n++;
154 }
155
156 if( n == 0 )
157 return( 0 );
158
159 n = ((n * 6) + 7) >> 3;
160
161 if( *dlen < n )
162 {
163 *dlen = n;
164 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
165 }
166
167 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
168 {
169 unsigned char c = *src;
170
171 if( c == '\r' || c == '\n' || c == ' ' || c == '\t' )
172 continue;
173
174 j -= ( base64_dec_map[c] == 64 );
175 x = (x << 6) | ( base64_dec_map[c] & 0x3F );
176
177 if( ++n == 4 )
178 {
179 n = 0;
180 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
181 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
182 if( j > 2 ) *p++ = (unsigned char)( x );
183 }
184 }
185
186 *dlen = p - dst;
187
188 return( 0 );
189 }
190
191 #if defined(POLARSSL_SELF_TEST)
192
193 #include <string.h>
194 #include <stdio.h>
195
196 static const unsigned char base64_test_dec[64] =
197 {
198 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
199 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
200 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
201 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
202 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
203 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
204 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
205 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
206 };
207
208 static const unsigned char base64_test_enc[] =
209 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
210 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
211
212 /*
213 * Checkup routine
214 */
215 int base64_self_test( int verbose )
216 {
217 int len;
218 unsigned char *src, buffer[128];
219
220 if( verbose != 0 )
221 printf( " Base64 encoding test: " );
222
223 len = sizeof( buffer );
224 src = (unsigned char *) base64_test_dec;
225
226 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
227 memcmp( base64_test_enc, buffer, 88 ) != 0 )
228 {
229 if( verbose != 0 )
230 printf( "failed\n" );
231
232 return( 1 );
233 }
234
235 if( verbose != 0 )
236 printf( "passed\n Base64 decoding test: " );
237
238 len = sizeof( buffer );
239 src = (unsigned char *) base64_test_enc;
240
241 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
242 memcmp( base64_test_dec, buffer, 64 ) != 0 )
243 {
244 if( verbose != 0 )
245 printf( "failed\n" );
246
247 return( 1 );
248 }
249
250 if( verbose != 0 )
251 printf( "passed\n\n" );
252
253 return( 0 );
254 }
255
256 #endif
257
258 #endif