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