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