PolarSSL v1.2.5
base64.c
Go to the documentation of this file.
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 #ifdef _MSC_VER
33 #include <basetsd.h>
34 typedef UINT32 uint32_t;
35 #else
36 #include <inttypes.h>
37 #endif
38 
39 static const unsigned char base64_enc_map[64] =
40 {
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', '+', '/'
48 };
49 
50 static const unsigned char base64_dec_map[128] =
51 {
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
65 };
66 
67 /*
68  * Encode a buffer into base64 format
69  */
70 int base64_encode( unsigned char *dst, size_t *dlen,
71  const unsigned char *src, size_t slen )
72 {
73  size_t i, n;
74  int C1, C2, C3;
75  unsigned char *p;
76 
77  if( slen == 0 )
78  return( 0 );
79 
80  n = (slen << 3) / 6;
81 
82  switch( (slen << 3) - (n * 6) )
83  {
84  case 2: n += 3; break;
85  case 4: n += 2; break;
86  default: break;
87  }
88 
89  if( *dlen < n + 1 )
90  {
91  *dlen = n + 1;
93  }
94 
95  n = (slen / 3) * 3;
96 
97  for( i = 0, p = dst; i < n; i += 3 )
98  {
99  C1 = *src++;
100  C2 = *src++;
101  C3 = *src++;
102 
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];
107  }
108 
109  if( i < slen )
110  {
111  C1 = *src++;
112  C2 = ((i + 1) < slen) ? *src++ : 0;
113 
114  *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
115  *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
116 
117  if( (i + 1) < slen )
118  *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
119  else *p++ = '=';
120 
121  *p++ = '=';
122  }
123 
124  *dlen = p - dst;
125  *p = 0;
126 
127  return( 0 );
128 }
129 
130 /*
131  * Decode a base64-formatted buffer
132  */
133 int base64_decode( unsigned char *dst, size_t *dlen,
134  const unsigned char *src, size_t slen )
135 {
136  size_t i, n;
137  uint32_t j, x;
138  unsigned char *p;
139 
140  for( i = j = n = 0; i < slen; i++ )
141  {
142  if( ( slen - i ) >= 2 &&
143  src[i] == '\r' && src[i + 1] == '\n' )
144  continue;
145 
146  if( src[i] == '\n' )
147  continue;
148 
149  if( src[i] == '=' && ++j > 2 )
151 
152  if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
154 
155  if( base64_dec_map[src[i]] < 64 && j != 0 )
157 
158  n++;
159  }
160 
161  if( n == 0 )
162  return( 0 );
163 
164  n = ((n * 6) + 7) >> 3;
165 
166  if( *dlen < n )
167  {
168  *dlen = n;
170  }
171 
172  for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
173  {
174  if( *src == '\r' || *src == '\n' )
175  continue;
176 
177  j -= ( base64_dec_map[*src] == 64 );
178  x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
179 
180  if( ++n == 4 )
181  {
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 );
186  }
187  }
188 
189  *dlen = p - dst;
190 
191  return( 0 );
192 }
193 
194 #if defined(POLARSSL_SELF_TEST)
195 
196 #include <string.h>
197 #include <stdio.h>
198 
199 static const unsigned char base64_test_dec[64] =
200 {
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
209 };
210 
211 static const unsigned char base64_test_enc[] =
212  "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
213  "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
214 
215 /*
216  * Checkup routine
217  */
218 int base64_self_test( int verbose )
219 {
220  size_t len;
221  unsigned char *src, buffer[128];
222 
223  if( verbose != 0 )
224  printf( " Base64 encoding test: " );
225 
226  len = sizeof( buffer );
227  src = (unsigned char *) base64_test_dec;
228 
229  if( base64_encode( buffer, &len, src, 64 ) != 0 ||
230  memcmp( base64_test_enc, buffer, 88 ) != 0 )
231  {
232  if( verbose != 0 )
233  printf( "failed\n" );
234 
235  return( 1 );
236  }
237 
238  if( verbose != 0 )
239  printf( "passed\n Base64 decoding test: " );
240 
241  len = sizeof( buffer );
242  src = (unsigned char *) base64_test_enc;
243 
244  if( base64_decode( buffer, &len, src, 88 ) != 0 ||
245  memcmp( base64_test_dec, buffer, 64 ) != 0 )
246  {
247  if( verbose != 0 )
248  printf( "failed\n" );
249 
250  return( 1 );
251  }
252 
253  if( verbose != 0 )
254  printf( "passed\n\n" );
255 
256  return( 0 );
257 }
258 
259 #endif
260 
261 #endif