1 /* 2 * RFC 1521 base64 encoding/decoding 3 * 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 * 7 * This file is provided under the Apache License 2.0, or the 8 * GNU General Public License v2.0 or later. 9 * 10 * ********** 11 * Apache License 2.0: 12 * 13 * Licensed under the Apache License, Version 2.0 (the "License"); you may 14 * not use this file except in compliance with the License. 15 * You may obtain a copy of the License at 16 * 17 * http://www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, software 20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 * See the License for the specific language governing permissions and 23 * limitations under the License. 24 * 25 * ********** 26 * 27 * ********** 28 * GNU General Public License v2.0 or later: 29 * 30 * This program is free software; you can redistribute it and/or modify 31 * it under the terms of the GNU General Public License as published by 32 * the Free Software Foundation; either version 2 of the License, or 33 * (at your option) any later version. 34 * 35 * This program is distributed in the hope that it will be useful, 36 * but WITHOUT ANY WARRANTY; without even the implied warranty of 37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 * GNU General Public License for more details. 39 * 40 * You should have received a copy of the GNU General Public License along 41 * with this program; if not, write to the Free Software Foundation, Inc., 42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 43 * 44 * ********** 45 * 46 * This file is part of mbed TLS (https://tls.mbed.org) 47 */ 48 49 #if !defined(MBEDTLS_CONFIG_FILE) 50 #include "mbedtls/config.h" 51 #else 52 #include MBEDTLS_CONFIG_FILE 53 #endif 54 55 #if defined(MBEDTLS_BASE64_C) 56 57 #include "mbedtls/base64.h" 58 59 #include <stdint.h> 60 61 #if defined(MBEDTLS_SELF_TEST) 62 #include <string.h> 63 #if defined(MBEDTLS_PLATFORM_C) 64 #include "mbedtls/platform.h" 65 #else 66 #include <stdio.h> 67 #define mbedtls_printf printf 68 #endif /* MBEDTLS_PLATFORM_C */ 69 #endif /* MBEDTLS_SELF_TEST */ 70 71 static const unsigned char base64_enc_map[64] = 72 { 73 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 74 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 75 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 76 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 77 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 78 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', 79 '8', '9', '+', '/' 80 }; 81 82 static const unsigned char base64_dec_map[128] = 83 { 84 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 85 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 86 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 87 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 88 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, 89 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, 90 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, 91 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 92 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 93 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, 94 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 95 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 96 49, 50, 51, 127, 127, 127, 127, 127 97 }; 98 99 #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ 100 101 /* 102 * Encode a buffer into base64 format 103 */ 104 int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, 105 const unsigned char *src, size_t slen ) 106 { 107 size_t i, n; 108 int C1, C2, C3; 109 unsigned char *p; 110 111 if( slen == 0 ) 112 { 113 *olen = 0; 114 return( 0 ); 115 } 116 117 n = slen / 3 + ( slen % 3 != 0 ); 118 119 if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) 120 { 121 *olen = BASE64_SIZE_T_MAX; 122 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); 123 } 124 125 n *= 4; 126 127 if( ( dlen < n + 1 ) || ( NULL == dst ) ) 128 { 129 *olen = n + 1; 130 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); 131 } 132 133 n = ( slen / 3 ) * 3; 134 135 for( i = 0, p = dst; i < n; i += 3 ) 136 { 137 C1 = *src++; 138 C2 = *src++; 139 C3 = *src++; 140 141 *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; 142 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; 143 *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; 144 *p++ = base64_enc_map[C3 & 0x3F]; 145 } 146 147 if( i < slen ) 148 { 149 C1 = *src++; 150 C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; 151 152 *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; 153 *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; 154 155 if( ( i + 1 ) < slen ) 156 *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; 157 else *p++ = '='; 158 159 *p++ = '='; 160 } 161 162 *olen = p - dst; 163 *p = 0; 164 165 return( 0 ); 166 } 167 168 /* 169 * Decode a base64-formatted buffer 170 */ 171 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, 172 const unsigned char *src, size_t slen ) 173 { 174 size_t i, n; 175 uint32_t j, x; 176 unsigned char *p; 177 178 /* First pass: check for validity and get output length */ 179 for( i = n = j = 0; i < slen; i++ ) 180 { 181 /* Skip spaces before checking for EOL */ 182 x = 0; 183 while( i < slen && src[i] == ' ' ) 184 { 185 ++i; 186 ++x; 187 } 188 189 /* Spaces at end of buffer are OK */ 190 if( i == slen ) 191 break; 192 193 if( ( slen - i ) >= 2 && 194 src[i] == '\r' && src[i + 1] == '\n' ) 195 continue; 196 197 if( src[i] == '\n' ) 198 continue; 199 200 /* Space inside a line is an error */ 201 if( x != 0 ) 202 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); 203 204 if( src[i] == '=' && ++j > 2 ) 205 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); 206 207 if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) 208 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); 209 210 if( base64_dec_map[src[i]] < 64 && j != 0 ) 211 return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); 212 213 n++; 214 } 215 216 if( n == 0 ) 217 { 218 *olen = 0; 219 return( 0 ); 220 } 221 222 /* The following expression is to calculate the following formula without 223 * risk of integer overflow in n: 224 * n = ( ( n * 6 ) + 7 ) >> 3; 225 */ 226 n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); 227 n -= j; 228 229 if( dst == NULL || dlen < n ) 230 { 231 *olen = n; 232 return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); 233 } 234 235 for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) 236 { 237 if( *src == '\r' || *src == '\n' || *src == ' ' ) 238 continue; 239 240 j -= ( base64_dec_map[*src] == 64 ); 241 x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); 242 243 if( ++n == 4 ) 244 { 245 n = 0; 246 if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); 247 if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); 248 if( j > 2 ) *p++ = (unsigned char)( x ); 249 } 250 } 251 252 *olen = p - dst; 253 254 return( 0 ); 255 } 256 257 #if defined(MBEDTLS_SELF_TEST) 258 259 static const unsigned char base64_test_dec[64] = 260 { 261 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, 262 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, 263 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, 264 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, 265 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, 266 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, 267 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, 268 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 269 }; 270 271 static const unsigned char base64_test_enc[] = 272 "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" 273 "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; 274 275 /* 276 * Checkup routine 277 */ 278 int mbedtls_base64_self_test( int verbose ) 279 { 280 size_t len; 281 const unsigned char *src; 282 unsigned char buffer[128]; 283 284 if( verbose != 0 ) 285 mbedtls_printf( " Base64 encoding test: " ); 286 287 src = base64_test_dec; 288 289 if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || 290 memcmp( base64_test_enc, buffer, 88 ) != 0 ) 291 { 292 if( verbose != 0 ) 293 mbedtls_printf( "failed\n" ); 294 295 return( 1 ); 296 } 297 298 if( verbose != 0 ) 299 mbedtls_printf( "passed\n Base64 decoding test: " ); 300 301 src = base64_test_enc; 302 303 if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || 304 memcmp( base64_test_dec, buffer, 64 ) != 0 ) 305 { 306 if( verbose != 0 ) 307 mbedtls_printf( "failed\n" ); 308 309 return( 1 ); 310 } 311 312 if( verbose != 0 ) 313 mbedtls_printf( "passed\n\n" ); 314 315 return( 0 ); 316 } 317 318 #endif /* MBEDTLS_SELF_TEST */ 319 320 #endif /* MBEDTLS_BASE64_C */ 321