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