/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/base64.c

Go to the documentation of this file.
00001 /* SVN FILE INFO
00002  * $Revision: 174 $ : Last Committed Revision
00003  * $Date: 2008-06-24 10:50:29 -0700 (Tue, 24 Jun 2008) $ : Last Committed Date */
00004 /*
00005  *  RFC 1521 base64 encoding/decoding
00006  *
00007  *  Copyright (C) 2006-2007  Christophe Devine
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License, version 2.1 as published by the Free Software Foundation.
00012  *
00013  *  This library 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 GNU
00016  *  Lesser General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Lesser General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00021  *  MA  02110-1301  USA
00022  */
00023 
00024 #ifndef _CRT_SECURE_NO_DEPRECATE
00025 #define _CRT_SECURE_NO_DEPRECATE 1
00026 #endif
00027 
00028 #include "xyssl/base64.h"
00029 
00030 static const int base64_enc_map[64] =
00031 {
00032     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00033     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00034     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
00035     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00036     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
00037     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
00038     '8', '9', '+', '/'
00039 };
00040 
00041 static const int base64_dec_map[128] =
00042 {
00043     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00044     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
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,  62, 127, 127, 127,  63,  52,  53,
00048      54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
00049     127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
00050       5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00051      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
00052      25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
00053      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
00054      39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
00055      49,  50,  51, 127, 127, 127, 127, 127
00056 };
00057 
00058 /*
00059  * Encode a buffer into base64 format
00060  */
00061 int base64_encode( unsigned char *dst, int *dlen,
00062                    unsigned char *src, int  slen )
00063 {
00064     int i, n;
00065     int C1, C2, C3;
00066     unsigned char *p;
00067 
00068     if( slen == 0 )
00069         return( 0 );
00070 
00071     n = ( slen << 3 ) / 6;
00072 
00073     switch( ( slen << 3 ) - ( n * 6 ) )
00074     {
00075         case  2: n += 3; break;
00076         case  4: n += 2; break;
00077         default: break;
00078     }
00079 
00080     if( *dlen < n + 1 )
00081     {
00082         *dlen = n + 1;
00083         return( ERR_BASE64_BUFFER_TOO_SMALL );
00084     }
00085 
00086     n = ( slen / 3 ) * 3;
00087 
00088     for( i = 0, p = dst; i < n; i += 3 )
00089     {
00090         C1 = *src++;
00091         C2 = *src++;
00092         C3 = *src++;
00093 
00094         *p++ = base64_enc_map[( C1 >> 2 ) & 0x3F];
00095         *p++ = base64_enc_map[((( C1 &  3 ) << 4) + ( C2 >> 4 )) & 0x3F];
00096         *p++ = base64_enc_map[((( C2 & 15 ) << 2) + ( C3 >> 6 )) & 0x3F];
00097         *p++ = base64_enc_map[C3 & 0x3F];
00098     }
00099 
00100     if( i < slen )
00101     {
00102         C1 = *src++;
00103         C2 = ((i + 1) < slen) ? *src++ : 0;
00104 
00105         *p++ = base64_enc_map[( C1 >> 2 ) & 0x3F];
00106         *p++ = base64_enc_map[((( C1 & 3 ) << 4) + ( C2 >> 4 )) & 0x3F];
00107         *p++ = ((i + 1) < slen) ?
00108             base64_enc_map[((( C2 & 15 ) << 2)) & 0x3F] : '=';
00109 
00110         *p++ = '=';
00111     }
00112 
00113     *dlen = p - dst;
00114 
00115     return( *p = 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( ERR_BASE64_INVALID_CHARACTER );
00139 
00140         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
00141             return( ERR_BASE64_INVALID_CHARACTER );
00142 
00143         if( base64_dec_map[src[i]] < 64 && j != 0 )
00144             return( 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( 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             *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 static const char _base64_src[] = "_base64_src";
00183 
00184 #if defined(SELF_TEST)
00185 
00186 #include <string.h>
00187 #include <stdio.h>
00188 
00189 static const unsigned char base64_test_dec[64] =
00190 {
00191     0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
00192     0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
00193     0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
00194     0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
00195     0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
00196     0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
00197     0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
00198     0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
00199 };
00200 
00201 static const unsigned char base64_test_enc[] =
00202     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
00203     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
00204 
00205 /*
00206  * Checkup routine
00207  */
00208 int base64_self_test( int verbose )
00209 {
00210     int len;
00211     unsigned char *src, buffer[128];
00212 
00213     if( verbose != 0 )
00214         printf( "  Base64 encoding test: " );
00215 
00216     len = sizeof( buffer );
00217     src = (unsigned char *) base64_test_dec;
00218 
00219     if( base64_encode( buffer, &len, src, 64 ) != 0 ||
00220         memcmp( base64_test_enc,  buffer, 88 ) != 0 ) 
00221     {
00222         if( verbose != 0 )
00223             printf( "failed\n" );
00224 
00225         return( 1 );
00226     }
00227 
00228     if( verbose != 0 )
00229         printf( "passed\n  Base64 decoding test: " );
00230 
00231     len = sizeof( buffer );
00232     src = (unsigned char *) base64_test_enc;
00233 
00234     if( base64_decode( buffer, &len, src, 88 ) != 0 ||
00235         memcmp( base64_test_dec,  buffer, 64 ) != 0 )
00236     {
00237         if( verbose != 0 )
00238             printf( "failed\n" );
00239 
00240         return( 1 );
00241     }
00242 
00243     if( verbose != 0 )
00244         printf( "passed\n\n" );
00245 
00246     return( 0 );
00247 }
00248 #else
00249 int base64_self_test( int verbose )
00250 {
00251     return( 0 );
00252 }
00253 #endif

Generated on Tue Jul 1 15:29:58 2008 for Mobile-C by  doxygen 1.5.4