mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

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