123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- diff --git a/library/base64.c b/library/base64.c
- index 692e11e3fae..b89313062b6 100644
- --- a/library/base64.c
- +++ b/library/base64.c
- @@ -66,127 +66,38 @@
- #endif /* MBEDTLS_PLATFORM_C */
- #endif /* MBEDTLS_SELF_TEST */
-
- -static const unsigned char base64_enc_map[64] =
- -{
- - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
- - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
- - '8', '9', '+', '/'
- -};
- -
- -static const unsigned char base64_dec_map[128] =
- -{
- - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- - 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
- - 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
- - 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
- - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- - 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
- - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- - 49, 50, 51, 127, 127, 127, 127, 127
- -};
- -
- #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
-
- -/*
- - * Constant flow conditional assignment to unsigned char
- - */
- -static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
- - unsigned char condition )
- -{
- - /* MSVC has a warning about unary minus on unsigned integer types,
- - * but this is well-defined and precisely what we want to do here. */
- -#if defined(_MSC_VER)
- -#pragma warning( push )
- -#pragma warning( disable : 4146 )
- -#endif
- -
- - /* Generate bitmask from condition, mask will either be 0xFF or 0 */
- - unsigned char mask = ( condition | -condition );
- - mask >>= 7;
- - mask = -mask;
- -
- -#if defined(_MSC_VER)
- -#pragma warning( pop )
- -#endif
- -
- - *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
- -}
- -
- -/*
- - * Constant flow conditional assignment to uint_32
- - */
- -static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
- - uint32_t condition )
- -{
- - /* MSVC has a warning about unary minus on unsigned integer types,
- - * but this is well-defined and precisely what we want to do here. */
- -#if defined(_MSC_VER)
- -#pragma warning( push )
- -#pragma warning( disable : 4146 )
- -#endif
- -
- - /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
- - uint32_t mask = ( condition | -condition );
- - mask >>= 31;
- - mask = -mask;
- -
- -#if defined(_MSC_VER)
- -#pragma warning( pop )
- -#endif
- -
- - *dest = ( src & mask ) | ( ( *dest ) & ~mask );
- -}
- -
- -/*
- - * Constant flow check for equality
- +/* Return 0xff if low <= c <= high, 0 otherwise.
- + *
- + * Constant flow with respect to c.
- */
- -static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
- +static unsigned char mask_of_range( unsigned char low, unsigned char high,
- + unsigned char c )
- {
- - size_t difference = in_a ^ in_b;
- -
- - /* MSVC has a warning about unary minus on unsigned integer types,
- - * but this is well-defined and precisely what we want to do here. */
- -#if defined(_MSC_VER)
- -#pragma warning( push )
- -#pragma warning( disable : 4146 )
- -#endif
- -
- - difference |= -difference;
- -
- -#if defined(_MSC_VER)
- -#pragma warning( pop )
- -#endif
- -
- - /* cope with the varying size of size_t per platform */
- - difference >>= ( sizeof( difference ) * 8 - 1 );
- -
- - return (unsigned char) ( 1 ^ difference );
- + /* low_mask is: 0 if low <= c, 0x...ff if low > c */
- + unsigned low_mask = ( (unsigned) c - low ) >> 8;
- + /* high_mask is: 0 if c <= high, 0x...ff if high > c */
- + unsigned high_mask = ( (unsigned) high - c ) >> 8;
- + return( ~( low_mask | high_mask ) & 0xff );
- }
-
- -/*
- - * Constant flow lookup into table.
- +/* Given a value in the range 0..63, return the corresponding Base64 digit.
- + * The implementation assumes that letters are consecutive (e.g. ASCII
- + * but not EBCDIC).
- */
- -static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
- - const size_t table_size, const size_t table_index )
- +static unsigned char enc_char( unsigned char val )
- {
- - size_t i;
- - unsigned char result = 0;
- -
- - for( i = 0; i < table_size; ++i )
- - {
- - mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
- - }
- -
- - return result;
- + unsigned char digit = 0;
- + /* For each range of values, if val is in that range, mask digit with
- + * the corresponding value. Since val can only be in a single range,
- + * only at most one masking will change digit. */
- + digit |= mask_of_range( 0, 25, val ) & ( 'A' + val );
- + digit |= mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
- + digit |= mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
- + digit |= mask_of_range( 62, 62, val ) & '+';
- + digit |= mask_of_range( 63, 63, val ) & '/';
- + return( digit );
- }
-
- /*
- @@ -229,17 +140,10 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
- C2 = *src++;
- C3 = *src++;
-
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( ( C1 >> 2 ) & 0x3F ) );
- -
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
- -
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
- -
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( C3 & 0x3F ) );
- + *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
- + *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
- + *p++ = enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F );
- + *p++ = enc_char( C3 & 0x3F );
- }
-
- if( i < slen )
- @@ -247,15 +151,11 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
- C1 = *src++;
- C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
-
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( ( C1 >> 2 ) & 0x3F ) );
- -
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
- + *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
- + *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
-
- if( ( i + 1 ) < slen )
- - *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- - ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
- + *p++ = enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
- else *p++ = '=';
-
- *p++ = '=';
- @@ -267,26 +167,57 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
- return( 0 );
- }
-
- +/* Given a Base64 digit, return its value.
- + * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
- + * return -1.
- + *
- + * The implementation assumes that letters are consecutive (e.g. ASCII
- + * but not EBCDIC).
- + *
- + * The implementation is constant-flow (no branch or memory access depending
- + * on the value of c) unless the compiler inlines and optimizes a specific
- + * access.
- + */
- +static signed char dec_value( unsigned char c )
- +{
- + unsigned char val = 0;
- + /* For each range of digits, if c is in that range, mask val with
- + * the corresponding value. Since c can only be in a single range,
- + * only at most one masking will change val. Set val to one plus
- + * the desired value so that it stays 0 if c is in none of the ranges. */
- + val |= mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 );
- + val |= mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
- + val |= mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
- + val |= mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
- + val |= mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
- + /* At this point, val is 0 if c is an invalid digit and v+1 if c is
- + * a digit with the value v. */
- + return( val - 1 );
- +}
- +
- /*
- * Decode a base64-formatted buffer
- */
- int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
- const unsigned char *src, size_t slen )
- {
- - size_t i, n;
- - uint32_t j, x;
- + size_t i; /* index in source */
- + size_t n; /* number of digits or trailing = in source */
- + uint32_t x; /* value accumulator */
- + unsigned accumulated_digits = 0;
- + unsigned equals = 0;
- + int spaces_present = 0;
- unsigned char *p;
- - unsigned char dec_map_lookup;
-
- /* First pass: check for validity and get output length */
- - for( i = n = j = 0; i < slen; i++ )
- + for( i = n = 0; i < slen; i++ )
- {
- /* Skip spaces before checking for EOL */
- - x = 0;
- + spaces_present = 0;
- while( i < slen && src[i] == ' ' )
- {
- ++i;
- - ++x;
- + spaces_present = 1;
- }
-
- /* Spaces at end of buffer are OK */
- @@ -301,20 +232,24 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
- continue;
-
- /* Space inside a line is an error */
- - if( x != 0 )
- + if( spaces_present )
- return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
- - if( src[i] == '=' && ++j > 2 )
- - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- -
- - dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
- -
- - if( src[i] > 127 || dec_map_lookup == 127 )
- - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- -
- - if( dec_map_lookup < 64 && j != 0 )
- + if( src[i] > 127 )
- return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
- + if( src[i] == '=' )
- + {
- + if( ++equals > 2 )
- + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- + }
- + else
- + {
- + if( equals != 0 )
- + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- + if( dec_value( src[i] ) < 0 )
- + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- + }
- n++;
- }
-
- @@ -329,7 +264,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
- * n = ( ( n * 6 ) + 7 ) >> 3;
- */
- n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
- - n -= j;
- + n -= equals;
-
- if( dst == NULL || dlen < n )
- {
- @@ -337,22 +272,24 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
- return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
- }
-
- - for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
- - {
- + equals = 0;
- + for( x = 0, p = dst; i > 0; i--, src++ )
- + {
- if( *src == '\r' || *src == '\n' || *src == ' ' )
- continue;
-
- - dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
- -
- - mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
- - x = ( x << 6 ) | ( dec_map_lookup & 0x3F );
- + x = x << 6;
- + if( *src == '=' )
- + ++equals;
- + else
- + x |= dec_value( *src );
-
- - if( ++n == 4 )
- + if( ++accumulated_digits == 4 )
- {
- - n = 0;
- - if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
- - if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
- - if( j > 2 ) *p++ = (unsigned char)( x );
- + accumulated_digits = 0;
- + *p++ = (unsigned char)( x >> 16 );
- + if( equals <= 1 ) *p++ = (unsigned char)( x >> 8 );
- + if( equals <= 0 ) *p++ = (unsigned char)( x );
- }
- }
-
|