Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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