PolarSSL v1.1.5
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 static const unsigned char base64_enc_map[64] =
33 {
34  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
35  'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
36  'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
37  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
38  'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
39  'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
40  '8', '9', '+', '/'
41 };
42 
43 static const unsigned char base64_dec_map[128] =
44 {
45  127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
46  127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
47  127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
48  127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
49  127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
50  54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
51  127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
52  5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
53  15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
54  25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
55  29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
56  39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
57  49, 50, 51, 127, 127, 127, 127, 127
58 };
59 
60 /*
61  * Encode a buffer into base64 format
62  */
63 int base64_encode( unsigned char *dst, size_t *dlen,
64  const unsigned char *src, size_t slen )
65 {
66  size_t i, n;
67  int C1, C2, C3;
68  unsigned char *p;
69 
70  if( slen == 0 )
71  return( 0 );
72 
73  n = (slen << 3) / 6;
74 
75  switch( (slen << 3) - (n * 6) )
76  {
77  case 2: n += 3; break;
78  case 4: n += 2; break;
79  default: break;
80  }
81 
82  if( *dlen < n + 1 )
83  {
84  *dlen = n + 1;
86  }
87 
88  n = (slen / 3) * 3;
89 
90  for( i = 0, p = dst; i < n; i += 3 )
91  {
92  C1 = *src++;
93  C2 = *src++;
94  C3 = *src++;
95 
96  *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
97  *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
98  *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
99  *p++ = base64_enc_map[C3 & 0x3F];
100  }
101 
102  if( i < slen )
103  {
104  C1 = *src++;
105  C2 = ((i + 1) < slen) ? *src++ : 0;
106 
107  *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
108  *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
109 
110  if( (i + 1) < slen )
111  *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
112  else *p++ = '=';
113 
114  *p++ = '=';
115  }
116 
117  *dlen = p - dst;
118  *p = 0;
119 
120  return( 0 );
121 }
122 
123 /*
124  * Decode a base64-formatted buffer
125  */
126 int base64_decode( unsigned char *dst, size_t *dlen,
127  const unsigned char *src, size_t slen )
128 {
129  size_t i, j, n;
130  unsigned long x;
131  unsigned char *p;
132 
133  for( i = j = n = 0; i < slen; i++ )
134  {
135  if( ( slen - i ) >= 2 &&
136  src[i] == '\r' && src[i + 1] == '\n' )
137  continue;
138 
139  if( src[i] == '\n' )
140  continue;
141 
142  if( src[i] == '=' && ++j > 2 )
144 
145  if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
147 
148  if( base64_dec_map[src[i]] < 64 && j != 0 )
150 
151  n++;
152  }
153 
154  if( n == 0 )
155  return( 0 );
156 
157  n = ((n * 6) + 7) >> 3;
158 
159  if( *dlen < n )
160  {
161  *dlen = n;
163  }
164 
165  for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
166  {
167  if( *src == '\r' || *src == '\n' )
168  continue;
169 
170  j -= ( base64_dec_map[*src] == 64 );
171  x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
172 
173  if( ++n == 4 )
174  {
175  n = 0;
176  if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
177  if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
178  if( j > 2 ) *p++ = (unsigned char)( x );
179  }
180  }
181 
182  *dlen = p - dst;
183 
184  return( 0 );
185 }
186 
187 #if defined(POLARSSL_SELF_TEST)
188 
189 #include <string.h>
190 #include <stdio.h>
191 
192 static const unsigned char base64_test_dec[64] =
193 {
194  0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
195  0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
196  0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
197  0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
198  0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
199  0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
200  0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
201  0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
202 };
203 
204 static const unsigned char base64_test_enc[] =
205  "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
206  "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
207 
208 /*
209  * Checkup routine
210  */
211 int base64_self_test( int verbose )
212 {
213  size_t len;
214  unsigned char *src, buffer[128];
215 
216  if( verbose != 0 )
217  printf( " Base64 encoding test: " );
218 
219  len = sizeof( buffer );
220  src = (unsigned char *) base64_test_dec;
221 
222  if( base64_encode( buffer, &len, src, 64 ) != 0 ||
223  memcmp( base64_test_enc, buffer, 88 ) != 0 )
224  {
225  if( verbose != 0 )
226  printf( "failed\n" );
227 
228  return( 1 );
229  }
230 
231  if( verbose != 0 )
232  printf( "passed\n Base64 decoding test: " );
233 
234  len = sizeof( buffer );
235  src = (unsigned char *) base64_test_enc;
236 
237  if( base64_decode( buffer, &len, src, 88 ) != 0 ||
238  memcmp( base64_test_dec, buffer, 64 ) != 0 )
239  {
240  if( verbose != 0 )
241  printf( "failed\n" );
242 
243  return( 1 );
244  }
245 
246  if( verbose != 0 )
247  printf( "passed\n\n" );
248 
249  return( 0 );
250 }
251 
252 #endif
253 
254 #endif