/home/dko/projects/mobilec/tags/MobileC-v1.10.2/MobileC-v1.10.2/src/security/xyssl-0.9/library/base64.c

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

Generated on Fri Jul 11 17:59:46 2008 for Mobile-C by  doxygen 1.5.4