diff --git a/crypto/base64/base64.c b/crypto/base64/base64.c index 1ddf0944..d5450fca 100644 --- a/crypto/base64/base64.c +++ b/crypto/base64/base64.c @@ -65,6 +65,24 @@ #include "../internal.h" +/* constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t| + * arguments for a slightly simpler implementation. */ +static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) { + crypto_word_t aw = a; + crypto_word_t bw = b; + /* |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same + * MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1. */ + return constant_time_msb_w(aw - bw); +} + +/* constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max| + * and |CONSTTIME_FALSE_8| otherwise. */ +static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min, + uint8_t max) { + a -= min; + return constant_time_lt_args_8(a, max - min + 1); +} + /* Encoding. */ static uint8_t conv_bin2ascii(uint8_t a) { @@ -72,9 +90,11 @@ static uint8_t conv_bin2ascii(uint8_t a) { * itself in constant-time. */ a &= 0x3f; uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/'); - ret = constant_time_select_8(constant_time_lt_8(a, 62), a - 52 + '0', ret); - ret = constant_time_select_8(constant_time_lt_8(a, 52), a - 26 + 'a', ret); - ret = constant_time_select_8(constant_time_lt_8(a, 26), a + 'A', ret); + ret = + constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret); + ret = + constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret); + ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret); return ret; } @@ -238,12 +258,9 @@ void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) { static uint8_t base64_ascii_to_bin(uint8_t a) { /* Since PEM is sometimes used to carry private keys, we decode base64 data * itself in constant-time. */ - const uint8_t is_upper = - constant_time_ge_8(a, 'A') & constant_time_ge_8('Z', a); - const uint8_t is_lower = - constant_time_ge_8(a, 'a') & constant_time_ge_8('z', a); - const uint8_t is_digit = - constant_time_ge_8(a, '0') & constant_time_ge_8('9', a); + const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z'); + const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z'); + const uint8_t is_digit = constant_time_in_range_8(a, '0', '9'); const uint8_t is_plus = constant_time_eq_8(a, '+'); const uint8_t is_slash = constant_time_eq_8(a, '/'); const uint8_t is_equals = constant_time_eq_8(a, '=');