mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers base64.c Source File

base64.c

00001 /*
00002  *  RFC 1521 base64 encoding/decoding
00003  *
00004  *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
00005  *
00006  *  This file is part of mbed TLS (https://tls.mbed.org)
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License along
00019  *  with this program; if not, write to the Free Software Foundation, Inc.,
00020  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021  */
00022 
00023 #if !defined(POLARSSL_CONFIG_FILE)
00024 #include "polarssl/config.h"
00025 #else
00026 #include POLARSSL_CONFIG_FILE
00027 #endif
00028 
00029 #if defined(POLARSSL_BASE64_C)
00030 
00031 #include "polarssl/base64.h"
00032 
00033 #if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
00034 #include <basetsd.h>
00035 typedef UINT32 uint32_t;
00036 #else
00037 #include <inttypes.h>
00038 #endif
00039 
00040 #if defined(POLARSSL_SELF_TEST)
00041 #include <string.h>
00042 #if defined(POLARSSL_PLATFORM_C)
00043 #include "polarssl/platform.h"
00044 #else
00045 #include <stdio.h>
00046 #define polarssl_printf printf
00047 #endif /* POLARSSL_PLATFORM_C */
00048 #endif /* POLARSSL_SELF_TEST */
00049 
00050 static const unsigned char base64_enc_map[64] =
00051 {
00052     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00053     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00054     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
00055     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00056     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
00057     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
00058     '8', '9', '+', '/'
00059 };
00060 
00061 static const unsigned char base64_dec_map[128] =
00062 {
00063     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00064     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00065     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00066     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00067     127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
00068      54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
00069     127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
00070       5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00071      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
00072      25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
00073      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
00074      39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
00075      49,  50,  51, 127, 127, 127, 127, 127
00076 };
00077 
00078 /*
00079  * Encode a buffer into base64 format
00080  */
00081 int base64_encode( unsigned char *dst, size_t *dlen,
00082                    const unsigned char *src, size_t slen )
00083 {
00084     size_t i, n;
00085     int C1, C2, C3;
00086     unsigned char *p;
00087 
00088     if( slen == 0 )
00089     {
00090         *dlen = 0;
00091         return( 0 );
00092     }
00093 
00094     n = ( slen << 3 ) / 6;
00095 
00096     switch( ( slen << 3 ) - ( n * 6 ) )
00097     {
00098         case  2: n += 3; break;
00099         case  4: n += 2; break;
00100         default: break;
00101     }
00102 
00103     if( *dlen < n + 1 )
00104     {
00105         *dlen = n + 1;
00106         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
00107     }
00108 
00109     n = ( slen / 3 ) * 3;
00110 
00111     for( i = 0, p = dst; i < n; i += 3 )
00112     {
00113         C1 = *src++;
00114         C2 = *src++;
00115         C3 = *src++;
00116 
00117         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
00118         *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
00119         *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
00120         *p++ = base64_enc_map[C3 & 0x3F];
00121     }
00122 
00123     if( i < slen )
00124     {
00125         C1 = *src++;
00126         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
00127 
00128         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
00129         *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
00130 
00131         if( ( i + 1 ) < slen )
00132              *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
00133         else *p++ = '=';
00134 
00135         *p++ = '=';
00136     }
00137 
00138     *dlen = p - dst;
00139     *p = 0;
00140 
00141     return( 0 );
00142 }
00143 
00144 /*
00145  * Decode a base64-formatted buffer
00146  */
00147 int base64_decode( unsigned char *dst, size_t *dlen,
00148                    const unsigned char *src, size_t slen )
00149 {
00150     size_t i, n;
00151     uint32_t j, x;
00152     unsigned char *p;
00153 
00154     /* First pass: check for validity and get output length */
00155     for( i = n = j = 0; i < slen; i++ )
00156     {
00157         /* Skip spaces before checking for EOL */
00158         x = 0;
00159         while( i < slen && src[i] == ' ' )
00160         {
00161             ++i;
00162             ++x;
00163         }
00164 
00165         /* Spaces at end of buffer are OK */
00166         if( i == slen )
00167             break;
00168 
00169         if( ( slen - i ) >= 2 &&
00170             src[i] == '\r' && src[i + 1] == '\n' )
00171             continue;
00172 
00173         if( src[i] == '\n' )
00174             continue;
00175 
00176         /* Space inside a line is an error */
00177         if( x != 0 )
00178             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00179 
00180         if( src[i] == '=' && ++j > 2 )
00181             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00182 
00183         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
00184             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00185 
00186         if( base64_dec_map[src[i]] < 64 && j != 0 )
00187             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00188 
00189         n++;
00190     }
00191 
00192     if( n == 0 )
00193         return( 0 );
00194 
00195     n = ( ( n * 6 ) + 7 ) >> 3;
00196     n -= j;
00197 
00198     if( dst == NULL || *dlen < n )
00199     {
00200         *dlen = n;
00201         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
00202     }
00203 
00204    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
00205    {
00206         if( *src == '\r' || *src == '\n' || *src == ' ' )
00207             continue;
00208 
00209         j -= ( base64_dec_map[*src] == 64 );
00210         x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
00211 
00212         if( ++n == 4 )
00213         {
00214             n = 0;
00215             if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
00216             if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
00217             if( j > 2 ) *p++ = (unsigned char)( x       );
00218         }
00219     }
00220 
00221     *dlen = p - dst;
00222 
00223     return( 0 );
00224 }
00225 
00226 #if defined(POLARSSL_SELF_TEST)
00227 
00228 static const unsigned char base64_test_dec[64] =
00229 {
00230     0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
00231     0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
00232     0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
00233     0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
00234     0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
00235     0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
00236     0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
00237     0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
00238 };
00239 
00240 static const unsigned char base64_test_enc[] =
00241     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
00242     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
00243 
00244 /*
00245  * Checkup routine
00246  */
00247 int base64_self_test( int verbose )
00248 {
00249     size_t len;
00250     const unsigned char *src;
00251     unsigned char buffer[128];
00252 
00253     if( verbose != 0 )
00254         polarssl_printf( "  Base64 encoding test: " );
00255 
00256     len = sizeof( buffer );
00257     src = base64_test_dec;
00258 
00259     if( base64_encode( buffer, &len, src, 64 ) != 0 ||
00260          memcmp( base64_test_enc, buffer, 88 ) != 0 )
00261     {
00262         if( verbose != 0 )
00263             polarssl_printf( "failed\n" );
00264 
00265         return( 1 );
00266     }
00267 
00268     if( verbose != 0 )
00269         polarssl_printf( "passed\n  Base64 decoding test: " );
00270 
00271     len = sizeof( buffer );
00272     src = base64_test_enc;
00273 
00274     if( base64_decode( buffer, &len, src, 88 ) != 0 ||
00275          memcmp( base64_test_dec, buffer, 64 ) != 0 )
00276     {
00277         if( verbose != 0 )
00278             polarssl_printf( "failed\n" );
00279 
00280         return( 1 );
00281     }
00282 
00283     if( verbose != 0 )
00284         polarssl_printf( "passed\n\n" );
00285 
00286     return( 0 );
00287 }
00288 
00289 #endif /* POLARSSL_SELF_TEST */
00290 
00291 #endif /* POLARSSL_BASE64_C */
00292