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