diff options
Diffstat (limited to 'thirdparty/mbedtls')
| -rw-r--r-- | thirdparty/mbedtls/include/mbedtls/bn_mul.h | 6 | ||||
| -rw-r--r-- | thirdparty/mbedtls/library/base64.c | 255 | ||||
| -rw-r--r-- | thirdparty/mbedtls/patches/pr4819-faster-base64.patch | 341 | ||||
| -rw-r--r-- | thirdparty/mbedtls/patches/pr4948-fix-clang12-opt.patch | 36 | 
4 files changed, 476 insertions, 162 deletions
diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h index 6f1201bf50..f84f9650dd 100644 --- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h +++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h @@ -256,9 +256,9 @@          "addq   $8, %%rdi\n"  #define MULADDC_STOP                        \ -        : "+c" (c), "+D" (d), "+S" (s)      \ -        : "b" (b)                           \ -        : "rax", "rdx", "r8"                \ +        : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ +        : "b" (b), "m" (*(const uint64_t (*)[16]) s)                 \ +        : "rax", "rdx", "r8"                                         \      );  #endif /* AMD64 */ diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c index 692e11e3fa..b89313062b 100644 --- a/thirdparty/mbedtls/library/base64.c +++ b/thirdparty/mbedtls/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       );          }      } diff --git a/thirdparty/mbedtls/patches/pr4819-faster-base64.patch b/thirdparty/mbedtls/patches/pr4819-faster-base64.patch new file mode 100644 index 0000000000..2f25b7b54c --- /dev/null +++ b/thirdparty/mbedtls/patches/pr4819-faster-base64.patch @@ -0,0 +1,341 @@ +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       ); +         } +     } +  diff --git a/thirdparty/mbedtls/patches/pr4948-fix-clang12-opt.patch b/thirdparty/mbedtls/patches/pr4948-fix-clang12-opt.patch new file mode 100644 index 0000000000..84c205a80f --- /dev/null +++ b/thirdparty/mbedtls/patches/pr4948-fix-clang12-opt.patch @@ -0,0 +1,36 @@ +From 7c847235e8f0e0b877c505f19733b417bb65ff2e Mon Sep 17 00:00:00 2001 +From: Gilles Peskine <Gilles.Peskine@arm.com> +Date: Tue, 14 Sep 2021 00:13:05 +0200 +Subject: [PATCH] x86_64 MULADDC assembly: add missing constraints about memory + +MULADDC_CORE reads from (%%rsi) and writes to (%%rdi). This fragment is +repeated up to 16 times, and %%rsi and %%rdi are s and d on entry +respectively. Hence the complete asm statement reads 16 64-bit words +from memory starting at s, and writes 16 64-bit words starting at d. + +Without any declaration of modified memory, Clang 12 and Clang 13 generated +non-working code for mbedtls_mpi_mod_exp. The constraints make the unit +tests pass with Clang 12. + +Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com> +--- + include/mbedtls/bn_mul.h             | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/mbedtls/bn_mul.h b/include/mbedtls/bn_mul.h +index 6f1201bf50a..f84f9650ddc 100644 +--- a/include/mbedtls/bn_mul.h ++++ b/include/mbedtls/bn_mul.h +@@ -256,9 +256,9 @@ +         "addq   $8, %%rdi\n" +  + #define MULADDC_STOP                        \ +-        : "+c" (c), "+D" (d), "+S" (s)      \ +-        : "b" (b)                           \ +-        : "rax", "rdx", "r8"                \ ++        : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ ++        : "b" (b), "m" (*(const uint64_t (*)[16]) s)                 \ ++        : "rax", "rdx", "r8"                                         \ +     ); +  + #endif /* AMD64 */  |