diff --git a/crypto/internal.h b/crypto/internal.h index a63f7a7d..f32d3699 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -169,7 +169,7 @@ void OPENSSL_cpuid_setup(void); * can be written as * * unsigned int lt = constant_time_lt(a, b); - * c = a & lt | b & ~lt; */ + * c = constant_time_select(lt, a, b); */ /* constant_time_msb returns the given value with the MSB copied to all the * other bits. Uses the fact that arithmetic shift shifts-in the sign bit. @@ -230,6 +230,27 @@ static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) { return (uint8_t)(constant_time_eq(a, b)); } +/* constant_time_select returns (mask & a) | (~mask & b). When |mask| is all 1s + * or all 0s (as returned by the methods above), the select methods return + * either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). */ +static inline unsigned int constant_time_select(unsigned int mask, + unsigned int a, unsigned int b) { + return (mask & a) | (~mask & b); +} + +/* constant_time_select_8 acts like |constant_time_select| but operates on + * 8-bit values. */ +static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a, + uint8_t b) { + return (uint8_t)(constant_time_select(mask, a, b)); +} + +/* constant_time_select_int acts like |constant_time_select| but operates on + * ints. */ +static inline int constant_time_select_int(unsigned int mask, int a, int b) { + return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b))); +} + #if defined(__cplusplus) } /* extern C */ diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c index 04bfd6d0..44f408d5 100644 --- a/ssl/s3_cbc.c +++ b/ssl/s3_cbc.c @@ -96,7 +96,7 @@ int ssl3_cbc_remove_padding(const SSL* s, padding_length = good & (padding_length+1); rec->length -= padding_length; rec->type |= padding_length<<8; /* kludge: pass padding length */ - return (int)((good & 1) | (~good & -1)); + return constant_time_select_int(good, 1, -1); } /* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC @@ -166,7 +166,7 @@ int tls1_cbc_remove_padding(const SSL* s, rec->length -= padding_length; rec->type |= padding_length<<8; /* kludge: pass padding length */ - return (int)((good & 1) | (~good & -1)); + return constant_time_select_int(good, 1, -1); } /* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in @@ -562,7 +562,7 @@ void ssl3_cbc_digest_record( /* If this is the block containing the end of the * application data, and we are at the offset for the * 0x80 value, then overwrite b with 0x80. */ - b = (b&~is_past_c) | (0x80&is_past_c); + b = constant_time_select_8(is_past_c, 0x80, b); /* If this the the block containing the end of the * application data and we're past the 0x80 value then * just write zero. */ @@ -578,7 +578,7 @@ void ssl3_cbc_digest_record( if (j >= md_block_size - md_length_size) { /* If this is index_b, write a length byte. */ - b = (b&~is_block_b) | (is_block_b&length_bytes[j-(md_block_size-md_length_size)]); + b = constant_time_select_8(is_block_b, length_bytes[j-(md_block_size-md_length_size)], b); } block[j] = b; }