Skip to content

Commit

Permalink
Move const time memory comparison utils to ct_utils.h
Browse files Browse the repository at this point in the history
  • Loading branch information
randombit committed Oct 16, 2023
1 parent 5073121 commit 6ecef88
Show file tree
Hide file tree
Showing 44 changed files with 149 additions and 75 deletions.
6 changes: 4 additions & 2 deletions src/cli/zfec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#if defined(BOTAN_HAS_ZFEC) && defined(BOTAN_HAS_SHA2_64)
#include <botan/hash.h>
#include <botan/mem_ops.h>
#include <botan/zfec.h>
#include <botan/internal/loadstor.h>
#include <fstream>
Expand Down Expand Up @@ -70,7 +71,7 @@ class FEC_Share final {
hash.update(bits, len - hash_len);
auto share_hash = hash.final();

const bool digest_ok = Botan::same_mem(share_hash.data(), &bits[len - hash_len], hash_len);
const bool digest_ok = Botan::constant_time_compare(share_hash.data(), &bits[len - hash_len], hash_len);

if(!digest_ok) {
throw CLI_Error("FEC share has invalid hash");
Expand Down Expand Up @@ -251,7 +252,8 @@ class FEC_Decode final : public Command {

auto decoded_digest = hash->process(decoded.data(), decoded.size() - (hash_len + padding));

if(!Botan::same_mem(decoded_digest.data(), &decoded[decoded.size() - (hash_len + padding)], hash_len)) {
if(!Botan::constant_time_compare(
decoded_digest.data(), &decoded[decoded.size() - (hash_len + padding)], hash_len)) {
throw CLI_Error("Recovered data failed digest check");
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/asn1/asn1_str.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ ASN1_Type choose_encoding(std::string_view str) {
all_printable &= is_printable;
}

if(all_printable.is_set()) {
if(all_printable.as_bool()) {
return ASN1_Type::PrintableString;
} else {
return ASN1_Type::Utf8String;
Expand Down
5 changes: 3 additions & 2 deletions src/lib/compat/sodium/sodium_secretbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <botan/mac.h>
#include <botan/secmem.h>
#include <botan/stream_cipher.h>
#include <botan/internal/ct_utils.h>

namespace Botan {

Expand Down Expand Up @@ -54,7 +55,7 @@ int Sodium::crypto_secretbox_xsalsa20poly1305_open(
poly1305->update(ctext + 32, ctext_len - 32);
secure_vector<uint8_t> computed = poly1305->final();

if(!constant_time_compare(computed.data(), ctext + 16, 16)) {
if(CT::is_not_equal(computed.data(), ctext + 16, 16).as_bool()) {
return -1;
}

Expand Down Expand Up @@ -105,7 +106,7 @@ int Sodium::crypto_secretbox_open_detached(uint8_t ptext[],
poly1305->update(ctext, ctext_len);
secure_vector<uint8_t> computed_mac = poly1305->final();

if(!constant_time_compare(mac, computed_mac.data(), computed_mac.size())) {
if(!CT::is_equal(mac, computed_mac.data(), computed_mac.size()).as_bool()) {
return -1;
}

Expand Down
11 changes: 6 additions & 5 deletions src/lib/compat/sodium/sodium_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,25 @@ void Sodium::randombytes_buf_deterministic(void* buf, size_t size, const uint8_t
}

int Sodium::crypto_verify_16(const uint8_t x[16], const uint8_t y[16]) {
return same_mem(x, y, 16);
return static_cast<int>(CT::is_equal(x, y, 16).select(1, 0));
}

int Sodium::crypto_verify_32(const uint8_t x[32], const uint8_t y[32]) {
return same_mem(x, y, 32);
return static_cast<int>(CT::is_equal(x, y, 32).select(1, 0));
}

int Sodium::crypto_verify_64(const uint8_t x[64], const uint8_t y[64]) {
return same_mem(x, y, 64);
return static_cast<int>(CT::is_equal(x, y, 64).select(1, 0));
}

void Sodium::sodium_memzero(void* ptr, size_t len) {
secure_scrub_memory(ptr, len);
}

int Sodium::sodium_memcmp(const void* x, const void* y, size_t len) {
const bool same = constant_time_compare(static_cast<const uint8_t*>(x), static_cast<const uint8_t*>(y), len);
return same ? 0 : -1;
const auto same = CT::is_equal(static_cast<const uint8_t*>(x), static_cast<const uint8_t*>(y), len);
// Return 0 if same or -1 if differing
return static_cast<int>(same.select(1, 0)) - 1;
}

int Sodium::sodium_compare(const uint8_t x[], const uint8_t y[], size_t len) {
Expand Down
5 changes: 4 additions & 1 deletion src/lib/ffi/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <botan/hex.h>
#include <botan/mem_ops.h>
#include <botan/version.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/ffi_util.h>
#include <botan/internal/os_utils.h>
#include <cstdio>
Expand Down Expand Up @@ -290,7 +291,9 @@ uint32_t botan_version_datestamp() {
}

int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len) {
return Botan::constant_time_compare(x, y, len) ? 0 : -1;
auto same = Botan::CT::is_equal(x, y, len);
// Return 0 if same or -1 otherwise
return static_cast<int>(same.select(1, 0)) - 1;
}

int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len) {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/mac/mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <botan/exceptn.h>
#include <botan/mem_ops.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/scan_name.h>

#if defined(BOTAN_HAS_CMAC)
Expand Down Expand Up @@ -169,7 +170,7 @@ bool MessageAuthenticationCode::verify_mac_result(std::span<const uint8_t> mac)
return false;
}

return constant_time_compare(our_mac.data(), mac.data(), mac.size());
return CT::is_equal(our_mac.data(), mac.data(), mac.size()).as_bool();
}

} // namespace Botan
6 changes: 3 additions & 3 deletions src/lib/math/bigint/bigint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ bool BigInt::is_equal(const BigInt& other) const {
return false;
}

return bigint_ct_is_eq(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
return bigint_ct_is_eq(this->data(), this->sig_words(), other.data(), other.sig_words()).as_bool();
}

bool BigInt::is_less_than(const BigInt& other) const {
Expand All @@ -178,10 +178,10 @@ bool BigInt::is_less_than(const BigInt& other) const {
}

if(other.is_negative() && this->is_negative()) {
return bigint_ct_is_lt(other.data(), other.sig_words(), this->data(), this->sig_words()).is_set();
return bigint_ct_is_lt(other.data(), other.sig_words(), this->data(), this->sig_words()).as_bool();
}

return bigint_ct_is_lt(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
return bigint_ct_is_lt(this->data(), this->sig_words(), other.data(), other.sig_words()).as_bool();
}

void BigInt::encode_words(word out[], size_t size) const {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/math/bigint/divide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ inline bool division_check(word q, word y2, word y1, word x3, word x2, word x1)
const word x[3] = {x1, x2, x3};
const word y[3] = {y1, y2, y3};

return bigint_ct_is_lt(x, 3, y, 3).is_set();
return bigint_ct_is_lt(x, 3, y, 3).as_bool();
}

} // namespace
Expand Down Expand Up @@ -98,7 +98,7 @@ void ct_divide_word(const BigInt& x, word y, BigInt& q_out, word& r_out) {
r += x_b;

const auto r_gte_y = CT::Mask<word>::is_gte(r, y) | r_carry;
q.conditionally_set_bit(b, r_gte_y.is_set());
q.conditionally_set_bit(b, r_gte_y.as_bool());
r = r_gte_y.select(r - y, r);
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/math/numbertheory/make_prm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Prime_Sieve final {
}
}

return passes.is_set();
return passes.as_bool();
}

private:
Expand Down
2 changes: 1 addition & 1 deletion src/lib/math/numbertheory/mod_inv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ BigInt inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod) {
b_is_1 &= CT::Mask<word>::is_zero(b_w[i]);
}

BOTAN_ASSERT(a_is_0.is_set(), "A is zero");
BOTAN_ASSERT(a_is_0.as_bool(), "A is zero");

// if b != 1 then gcd(n,mod) > 1 and inverse does not exist
// in which case zero out the result to indicate this
Expand Down
3 changes: 2 additions & 1 deletion src/lib/misc/cryptobox/cryptobox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <botan/pem.h>
#include <botan/pwdhash.h>
#include <botan/rng.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/loadstor.h>

namespace Botan::CryptoBox {
Expand Down Expand Up @@ -132,7 +133,7 @@ secure_vector<uint8_t> decrypt_bin(const uint8_t input[], size_t input_len, std:
}
secure_vector<uint8_t> computed_mac = hmac->final();

if(!constant_time_compare(computed_mac.data(), box_mac, MAC_OUTPUT_LEN)) {
if(!CT::is_equal(computed_mac.data(), box_mac, MAC_OUTPUT_LEN).as_bool()) {
throw Decoding_Error("CryptoBox integrity failure");
}

Expand Down
5 changes: 3 additions & 2 deletions src/lib/misc/tss/tss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <botan/hash.h>
#include <botan/hex.h>
#include <botan/rng.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/loadstor.h>

namespace Botan {
Expand Down Expand Up @@ -215,7 +216,7 @@ secure_vector<uint8_t> RTSS_Share::reconstruct(const std::vector<RTSS_Share>& sh
throw Decoding_Error("Different sized RTSS shares detected");
}

if(!same_mem(&shares[0].m_contents[0], &shares[i].m_contents[0], RTSS_HEADER_SIZE)) {
if(!CT::is_equal(&shares[0].m_contents[0], &shares[i].m_contents[0], RTSS_HEADER_SIZE).as_bool()) {
throw Decoding_Error("Different RTSS headers detected");
}
}
Expand Down Expand Up @@ -289,7 +290,7 @@ secure_vector<uint8_t> RTSS_Share::reconstruct(const std::vector<RTSS_Share>& sh
hash->update(recovered.data(), secret_len);
secure_vector<uint8_t> hash_check = hash->final();

if(!constant_time_compare(hash_check.data(), &recovered[secret_len], hash->output_length())) {
if(!CT::is_equal(hash_check.data(), &recovered[secret_len], hash->output_length()).as_bool()) {
throw Decoding_Error("RTSS hash check failed");
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/modes/aead/ccm/ccm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <botan/internal/ccm.h>

#include <botan/internal/ct_utils.h>
#include <botan/internal/fmt.h>
#include <botan/internal/loadstor.h>

Expand Down Expand Up @@ -265,7 +266,7 @@ void CCM_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {

T ^= S0;

if(!constant_time_compare(T.data(), buf_end, tag_size())) {
if(!CT::is_equal(T.data(), buf_end, tag_size()).as_bool()) {
throw Invalid_Authentication_Tag("CCM tag check failed");
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <botan/internal/chacha20poly1305.h>

#include <botan/internal/ct_utils.h>
#include <botan/internal/loadstor.h>

namespace Botan {
Expand Down Expand Up @@ -158,7 +159,7 @@ void ChaCha20Poly1305_Decryption::finish_msg(secure_vector<uint8_t>& buffer, siz
m_ctext_len = 0;
m_nonce_len = 0;

if(!constant_time_compare(mac, included_tag, tag_size())) {
if(!CT::is_equal(mac, included_tag, tag_size()).as_bool()) {
throw Invalid_Authentication_Tag("ChaCha20Poly1305 tag check failed");
}
buffer.resize(offset + remaining);
Expand Down
3 changes: 2 additions & 1 deletion src/lib/modes/aead/eax/eax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <botan/internal/eax.h>

#include <botan/internal/cmac.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/ctr.h>
#include <botan/internal/fmt.h>

Expand Down Expand Up @@ -176,7 +177,7 @@ void EAX_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {

mac ^= m_ad_mac;

bool accept_mac = constant_time_compare(mac.data(), included_tag, tag_size());
const bool accept_mac = CT::is_equal(mac.data(), included_tag, tag_size()).as_bool();

buffer.resize(offset + remaining);

Expand Down
3 changes: 2 additions & 1 deletion src/lib/modes/aead/gcm/gcm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <botan/internal/gcm.h>

#include <botan/block_cipher.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/ctr.h>
#include <botan/internal/fmt.h>
#include <botan/internal/ghash.h>
Expand Down Expand Up @@ -167,7 +168,7 @@ void GCM_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {

const uint8_t* included_tag = &buffer[remaining + offset];

if(!constant_time_compare(mac.data(), included_tag, tag_size())) {
if(!CT::is_equal(mac.data(), included_tag, tag_size()).as_bool()) {
throw Invalid_Authentication_Tag("GCM tag check failed");
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/modes/aead/ocb/ocb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <botan/block_cipher.h>
#include <botan/internal/bit_ops.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/poly_dbl.h>

namespace Botan {
Expand Down Expand Up @@ -486,7 +487,7 @@ void OCB_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {
// compare mac
const uint8_t* included_tag = &buf[remaining];

if(!constant_time_compare(mac.data(), included_tag, tag_size())) {
if(!CT::is_equal(mac.data(), included_tag, tag_size()).as_bool()) {
throw Invalid_Authentication_Tag("OCB tag check failed");
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/modes/aead/siv/siv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <botan/block_cipher.h>
#include <botan/internal/cmac.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/ctr.h>
#include <botan/internal/poly_dbl.h>

Expand Down Expand Up @@ -187,7 +188,7 @@ void SIV_Decryption::finish_msg(secure_vector<uint8_t>& buffer, size_t offset) {

const secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());

if(!constant_time_compare(T.data(), V.data(), T.size())) {
if(!CT::is_equal(T.data(), V.data(), T.size()).as_bool()) {
throw Invalid_Authentication_Tag("SIV tag check failed");
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/passhash/argon2fmt/argon2fmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <botan/base64.h>
#include <botan/pwdhash.h>
#include <botan/rng.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/fmt.h>
#include <botan/internal/parsing.h>

Expand Down Expand Up @@ -139,7 +140,7 @@ bool argon2_check_pwhash(const char* password, size_t password_len, std::string_

pwdhash->derive_key(generated.data(), generated.size(), password, password_len, salt.data(), salt.size());

return constant_time_compare(generated.data(), hash.data(), generated.size());
return CT::is_equal(generated.data(), hash.data(), generated.size()).as_bool();
}

} // namespace Botan
3 changes: 2 additions & 1 deletion src/lib/passhash/bcrypt/bcrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ bool check_bcrypt(std::string_view pass, std::string_view hash) {

const std::string compare = make_bcrypt(pass, salt, workfactor, bcrypt_version);

return same_mem(hash.data(), compare.data(), compare.size());
return CT::is_equal(cast_char_ptr_to_uint8(hash.data()), cast_char_ptr_to_uint8(compare.data()), compare.size())
.as_bool();
}

} // namespace Botan
6 changes: 4 additions & 2 deletions src/lib/passhash/passhash9/passhash9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <botan/base64.h>
#include <botan/pbkdf2.h>
#include <botan/rng.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/loadstor.h>

namespace Botan {
Expand Down Expand Up @@ -119,8 +120,9 @@ bool check_passhash9(std::string_view pass, std::string_view hash) {
kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN, pass, &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES, kdf_iterations)
.bits_of();

return constant_time_compare(
cmp.data(), &bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES], PASSHASH9_PBKDF_OUTPUT_LEN);
const uint8_t* hashbytes = &bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES];

return CT::is_equal(cmp.data(), hashbytes, PASSHASH9_PBKDF_OUTPUT_LEN).as_bool();
}

bool is_passhash9_alg_supported(uint8_t alg_id) {
Expand Down
4 changes: 3 additions & 1 deletion src/lib/pk_pad/eme_oaep/oaep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ secure_vector<uint8_t> oaep_find_delim(uint8_t& valid_mask,

// If we never saw any non-zero byte, then it's not valid input
bad_input_m |= waiting_for_delim;
bad_input_m |= CT::Mask<uint8_t>::is_zero(ct_compare_u8(&input[hlen], Phash.data(), hlen));

// If the P hash is wrong, then it's not valid
bad_input_m |= CT::is_not_equal(&input[hlen], Phash.data(), hlen);

delim_idx += 1;

Expand Down
Loading

0 comments on commit 6ecef88

Please sign in to comment.