blob: ee9c05c5d9f7d4646de2cc06d293389cfd7607de [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * RFC 1521 base64 encoding/decoding
3 *
Paul Bakker7dc4c442014-02-01 22:50:26 +01004 * Copyright (C) 2006-2014, Brainspark B.V.
Paul Bakkerb96f1542010-07-18 20:36:00 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
Paul Bakker84f12b72010-07-18 10:13:04 +00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakkerb96f1542010-07-18 20:36:00 +00008 *
Paul Bakker77b385e2009-07-28 17:23:11 +00009 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +000010 *
Paul Bakker5121ce52009-01-03 21:22:43 +000011 * 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
Paul Bakker40e46942009-01-03 21:51:57 +000026#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000027
Paul Bakker40e46942009-01-03 21:51:57 +000028#if defined(POLARSSL_BASE64_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Paul Bakker40e46942009-01-03 21:51:57 +000030#include "polarssl/base64.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakkerfa6a6202013-10-28 18:48:30 +010032#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker5c2364c2012-10-01 14:41:15 +000033#include <basetsd.h>
34typedef UINT32 uint32_t;
35#else
36#include <inttypes.h>
37#endif
38
Paul Bakker7dc4c442014-02-01 22:50:26 +010039#if defined(POLARSSL_PLATFORM_C)
40#include "polarssl/platform.h"
41#else
42#define polarssl_printf printf
43#endif
44
Paul Bakker5121ce52009-01-03 21:22:43 +000045static const unsigned char base64_enc_map[64] =
46{
47 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
48 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
49 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
50 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
51 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
52 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
53 '8', '9', '+', '/'
54};
55
56static const unsigned char base64_dec_map[128] =
57{
58 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
59 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
60 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
61 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
62 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
63 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
64 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
65 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
66 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
67 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
68 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
69 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
70 49, 50, 51, 127, 127, 127, 127, 127
71};
72
73/*
74 * Encode a buffer into base64 format
75 */
Paul Bakker23986e52011-04-24 08:57:21 +000076int base64_encode( unsigned char *dst, size_t *dlen,
77 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +000078{
Paul Bakker23986e52011-04-24 08:57:21 +000079 size_t i, n;
Paul Bakker5121ce52009-01-03 21:22:43 +000080 int C1, C2, C3;
81 unsigned char *p;
82
83 if( slen == 0 )
84 return( 0 );
85
86 n = (slen << 3) / 6;
87
88 switch( (slen << 3) - (n * 6) )
89 {
90 case 2: n += 3; break;
91 case 4: n += 2; break;
92 default: break;
93 }
94
95 if( *dlen < n + 1 )
96 {
97 *dlen = n + 1;
Paul Bakker40e46942009-01-03 21:51:57 +000098 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +000099 }
100
101 n = (slen / 3) * 3;
102
103 for( i = 0, p = dst; i < n; i += 3 )
104 {
105 C1 = *src++;
106 C2 = *src++;
107 C3 = *src++;
108
109 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
110 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
111 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
112 *p++ = base64_enc_map[C3 & 0x3F];
113 }
114
115 if( i < slen )
116 {
117 C1 = *src++;
118 C2 = ((i + 1) < slen) ? *src++ : 0;
119
120 *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
121 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
122
123 if( (i + 1) < slen )
124 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
125 else *p++ = '=';
126
127 *p++ = '=';
128 }
129
130 *dlen = p - dst;
131 *p = 0;
132
133 return( 0 );
134}
135
136/*
137 * Decode a base64-formatted buffer
138 */
Paul Bakker23986e52011-04-24 08:57:21 +0000139int base64_decode( unsigned char *dst, size_t *dlen,
140 const unsigned char *src, size_t slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000141{
Paul Bakker5c2364c2012-10-01 14:41:15 +0000142 size_t i, n;
143 uint32_t j, x;
Paul Bakker5121ce52009-01-03 21:22:43 +0000144 unsigned char *p;
145
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200146 for( i = n = j = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000147 {
148 if( ( slen - i ) >= 2 &&
149 src[i] == '\r' && src[i + 1] == '\n' )
150 continue;
151
152 if( src[i] == '\n' )
153 continue;
154
155 if( src[i] == '=' && ++j > 2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000156 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000157
158 if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
Paul Bakker40e46942009-01-03 21:51:57 +0000159 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000160
161 if( base64_dec_map[src[i]] < 64 && j != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000162 return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000163
164 n++;
165 }
166
167 if( n == 0 )
168 return( 0 );
169
170 n = ((n * 6) + 7) >> 3;
171
Paul Bakkerf4a14272013-07-05 10:29:12 +0200172 if( dst == NULL || *dlen < n )
Paul Bakker5121ce52009-01-03 21:22:43 +0000173 {
174 *dlen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000175 return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000176 }
177
178 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
179 {
180 if( *src == '\r' || *src == '\n' )
181 continue;
182
183 j -= ( base64_dec_map[*src] == 64 );
184 x = (x << 6) | ( base64_dec_map[*src] & 0x3F );
185
186 if( ++n == 4 )
187 {
188 n = 0;
189 if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
190 if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
191 if( j > 2 ) *p++ = (unsigned char)( x );
192 }
193 }
194
195 *dlen = p - dst;
196
197 return( 0 );
198}
199
Paul Bakker40e46942009-01-03 21:51:57 +0000200#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000201
202#include <string.h>
203#include <stdio.h>
204
205static const unsigned char base64_test_dec[64] =
206{
207 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
208 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
209 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
210 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
211 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
212 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
213 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
214 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
215};
216
217static const unsigned char base64_test_enc[] =
218 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
219 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
220
221/*
222 * Checkup routine
223 */
224int base64_self_test( int verbose )
225{
Paul Bakker23986e52011-04-24 08:57:21 +0000226 size_t len;
Paul Bakker3c2122f2013-06-24 19:03:14 +0200227 const unsigned char *src;
228 unsigned char buffer[128];
Paul Bakker5121ce52009-01-03 21:22:43 +0000229
230 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100231 polarssl_printf( " Base64 encoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
233 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200234 src = base64_test_dec;
Paul Bakker5121ce52009-01-03 21:22:43 +0000235
236 if( base64_encode( buffer, &len, src, 64 ) != 0 ||
Paul Bakker3c2122f2013-06-24 19:03:14 +0200237 memcmp( base64_test_enc, buffer, 88 ) != 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000238 {
239 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100240 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
242 return( 1 );
243 }
244
245 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100246 polarssl_printf( "passed\n Base64 decoding test: " );
Paul Bakker5121ce52009-01-03 21:22:43 +0000247
248 len = sizeof( buffer );
Paul Bakker3c2122f2013-06-24 19:03:14 +0200249 src = base64_test_enc;
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
251 if( base64_decode( buffer, &len, src, 88 ) != 0 ||
252 memcmp( base64_test_dec, buffer, 64 ) != 0 )
253 {
254 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100255 polarssl_printf( "failed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000256
257 return( 1 );
258 }
259
260 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100261 polarssl_printf( "passed\n\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +0000262
263 return( 0 );
264}
265
266#endif
267
268#endif