tidying
[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