PolarSSL v1.2.9
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  const unsigned char *src;
222  unsigned char buffer[128];
223 
224  if( verbose != 0 )
225  printf( " Base64 encoding test: " );
226 
227  len = sizeof( buffer );
228  src = base64_test_dec;
229 
230  if( base64_encode( buffer, &len, src, 64 ) != 0 ||
231  memcmp( base64_test_enc, buffer, 88 ) != 0 )
232  {
233  if( verbose != 0 )
234  printf( "failed\n" );
235 
236  return( 1 );
237  }
238 
239  if( verbose != 0 )
240  printf( "passed\n Base64 decoding test: " );
241 
242  len = sizeof( buffer );
243  src = base64_test_enc;
244 
245  if( base64_decode( buffer, &len, src, 88 ) != 0 ||
246  memcmp( base64_test_dec, buffer, 64 ) != 0 )
247  {
248  if( verbose != 0 )
249  printf( "failed\n" );
250 
251  return( 1 );
252  }
253 
254  if( verbose != 0 )
255  printf( "passed\n\n" );
256 
257  return( 0 );
258 }
259 
260 #endif
261 
262 #endif
int base64_decode(unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen)
Decode a base64-formatted buffer.
Configuration options (set of defines)
int base64_self_test(int verbose)
Checkup routine.
#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL
Output buffer too small.
Definition: base64.h:32
RFC 1521 base64 encoding/decoding.
#define POLARSSL_ERR_BASE64_INVALID_CHARACTER
Invalid character in input.
Definition: base64.h:33
int base64_encode(unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen)
Encode a buffer into base64 format.