/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/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 library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  *  MA  02110-1301  USA
00019  */
00020 
00021 #ifndef _CRT_SECURE_NO_DEPRECATE
00022 #define _CRT_SECURE_NO_DEPRECATE 1
00023 #endif
00024 
00025 #include "xyssl/base64.h"
00026 
00027 static const int 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 int 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( 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         *p++ = ((i + 1) < slen) ?
00105             base64_enc_map[((( C2 & 15 ) << 2)) & 0x3F] : '=';
00106 
00107         *p++ = '=';
00108     }
00109 
00110     *dlen = p - dst;
00111 
00112     return( *p = 0 );
00113 }
00114 
00115 /*
00116  * Decode a base64-formatted buffer
00117  */
00118 int base64_decode( unsigned char *dst, int *dlen,
00119                    unsigned char *src, int  slen )
00120 {
00121     int i, j, n;
00122     unsigned long x;
00123     unsigned char *p;
00124 
00125     for( i = j = n = 0; i < slen; i++ )
00126     {
00127         if( ( slen - i ) >= 2 &&
00128             src[i] == '\r' && src[i + 1] == '\n' )
00129             continue;
00130 
00131         if( src[i] == '\n' )
00132             continue;
00133 
00134         if( src[i] == '=' && ++j > 2 )
00135             return( ERR_BASE64_INVALID_CHARACTER );
00136 
00137         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
00138             return( ERR_BASE64_INVALID_CHARACTER );
00139 
00140         if( base64_dec_map[src[i]] < 64 && j != 0 )
00141             return( ERR_BASE64_INVALID_CHARACTER );
00142 
00143         n++;
00144     }
00145 
00146     if( n == 0 )
00147         return( 0 );
00148 
00149     n = ( ( n * 6 ) + 7 ) >> 3;
00150 
00151     if( *dlen < n )
00152     {
00153         *dlen = n;
00154         return( ERR_BASE64_BUFFER_TOO_SMALL );
00155     }
00156 
00157    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
00158    {
00159         if( *src == '\r' || *src == '\n' )
00160             continue;
00161 
00162         j -= ( base64_dec_map[*src] == 64 );
00163         x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
00164 
00165         if( ++n == 4 )
00166         {
00167             n = 0;
00168             *p++ = (unsigned char) ( x >> 16 );
00169             if( j > 1 ) *p++ = (unsigned char) ( x >> 8 );
00170             if( j > 2 ) *p++ = (unsigned char )  x;
00171         }
00172     }
00173 
00174     *dlen = p - dst;
00175 
00176     return( 0 );
00177 }
00178 
00179 static const char _base64_src[] = "_base64_src";
00180 
00181 #if defined(SELF_TEST)
00182 
00183 #include <string.h>
00184 #include <stdio.h>
00185 
00186 static const unsigned char base64_test_dec[64] =
00187 {
00188     0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
00189     0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
00190     0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
00191     0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
00192     0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
00193     0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
00194     0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
00195     0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
00196 };
00197 
00198 static const unsigned char base64_test_enc[] =
00199     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
00200     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
00201 
00202 /*
00203  * Checkup routine
00204  */
00205 int base64_self_test( int verbose )
00206 {
00207     int len;
00208     unsigned char *src, buffer[128];
00209 
00210     if( verbose != 0 )
00211         printf( "  Base64 encoding test: " );
00212 
00213     len = sizeof( buffer );
00214     src = (unsigned char *) base64_test_dec;
00215 
00216     if( base64_encode( buffer, &len, src, 64 ) != 0 ||
00217         memcmp( base64_test_enc,  buffer, 88 ) != 0 ) 
00218     {
00219         if( verbose != 0 )
00220             printf( "failed\n" );
00221 
00222         return( 1 );
00223     }
00224 
00225     if( verbose != 0 )
00226         printf( "passed\n  Base64 decoding test: " );
00227 
00228     len = sizeof( buffer );
00229     src = (unsigned char *) base64_test_enc;
00230 
00231     if( base64_decode( buffer, &len, src, 88 ) != 0 ||
00232         memcmp( base64_test_dec,  buffer, 64 ) != 0 )
00233     {
00234         if( verbose != 0 )
00235             printf( "failed\n" );
00236 
00237         return( 1 );
00238     }
00239 
00240     if( verbose != 0 )
00241         printf( "passed\n\n" );
00242 
00243     return( 0 );
00244 }
00245 #else
00246 int base64_self_test( int verbose )
00247 {
00248     return( 0 );
00249 }
00250 #endif

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4