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