PolarSSL v1.2.11
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  n -= j;
166 
167  if( *dlen < n )
168  {
169  *dlen = n;
171  }
172 
173  for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
174  {
175  if( *src == '\r' || *src == '\n' )
176  continue;
177 
178  j -= ( base64_dec_map[*src] == 64 );
179  x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
180 
181  if( ++n == 4 )
182  {
183  n = 0;
184  if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
185  if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
186  if( j > 2 ) *p++ = (unsigned char)( x );
187  }
188  }
189 
190  *dlen = p - dst;
191 
192  return( 0 );
193 }
194 
195 #if defined(POLARSSL_SELF_TEST)
196 
197 #include <string.h>
198 #include <stdio.h>
199 
200 static const unsigned char base64_test_dec[64] =
201 {
202  0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
203  0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
204  0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
205  0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
206  0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
207  0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
208  0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
209  0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
210 };
211 
212 static const unsigned char base64_test_enc[] =
213  "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
214  "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
215 
216 /*
217  * Checkup routine
218  */
219 int base64_self_test( int verbose )
220 {
221  size_t len;
222  const unsigned char *src;
223  unsigned char buffer[128];
224 
225  if( verbose != 0 )
226  printf( " Base64 encoding test: " );
227 
228  len = sizeof( buffer );
229  src = base64_test_dec;
230 
231  if( base64_encode( buffer, &len, src, 64 ) != 0 ||
232  memcmp( base64_test_enc, buffer, 88 ) != 0 )
233  {
234  if( verbose != 0 )
235  printf( "failed\n" );
236 
237  return( 1 );
238  }
239 
240  if( verbose != 0 )
241  printf( "passed\n Base64 decoding test: " );
242 
243  len = sizeof( buffer );
244  src = base64_test_enc;
245 
246  if( base64_decode( buffer, &len, src, 88 ) != 0 ||
247  memcmp( base64_test_dec, buffer, 64 ) != 0 )
248  {
249  if( verbose != 0 )
250  printf( "failed\n" );
251 
252  return( 1 );
253  }
254 
255  if( verbose != 0 )
256  printf( "passed\n\n" );
257 
258  return( 0 );
259 }
260 
261 #endif
262 
263 #endif