Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers base64.c Source File

base64.c

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