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