aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build-data/cc/clang.txt2
-rw-r--r--src/build-data/cc/gcc.txt2
-rw-r--r--src/cli/speed.cpp14
-rw-r--r--src/cli/utils.cpp3
-rw-r--r--src/contrib/perl-xs/Botan.xs12
-rw-r--r--src/contrib/perl-xs/t/oid.t7
-rw-r--r--src/lib/block/cast/cast128.cpp82
-rw-r--r--src/lib/ffi/ffi.cpp7
-rw-r--r--src/lib/ffi/ffi.h5
-rw-r--r--src/lib/hash/streebog/streebog.cpp37
-rw-r--r--src/lib/mac/mac.cpp2
-rw-r--r--src/lib/misc/cryptobox/cryptobox.cpp2
-rw-r--r--src/lib/misc/tss/tss.cpp7
-rw-r--r--src/lib/modes/aead/ccm/ccm.cpp2
-rw-r--r--src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp2
-rw-r--r--src/lib/modes/aead/eax/eax.cpp2
-rw-r--r--src/lib/modes/aead/gcm/gcm.cpp6
-rw-r--r--src/lib/modes/aead/ocb/ocb.cpp2
-rw-r--r--src/lib/modes/cbc/cbc.cpp42
-rw-r--r--src/lib/modes/cbc/cbc.h2
-rw-r--r--src/lib/modes/cfb/cfb.cpp78
-rw-r--r--src/lib/modes/cfb/cfb.h13
-rw-r--r--src/lib/passhash/bcrypt/bcrypt.cpp6
-rw-r--r--src/lib/passhash/passhash9/passhash9.cpp2
-rw-r--r--src/lib/pk_pad/eme_oaep/oaep.cpp2
-rw-r--r--src/lib/pk_pad/emsa1/emsa1.cpp2
-rw-r--r--src/lib/pk_pad/emsa_pssr/pssr.cpp2
-rw-r--r--src/lib/pk_pad/emsa_raw/emsa_raw.cpp2
-rw-r--r--src/lib/pk_pad/iso9796/iso9796.cpp2
-rw-r--r--src/lib/prov/openssl/openssl_ec.cpp2
-rw-r--r--src/lib/pubkey/dlies/dlies.cpp2
-rw-r--r--src/lib/pubkey/ecc_key/ecc_key.cpp3
-rw-r--r--src/lib/pubkey/ecies/ecies.cpp2
-rw-r--r--src/lib/pubkey/ed25519/ed25519.cpp2
-rw-r--r--src/lib/pubkey/ed25519/ed25519_fe.cpp514
-rw-r--r--src/lib/pubkey/ed25519/ed25519_internal.h18
-rw-r--r--src/lib/pubkey/sm2/sm2_enc.cpp2
-rw-r--r--src/lib/tls/msg_finished.cpp2
-rw-r--r--src/lib/tls/tls_cbc/tls_cbc.cpp4
-rw-r--r--src/lib/utils/cpuid.cpp461
-rw-r--r--src/lib/utils/cpuid/cpuid.cpp169
-rw-r--r--src/lib/utils/cpuid/cpuid.h (renamed from src/lib/utils/cpuid.h)10
-rw-r--r--src/lib/utils/cpuid/cpuid_arm.cpp214
-rw-r--r--src/lib/utils/cpuid/cpuid_ppc.cpp101
-rw-r--r--src/lib/utils/cpuid/cpuid_x86.cpp167
-rw-r--r--src/lib/utils/cpuid/info.txt7
-rw-r--r--src/lib/utils/info.txt5
-rw-r--r--src/lib/utils/mem_ops.cpp84
-rw-r--r--src/lib/utils/mem_ops.h46
-rw-r--r--src/lib/utils/os_utils.cpp386
-rw-r--r--src/lib/utils/simd/simd_32.h7
-rwxr-xr-xsrc/scripts/ci/setup_travis.sh2
-rw-r--r--src/scripts/ci/travis.yml5
-rwxr-xr-xsrc/scripts/ci_build.py8
-rw-r--r--src/tests/data/aead/gcm.vec143
-rw-r--r--src/tests/data/ecc/ecc_private_with_rfc5915_parameters.pem6
-rw-r--r--src/tests/test_filters.cpp71
-rw-r--r--src/tests/tests.cpp41
-rw-r--r--src/tests/unit_ecdsa.cpp27
59 files changed, 1668 insertions, 1192 deletions
diff --git a/src/build-data/cc/clang.txt b/src/build-data/cc/clang.txt
index 865809792..ee22e25e9 100644
--- a/src/build-data/cc/clang.txt
+++ b/src/build-data/cc/clang.txt
@@ -11,7 +11,7 @@ add_framework_option "-framework "
lang_flags "-std=c++11 -D_REENTRANT"
warning_flags "-Wall -Wextra -Wpedantic -Wshadow -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wunreachable-code"
-maintainer_warning_flags "-Wdocumentation -Qunused-arguments -Werror -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=unreachable-code -Wno-error=deprecated-declarations"
+maintainer_warning_flags "-Wdocumentation -Qunused-arguments -Werror -Wno-error=unused-parameter -Wno-error=unreachable-code -Wno-error=deprecated-declarations"
compile_flags "-c"
debug_info_flags "-g"
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index fdada6a3d..7249fae8e 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -12,7 +12,7 @@ lang_flags "-std=c++11 -D_REENTRANT"
# This should only contain flags which are included in GCC 4.8
warning_flags "-Wall -Wextra -Wpedantic -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wzero-as-null-pointer-constant -Wnon-virtual-dtor"
-maintainer_warning_flags "-Wold-style-cast -Wsuggest-override -Wshadow -Werror -Wno-error=old-style-cast -Wno-error=zero-as-null-pointer-constant -Wno-error=strict-overflow -Wno-error=deprecated-declarations"
+maintainer_warning_flags "-Wold-style-cast -Wsuggest-override -Wshadow -Werror -Wno-error=strict-overflow -Wno-error=deprecated-declarations"
compile_flags "-c"
debug_info_flags "-g"
diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp
index 99e4c157f..e53c3e785 100644
--- a/src/cli/speed.cpp
+++ b/src/cli/speed.cpp
@@ -1,5 +1,5 @@
/*
-* (C) 2009,2010,2014,2015 Jack Lloyd
+* (C) 2009,2010,2014,2015,2017 Jack Lloyd
* (C) 2015 Simon Warta (Kullo GmbH)
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -677,14 +677,10 @@ class Speed final : public Command
for(std::string cpuid_to_clear : Botan::split_on(get_arg("clear-cpuid"), ','))
{
-#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
- if(cpuid_to_clear == "avx2")
- Botan::CPUID::clear_cpuid_bit(Botan::CPUID::CPUID_AVX2_BIT);
- else if(cpuid_to_clear == "sse2")
- Botan::CPUID::clear_cpuid_bit(Botan::CPUID::CPUID_SSE2_BIT);
- else if(cpuid_to_clear == "sha")
- Botan::CPUID::clear_cpuid_bit(Botan::CPUID::CPUID_SHA_BIT);
-#endif
+ for(auto bit : Botan::CPUID::bit_from_string(cpuid_to_clear))
+ {
+ Botan::CPUID::clear_cpuid_bit(bit);
+ }
}
const bool using_defaults = (algos.empty());
diff --git a/src/cli/utils.cpp b/src/cli/utils.cpp
index 0fb939066..c8b23cb6d 100644
--- a/src/cli/utils.cpp
+++ b/src/cli/utils.cpp
@@ -141,8 +141,7 @@ class Config_Info final : public Command
}
else if(arg == "libs")
{
- output() << "-lbotan-" << Botan::version_major() << "." << Botan::version_minor()
- << " " << BOTAN_LIB_LINK << "\n";
+ output() << "-lbotan-" << Botan::version_major() << " " << BOTAN_LIB_LINK << "\n";
}
else
{
diff --git a/src/contrib/perl-xs/Botan.xs b/src/contrib/perl-xs/Botan.xs
index 38f1646b6..339986092 100644
--- a/src/contrib/perl-xs/Botan.xs
+++ b/src/contrib/perl-xs/Botan.xs
@@ -361,18 +361,6 @@ Botan__OID::as_string()
MODULE = Botan PACKAGE = Botan::OIDS
-void
-add_oid(oid, name)
- Botan__OID *oid;
- char *name;
- CODE:
- try {
- Botan::OIDS::add_oid(*oid, name);
- }
- catch (const std::exception &e) {
- croak(e.what());
- }
-
char *
lookup_by_oid(oid)
Botan__OID *oid;
diff --git a/src/contrib/perl-xs/t/oid.t b/src/contrib/perl-xs/t/oid.t
index 66204541f..694121ca8 100644
--- a/src/contrib/perl-xs/t/oid.t
+++ b/src/contrib/perl-xs/t/oid.t
@@ -7,7 +7,7 @@
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
-BEGIN { $| = 1; print "1..6\n"; }
+BEGIN { $| = 1; print "1..5\n"; }
END { print "not ok 1\n" unless $loaded; }
use Botan;
@@ -38,8 +38,3 @@ my $oid_foo_num = '1.2.3.4.5.6.7.8.9.10.11.12.13.14.15';
my $oid_foo = Botan::OID->new($oid_foo_num);
print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne $oid_foo_num;
print "ok 5\n";
-
-Botan::OIDS::add_oid($oid_foo, 'Zito.Foo');
-
-print "not " if Botan::OIDS::lookup_by_oid($oid_foo) ne 'Zito.Foo';
-print "ok 6\n";
diff --git a/src/lib/block/cast/cast128.cpp b/src/lib/block/cast/cast128.cpp
index 26076e128..d6ded8cd2 100644
--- a/src/lib/block/cast/cast128.cpp
+++ b/src/lib/block/cast/cast128.cpp
@@ -16,31 +16,31 @@ namespace {
/*
* CAST-128 Round Type 1
*/
-inline void R1(uint32_t& L, uint32_t R, uint32_t MK, uint8_t RK)
+inline uint32_t R1(uint32_t R, uint32_t MK, uint8_t RK)
{
uint32_t T = rotate_left(MK + R, RK);
- L ^= (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) -
- CAST_SBOX3[get_byte(2, T)] + CAST_SBOX4[get_byte(3, T)];
+ return (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) -
+ CAST_SBOX3[get_byte(2, T)] + CAST_SBOX4[get_byte(3, T)];
}
/*
* CAST-128 Round Type 2
*/
-inline void R2(uint32_t& L, uint32_t R, uint32_t MK, uint8_t RK)
+inline uint32_t R2(uint32_t R, uint32_t MK, uint8_t RK)
{
uint32_t T = rotate_left(MK ^ R, RK);
- L ^= (CAST_SBOX1[get_byte(0, T)] - CAST_SBOX2[get_byte(1, T)] +
- CAST_SBOX3[get_byte(2, T)]) ^ CAST_SBOX4[get_byte(3, T)];
+ return (CAST_SBOX1[get_byte(0, T)] - CAST_SBOX2[get_byte(1, T)] +
+ CAST_SBOX3[get_byte(2, T)]) ^ CAST_SBOX4[get_byte(3, T)];
}
/*
* CAST-128 Round Type 3
*/
-inline void R3(uint32_t& L, uint32_t R, uint32_t MK, uint8_t RK)
+inline uint32_t R3(uint32_t R, uint32_t MK, uint8_t RK)
{
uint32_t T = rotate_left(MK - R, RK);
- L ^= ((CAST_SBOX1[get_byte(0, T)] + CAST_SBOX2[get_byte(1, T)]) ^
- CAST_SBOX3[get_byte(2, T)]) - CAST_SBOX4[get_byte(3, T)];
+ return ((CAST_SBOX1[get_byte(0, T)] + CAST_SBOX2[get_byte(1, T)]) ^
+ CAST_SBOX3[get_byte(2, T)]) - CAST_SBOX4[get_byte(3, T)];
}
}
@@ -55,22 +55,22 @@ void CAST_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
uint32_t L, R;
load_be(in + BLOCK_SIZE*i, L, R);
- R1(L, R, m_MK[ 0], m_RK[ 0]);
- R2(R, L, m_MK[ 1], m_RK[ 1]);
- R3(L, R, m_MK[ 2], m_RK[ 2]);
- R1(R, L, m_MK[ 3], m_RK[ 3]);
- R2(L, R, m_MK[ 4], m_RK[ 4]);
- R3(R, L, m_MK[ 5], m_RK[ 5]);
- R1(L, R, m_MK[ 6], m_RK[ 6]);
- R2(R, L, m_MK[ 7], m_RK[ 7]);
- R3(L, R, m_MK[ 8], m_RK[ 8]);
- R1(R, L, m_MK[ 9], m_RK[ 9]);
- R2(L, R, m_MK[10], m_RK[10]);
- R3(R, L, m_MK[11], m_RK[11]);
- R1(L, R, m_MK[12], m_RK[12]);
- R2(R, L, m_MK[13], m_RK[13]);
- R3(L, R, m_MK[14], m_RK[14]);
- R1(R, L, m_MK[15], m_RK[15]);
+ L ^= R1(R, m_MK[ 0], m_RK[ 0]);
+ R ^= R2(L, m_MK[ 1], m_RK[ 1]);
+ L ^= R3(R, m_MK[ 2], m_RK[ 2]);
+ R ^= R1(L, m_MK[ 3], m_RK[ 3]);
+ L ^= R2(R, m_MK[ 4], m_RK[ 4]);
+ R ^= R3(L, m_MK[ 5], m_RK[ 5]);
+ L ^= R1(R, m_MK[ 6], m_RK[ 6]);
+ R ^= R2(L, m_MK[ 7], m_RK[ 7]);
+ L ^= R3(R, m_MK[ 8], m_RK[ 8]);
+ R ^= R1(L, m_MK[ 9], m_RK[ 9]);
+ L ^= R2(R, m_MK[10], m_RK[10]);
+ R ^= R3(L, m_MK[11], m_RK[11]);
+ L ^= R1(R, m_MK[12], m_RK[12]);
+ R ^= R2(L, m_MK[13], m_RK[13]);
+ L ^= R3(R, m_MK[14], m_RK[14]);
+ R ^= R1(L, m_MK[15], m_RK[15]);
store_be(out + BLOCK_SIZE*i, R, L);
}
@@ -86,22 +86,22 @@ void CAST_128::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
uint32_t L, R;
load_be(in + BLOCK_SIZE*i, L, R);
- R1(L, R, m_MK[15], m_RK[15]);
- R3(R, L, m_MK[14], m_RK[14]);
- R2(L, R, m_MK[13], m_RK[13]);
- R1(R, L, m_MK[12], m_RK[12]);
- R3(L, R, m_MK[11], m_RK[11]);
- R2(R, L, m_MK[10], m_RK[10]);
- R1(L, R, m_MK[ 9], m_RK[ 9]);
- R3(R, L, m_MK[ 8], m_RK[ 8]);
- R2(L, R, m_MK[ 7], m_RK[ 7]);
- R1(R, L, m_MK[ 6], m_RK[ 6]);
- R3(L, R, m_MK[ 5], m_RK[ 5]);
- R2(R, L, m_MK[ 4], m_RK[ 4]);
- R1(L, R, m_MK[ 3], m_RK[ 3]);
- R3(R, L, m_MK[ 2], m_RK[ 2]);
- R2(L, R, m_MK[ 1], m_RK[ 1]);
- R1(R, L, m_MK[ 0], m_RK[ 0]);
+ L ^= R1(R, m_MK[15], m_RK[15]);
+ R ^= R3(L, m_MK[14], m_RK[14]);
+ L ^= R2(R, m_MK[13], m_RK[13]);
+ R ^= R1(L, m_MK[12], m_RK[12]);
+ L ^= R3(R, m_MK[11], m_RK[11]);
+ R ^= R2(L, m_MK[10], m_RK[10]);
+ L ^= R1(R, m_MK[ 9], m_RK[ 9]);
+ R ^= R3(L, m_MK[ 8], m_RK[ 8]);
+ L ^= R2(R, m_MK[ 7], m_RK[ 7]);
+ R ^= R1(L, m_MK[ 6], m_RK[ 6]);
+ L ^= R3(R, m_MK[ 5], m_RK[ 5]);
+ R ^= R2(L, m_MK[ 4], m_RK[ 4]);
+ L ^= R1(R, m_MK[ 3], m_RK[ 3]);
+ R ^= R3(L, m_MK[ 2], m_RK[ 2]);
+ L ^= R2(R, m_MK[ 1], m_RK[ 1]);
+ R ^= R1(L, m_MK[ 0], m_RK[ 0]);
store_be(out + BLOCK_SIZE*i, R, L);
}
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 1dfa66e5f..00181dbc9 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -63,9 +63,14 @@ uint32_t botan_version_minor() { return Botan::version_minor(); }
uint32_t botan_version_patch() { return Botan::version_patch(); }
uint32_t botan_version_datestamp() { return 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;
+ }
+
int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
{
- return Botan::same_mem(x, y, len) ? 0 : -1;
+ return botan_constant_time_compare(x, y, len);
}
int botan_scrub_mem(void* mem, size_t bytes)
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index de752f43c..73c999f66 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -155,6 +155,11 @@ doesn't exactly work well either!
/**
* Returns 0 if x[0..len] == y[0..len], or otherwise -1
*/
+BOTAN_DLL int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len);
+
+/**
+* Deprecated equivalent to botan_constant_time_compare
+*/
BOTAN_DLL int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len);
/**
diff --git a/src/lib/hash/streebog/streebog.cpp b/src/lib/hash/streebog/streebog.cpp
index ae2fe1fef..07286e9c8 100644
--- a/src/lib/hash/streebog/streebog.cpp
+++ b/src/lib/hash/streebog/streebog.cpp
@@ -53,20 +53,28 @@ inline void lps(uint64_t* block)
}
}
-inline void e(uint64_t* K, const uint8_t* m)
+inline void e(uint64_t* K, const uint64_t* m)
{
- uint64_t tmp[8];
+ uint64_t A[8];
uint64_t C[8];
- std::memcpy(tmp, K, 64);
- xor_buf(K, reinterpret_cast<const uint64_t*>(m), 8);
- for(int i = 0; i < 12; ++i)
+ copy_mem(A, K, 8);
+
+ for(size_t i = 0; i != 8; ++i)
+ {
+ K[i] ^= m[i];
+ }
+
+ for(size_t i = 0; i < 12; ++i)
{
lps(K);
load_le(C, reinterpret_cast<const uint8_t*>(&STREEBOG_C[i][0]), 8);
- xor_buf(tmp, C, 8);
- lps(tmp);
- xor_buf(K, tmp, 8);
+
+ for(size_t j = 0; j != 8; ++j)
+ A[j] ^= C[j];
+ lps(A);
+ for(size_t j = 0; j != 8; ++j)
+ K[j] ^= A[j];
}
}
@@ -77,12 +85,17 @@ inline void g(uint64_t* h, const uint8_t* m, uint64_t N)
// force N to little-endian
store_le(N, reinterpret_cast<uint8_t*>(&N));
- std::memcpy(hN, h, 64);
+ copy_mem(hN, h, 8);
hN[0] ^= N;
lps(hN);
- e(hN, m);
- xor_buf(h, hN, 8);
- xor_buf(h, reinterpret_cast<const uint64_t*>(m), 8);
+ const uint64_t* m64 = reinterpret_cast<const uint64_t*>(m);
+
+ e(hN, m64);
+
+ for(size_t i = 0; i != 8; ++i)
+ {
+ h[i] ^= hN[i] ^ m64[i];
+ }
}
} //namespace
diff --git a/src/lib/mac/mac.cpp b/src/lib/mac/mac.cpp
index c48deb24b..053e36b6f 100644
--- a/src/lib/mac/mac.cpp
+++ b/src/lib/mac/mac.cpp
@@ -155,7 +155,7 @@ bool MessageAuthenticationCode::verify_mac(const uint8_t mac[], size_t length)
if(our_mac.size() != length)
return false;
- return same_mem(our_mac.data(), mac, length);
+ return constant_time_compare(our_mac.data(), mac, length);
}
}
diff --git a/src/lib/misc/cryptobox/cryptobox.cpp b/src/lib/misc/cryptobox/cryptobox.cpp
index 944adef49..0ff6fe8f5 100644
--- a/src/lib/misc/cryptobox/cryptobox.cpp
+++ b/src/lib/misc/cryptobox/cryptobox.cpp
@@ -145,7 +145,7 @@ std::string decrypt(const uint8_t input[], size_t input_len,
uint8_t computed_mac[MAC_OUTPUT_LEN];
BOTAN_ASSERT_EQUAL(MAC_OUTPUT_LEN, pipe.read(computed_mac, MAC_OUTPUT_LEN, 1), "MAC size");
- if(!same_mem(computed_mac,
+ if(!constant_time_compare(computed_mac,
&ciphertext[VERSION_CODE_LEN + PBKDF_SALT_LEN],
MAC_OUTPUT_LEN))
throw Decoding_Error("CryptoBox integrity failure");
diff --git a/src/lib/misc/tss/tss.cpp b/src/lib/misc/tss/tss.cpp
index a7b0c4eac..2039e5fea 100644
--- a/src/lib/misc/tss/tss.cpp
+++ b/src/lib/misc/tss/tss.cpp
@@ -250,9 +250,12 @@ RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares)
hash->update(secret.data(), secret_len);
secure_vector<uint8_t> hash_check = hash->final();
- if(!same_mem(hash_check.data(),
- &secret[secret_len], hash->output_length()))
+ if(!constant_time_compare(hash_check.data(),
+ &secret[secret_len],
+ hash->output_length()))
+ {
throw Decoding_Error("RTSS hash check failed");
+ }
return secure_vector<uint8_t>(secret.cbegin(), secret.cbegin() + secret_len);
}
diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp
index b7f81e5ab..5a1de4908 100644
--- a/src/lib/modes/aead/ccm/ccm.cpp
+++ b/src/lib/modes/aead/ccm/ccm.cpp
@@ -260,7 +260,7 @@ void CCM_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
T ^= S0;
- if(!same_mem(T.data(), buf_end, tag_size()))
+ if(!constant_time_compare(T.data(), buf_end, tag_size()))
throw Integrity_Failure("CCM tag check failed");
buffer.resize(buffer.size() - tag_size());
diff --git a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp
index 64169a9b8..e1fd4978c 100644
--- a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp
+++ b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp
@@ -157,7 +157,7 @@ void ChaCha20Poly1305_Decryption::finish(secure_vector<uint8_t>& buffer, size_t
m_ctext_len = 0;
- if(!same_mem(mac.data(), included_tag, tag_size()))
+ if(!constant_time_compare(mac.data(), included_tag, tag_size()))
throw Integrity_Failure("ChaCha20Poly1305 tag check failed");
buffer.resize(offset + remaining);
}
diff --git a/src/lib/modes/aead/eax/eax.cpp b/src/lib/modes/aead/eax/eax.cpp
index 4889ac21a..66cd90151 100644
--- a/src/lib/modes/aead/eax/eax.cpp
+++ b/src/lib/modes/aead/eax/eax.cpp
@@ -169,7 +169,7 @@ void EAX_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
mac ^= m_ad_mac;
- if(!same_mem(mac.data(), included_tag, tag_size()))
+ if(!constant_time_compare(mac.data(), included_tag, tag_size()))
throw Integrity_Failure("EAX tag check failed");
buffer.resize(offset + remaining);
diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp
index f9ffdee97..9c6a85282 100644
--- a/src/lib/modes/aead/gcm/gcm.cpp
+++ b/src/lib/modes/aead/gcm/gcm.cpp
@@ -182,7 +182,9 @@ GCM_Mode::GCM_Mode(BlockCipher* cipher, size_t tag_size) :
m_ctr.reset(new CTR_BE(cipher, 4)); // CTR_BE takes ownership of cipher
- if(m_tag_size != 8 && m_tag_size != GCM_BS)
+ /* We allow any of the values 128, 120, 112, 104, or 96 bits as a tag size */
+ /* 64 bit tag is still supported but deprecated and will be removed in the future */
+ if(m_tag_size != 8 && (m_tag_size < 12 || m_tag_size > 16))
throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(m_tag_size));
}
@@ -315,7 +317,7 @@ void GCM_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
const uint8_t* included_tag = &buffer[remaining+offset];
- if(!same_mem(mac.data(), included_tag, tag_size()))
+ if(!constant_time_compare(mac.data(), included_tag, tag_size()))
throw Integrity_Failure("GCM tag check failed");
buffer.resize(offset + remaining);
diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp
index e580c95d9..a48f0751a 100644
--- a/src/lib/modes/aead/ocb/ocb.cpp
+++ b/src/lib/modes/aead/ocb/ocb.cpp
@@ -478,7 +478,7 @@ void OCB_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
// compare mac
const uint8_t* included_tag = &buf[remaining];
- if(!same_mem(mac.data(), included_tag, tag_size()))
+ if(!constant_time_compare(mac.data(), included_tag, tag_size()))
throw Integrity_Failure("OCB tag check failed");
// remove tag from end of message
diff --git a/src/lib/modes/cbc/cbc.cpp b/src/lib/modes/cbc/cbc.cpp
index fbe56da82..c67664a6e 100644
--- a/src/lib/modes/cbc/cbc.cpp
+++ b/src/lib/modes/cbc/cbc.cpp
@@ -54,12 +54,12 @@ Key_Length_Specification CBC_Mode::key_spec() const
size_t CBC_Mode::default_nonce_length() const
{
- return cipher().block_size();
+ return block_size();
}
bool CBC_Mode::valid_nonce_length(size_t n) const
{
- return (n == 0 || n == cipher().block_size());
+ return (n == 0 || n == block_size());
}
void CBC_Mode::key_schedule(const uint8_t key[], size_t length)
@@ -89,27 +89,27 @@ size_t CBC_Encryption::minimum_final_size() const
size_t CBC_Encryption::output_length(size_t input_length) const
{
if(input_length == 0)
- return cipher().block_size();
+ return block_size();
else
- return round_up(input_length, cipher().block_size());
+ return round_up(input_length, block_size());
}
size_t CBC_Encryption::process(uint8_t buf[], size_t sz)
{
- const size_t BS = cipher().block_size();
+ const size_t BS = block_size();
BOTAN_ASSERT(sz % BS == 0, "CBC input is full blocks");
const size_t blocks = sz / BS;
- const uint8_t* prev_block = state_ptr();
-
- if(blocks)
+ if(blocks > 0)
{
- for(size_t i = 0; i != blocks; ++i)
+ xor_buf(&buf[0], state_ptr(), BS);
+ cipher().encrypt(&buf[0]);
+
+ for(size_t i = 1; i != blocks; ++i)
{
- xor_buf(&buf[BS*i], prev_block, BS);
+ xor_buf(&buf[BS*i], &buf[BS*(i-1)], BS);
cipher().encrypt(&buf[BS*i]);
- prev_block = &buf[BS*i];
}
state().assign(&buf[BS*(blocks-1)], &buf[BS*blocks]);
@@ -122,7 +122,7 @@ void CBC_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
{
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
- const size_t BS = cipher().block_size();
+ const size_t BS = block_size();
const size_t bytes_in_final_block = (buffer.size()-offset) % BS;
@@ -136,12 +136,12 @@ void CBC_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
bool CTS_Encryption::valid_nonce_length(size_t n) const
{
- return (n == cipher().block_size());
+ return (n == block_size());
}
size_t CTS_Encryption::minimum_final_size() const
{
- return cipher().block_size() + 1;
+ return block_size() + 1;
}
size_t CTS_Encryption::output_length(size_t input_length) const
@@ -155,7 +155,7 @@ void CTS_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
uint8_t* buf = buffer.data() + offset;
const size_t sz = buffer.size() - offset;
- const size_t BS = cipher().block_size();
+ const size_t BS = block_size();
if(sz < BS + 1)
throw Encoding_Error(name() + ": insufficient data to encrypt");
@@ -200,12 +200,12 @@ size_t CBC_Decryption::output_length(size_t input_length) const
size_t CBC_Decryption::minimum_final_size() const
{
- return cipher().block_size();
+ return block_size();
}
size_t CBC_Decryption::process(uint8_t buf[], size_t sz)
{
- const size_t BS = cipher().block_size();
+ const size_t BS = block_size();
BOTAN_ASSERT(sz % BS == 0, "Input is full blocks");
size_t blocks = sz / BS;
@@ -234,7 +234,7 @@ void CBC_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
const size_t sz = buffer.size() - offset;
- const size_t BS = cipher().block_size();
+ const size_t BS = block_size();
if(sz == 0 || sz % BS)
throw Decoding_Error(name() + ": Ciphertext not a multiple of block size");
@@ -257,12 +257,12 @@ void CBC_Decryption::reset()
bool CTS_Decryption::valid_nonce_length(size_t n) const
{
- return (n == cipher().block_size());
+ return (n == block_size());
}
size_t CTS_Decryption::minimum_final_size() const
{
- return cipher().block_size() + 1;
+ return block_size() + 1;
}
void CTS_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
@@ -271,7 +271,7 @@ void CTS_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
const size_t sz = buffer.size() - offset;
uint8_t* buf = buffer.data() + offset;
- const size_t BS = cipher().block_size();
+ const size_t BS = block_size();
if(sz < BS + 1)
throw Encoding_Error(name() + ": insufficient data to decrypt");
diff --git a/src/lib/modes/cbc/cbc.h b/src/lib/modes/cbc/cbc.h
index a44a9b5d9..54b574981 100644
--- a/src/lib/modes/cbc/cbc.h
+++ b/src/lib/modes/cbc/cbc.h
@@ -48,6 +48,8 @@ class BOTAN_DLL CBC_Mode : public Cipher_Mode
secure_vector<uint8_t>& state() { return m_state; }
+ size_t block_size() const { return m_state.size(); }
+
uint8_t* state_ptr() { return m_state.data(); }
private:
diff --git a/src/lib/modes/cfb/cfb.cpp b/src/lib/modes/cfb/cfb.cpp
index 56d234090..d22f1a35b 100644
--- a/src/lib/modes/cfb/cfb.cpp
+++ b/src/lib/modes/cfb/cfb.cpp
@@ -1,6 +1,6 @@
/*
* CFB Mode
-* (C) 1999-2007,2013 Jack Lloyd
+* (C) 1999-2007,2013,2017 Jack Lloyd
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -28,8 +28,8 @@ void CFB_Mode::clear()
void CFB_Mode::reset()
{
- m_shift_register.clear();
- m_keystream_buf.clear();
+ m_state.clear();
+ m_keystream.clear();
}
std::string CFB_Mode::name() const
@@ -82,44 +82,46 @@ void CFB_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
if(nonce_len == 0)
{
- if(m_shift_register.empty())
+ if(m_state.empty())
{
throw Invalid_State("CFB requires a non-empty initial nonce");
}
+ // No reason to encrypt state->keystream_buf, because no change
}
else
{
- m_shift_register.assign(nonce, nonce + nonce_len);
+ m_state.assign(nonce, nonce + nonce_len);
+ m_keystream.resize(m_state.size());
+ cipher().encrypt(m_state, m_keystream);
+ m_keystream_pos = 0;
}
-
- m_keystream_buf.resize(m_shift_register.size());
- cipher().encrypt(m_shift_register, m_keystream_buf);
}
size_t CFB_Encryption::process(uint8_t buf[], size_t sz)
{
const size_t BS = cipher().block_size();
- secure_vector<uint8_t>& state = shift_register();
const size_t shift = feedback();
- size_t left = sz;
+ const size_t carryover = BS - shift;
- while(left)
+ for(size_t i = 0; i != sz; ++i)
{
- const size_t took = std::min(shift, left);
- xor_buf(buf, &keystream_buf()[0], took);
+ buf[i] = (m_keystream[m_keystream_pos] ^= buf[i]);
+
+ m_keystream_pos++;
- // Assumes feedback-sized block except for last input
- if (BS - shift > 0)
+ if(m_keystream_pos == shift)
{
- copy_mem(state.data(), &state[shift], BS - shift);
+ if(carryover > 0)
+ {
+ copy_mem(m_state.data(), &m_state[shift], carryover);
+ }
+ copy_mem(&m_state[carryover], m_keystream.data(), shift);
+ cipher().encrypt(m_state, m_keystream);
+ m_keystream_pos = 0;
}
- copy_mem(&state[BS-shift], buf, took);
- cipher().encrypt(state, keystream_buf());
-
- buf += took;
- left -= took;
}
+
return sz;
}
@@ -131,31 +133,29 @@ void CFB_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
size_t CFB_Decryption::process(uint8_t buf[], size_t sz)
{
const size_t BS = cipher().block_size();
-
- secure_vector<uint8_t>& state = shift_register();
const size_t shift = feedback();
- size_t left = sz;
+ const size_t carryover = BS - shift;
- while(left)
+ for(size_t i = 0; i != sz; ++i)
{
- const size_t took = std::min(shift, left);
+ uint8_t k = m_keystream[m_keystream_pos];
+ m_keystream[m_keystream_pos] = buf[i];
+ buf[i] ^= k;
- // first update shift register with ciphertext
- if (BS - shift > 0)
+ m_keystream_pos++;
+
+ if(m_keystream_pos == shift)
{
- copy_mem(state.data(), &state[shift], BS - shift);
+ if(carryover > 0)
+ {
+ copy_mem(m_state.data(), &m_state[shift], carryover);
+ }
+ copy_mem(&m_state[carryover], m_keystream.data(), shift);
+ cipher().encrypt(m_state, m_keystream);
+ m_keystream_pos = 0;
}
- copy_mem(&state[BS-shift], buf, took);
-
- // then decrypt
- xor_buf(buf, &keystream_buf()[0], took);
-
- // then update keystream
- cipher().encrypt(state, keystream_buf());
-
- buf += took;
- left -= took;
}
+
return sz;
}
diff --git a/src/lib/modes/cfb/cfb.h b/src/lib/modes/cfb/cfb.h
index a128539a4..ce85d2c2e 100644
--- a/src/lib/modes/cfb/cfb.h
+++ b/src/lib/modes/cfb/cfb.h
@@ -40,22 +40,19 @@ class BOTAN_DLL CFB_Mode : public Cipher_Mode
protected:
CFB_Mode(BlockCipher* cipher, size_t feedback_bits);
- const BlockCipher& cipher() const { return *m_cipher; }
-
size_t feedback() const { return m_feedback_bytes; }
+ const BlockCipher& cipher() const { return *m_cipher; }
- secure_vector<uint8_t>& shift_register() { return m_shift_register; }
-
- secure_vector<uint8_t>& keystream_buf() { return m_keystream_buf; }
+ secure_vector<uint8_t> m_state;
+ secure_vector<uint8_t> m_keystream;
+ size_t m_keystream_pos = 0;
private:
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
void key_schedule(const uint8_t key[], size_t length) override;
std::unique_ptr<BlockCipher> m_cipher;
- secure_vector<uint8_t> m_shift_register;
- secure_vector<uint8_t> m_keystream_buf;
- size_t m_feedback_bytes;
+ const size_t m_feedback_bytes;
};
/**
diff --git a/src/lib/passhash/bcrypt/bcrypt.cpp b/src/lib/passhash/bcrypt/bcrypt.cpp
index 4f3cda2ae..73456dead 100644
--- a/src/lib/passhash/bcrypt/bcrypt.cpp
+++ b/src/lib/passhash/bcrypt/bcrypt.cpp
@@ -90,14 +90,12 @@ std::string make_bcrypt(const std::string& pass,
const std::vector<uint8_t>& salt,
uint16_t work_factor)
{
- auto magic = std::vector<uint8_t>{
+ static const uint8_t BCRYPT_MAGIC[8*3] = {
0x4F, 0x72, 0x70, 0x68, 0x65, 0x61, 0x6E, 0x42,
0x65, 0x68, 0x6F, 0x6C, 0x64, 0x65, 0x72, 0x53,
0x63, 0x72, 0x79, 0x44, 0x6F, 0x75, 0x62, 0x74
};
- std::vector<uint8_t> ctext = magic;
-
Blowfish blowfish;
// Include the trailing NULL byte
@@ -106,6 +104,8 @@ std::string make_bcrypt(const std::string& pass,
salt.data(),
work_factor);
+ std::vector<uint8_t> ctext(BCRYPT_MAGIC, BCRYPT_MAGIC + 8*3);
+
for(size_t i = 0; i != 64; ++i)
blowfish.encrypt_n(ctext.data(), ctext.data(), 3);
diff --git a/src/lib/passhash/passhash9/passhash9.cpp b/src/lib/passhash/passhash9/passhash9.cpp
index e78ac5012..1fa88c8c4 100644
--- a/src/lib/passhash/passhash9/passhash9.cpp
+++ b/src/lib/passhash/passhash9/passhash9.cpp
@@ -122,7 +122,7 @@ bool check_passhash9(const std::string& pass, const std::string& hash)
&bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
kdf_iterations).bits_of();
- return same_mem(cmp.data(),
+ return constant_time_compare(cmp.data(),
&bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES],
PASSHASH9_PBKDF_OUTPUT_LEN);
}
diff --git a/src/lib/pk_pad/eme_oaep/oaep.cpp b/src/lib/pk_pad/eme_oaep/oaep.cpp
index ef2fb81bb..71f5c14e0 100644
--- a/src/lib/pk_pad/eme_oaep/oaep.cpp
+++ b/src/lib/pk_pad/eme_oaep/oaep.cpp
@@ -106,7 +106,7 @@ secure_vector<uint8_t> OAEP::unpad(uint8_t& valid_mask,
// If we never saw any non-zero byte, then it's not valid input
bad_input |= waiting_for_delim;
- bad_input |= CT::is_equal<uint8_t>(same_mem(&input[hlen], m_Phash.data(), hlen), false);
+ bad_input |= CT::is_equal<uint8_t>(constant_time_compare(&input[hlen], m_Phash.data(), hlen), false);
CT::unpoison(input.data(), input.size());
CT::unpoison(&bad_input, 1);
diff --git a/src/lib/pk_pad/emsa1/emsa1.cpp b/src/lib/pk_pad/emsa1/emsa1.cpp
index 82c3b86a7..e3580ff93 100644
--- a/src/lib/pk_pad/emsa1/emsa1.cpp
+++ b/src/lib/pk_pad/emsa1/emsa1.cpp
@@ -85,7 +85,7 @@ bool EMSA1::verify(const secure_vector<uint8_t>& input,
if(our_coding[i] != 0)
return false;
- return same_mem(input.data(), &our_coding[offset], input.size());
+ return constant_time_compare(input.data(), &our_coding[offset], input.size());
}
catch(Invalid_Argument)
{
diff --git a/src/lib/pk_pad/emsa_pssr/pssr.cpp b/src/lib/pk_pad/emsa_pssr/pssr.cpp
index 5f76b5a6f..65ee5a145 100644
--- a/src/lib/pk_pad/emsa_pssr/pssr.cpp
+++ b/src/lib/pk_pad/emsa_pssr/pssr.cpp
@@ -122,7 +122,7 @@ bool PSSR::verify(const secure_vector<uint8_t>& const_coded,
m_hash->update(&DB[salt_offset], DB_size - salt_offset);
secure_vector<uint8_t> H2 = m_hash->final();
- return same_mem(H, H2.data(), HASH_SIZE);
+ return constant_time_compare(H, H2.data(), HASH_SIZE);
}
PSSR::PSSR(HashFunction* h) :
diff --git a/src/lib/pk_pad/emsa_raw/emsa_raw.cpp b/src/lib/pk_pad/emsa_raw/emsa_raw.cpp
index bae7b2d04..cf2426298 100644
--- a/src/lib/pk_pad/emsa_raw/emsa_raw.cpp
+++ b/src/lib/pk_pad/emsa_raw/emsa_raw.cpp
@@ -75,7 +75,7 @@ bool EMSA_Raw::verify(const secure_vector<uint8_t>& coded,
if(raw[i])
same_modulo_leading_zeros = false;
- if(!same_mem(coded.data(), raw.data() + leading_zeros_expected, coded.size()))
+ if(!constant_time_compare(coded.data(), raw.data() + leading_zeros_expected, coded.size()))
same_modulo_leading_zeros = false;
return same_modulo_leading_zeros;
diff --git a/src/lib/pk_pad/iso9796/iso9796.cpp b/src/lib/pk_pad/iso9796/iso9796.cpp
index 6dcae799a..8608e7239 100644
--- a/src/lib/pk_pad/iso9796/iso9796.cpp
+++ b/src/lib/pk_pad/iso9796/iso9796.cpp
@@ -202,7 +202,7 @@ bool iso9796_verification(const secure_vector<uint8_t>& const_coded,
secure_vector<uint8_t> H2 = hash->final();
//check if H3 == H2
- bad_input |= CT::is_equal<uint8_t>(same_mem(H3.data(), H2.data(), HASH_SIZE), false);
+ bad_input |= CT::is_equal<uint8_t>(constant_time_compare(H3.data(), H2.data(), HASH_SIZE), false);
CT::unpoison(bad_input);
return (bad_input == 0);
diff --git a/src/lib/prov/openssl/openssl_ec.cpp b/src/lib/prov/openssl/openssl_ec.cpp
index 4e68258ef..4d26661ac 100644
--- a/src/lib/prov/openssl/openssl_ec.cpp
+++ b/src/lib/prov/openssl/openssl_ec.cpp
@@ -74,7 +74,7 @@ int OpenSSL_EC_curve_builtin(int nid)
return -1;
}
- for(int i=0; i < num; ++i)
+ for(size_t i = 0; i < num; ++i)
{
if(builtin_curves[i].nid == nid)
{
diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp
index a4171a55f..a4603f0d7 100644
--- a/src/lib/pubkey/dlies/dlies.cpp
+++ b/src/lib/pubkey/dlies/dlies.cpp
@@ -175,7 +175,7 @@ secure_vector<uint8_t> DLIES_Decryptor::do_decrypt(uint8_t& valid_mask,
secure_vector<uint8_t> tag(msg + m_pub_key_size + ciphertext_len,
msg + m_pub_key_size + ciphertext_len + m_mac->output_length());
- valid_mask = CT::expand_mask<uint8_t>(same_mem(tag.data(), calculated_tag.data(), tag.size()));
+ valid_mask = CT::expand_mask<uint8_t>(constant_time_compare(tag.data(), calculated_tag.data(), tag.size()));
// decrypt
if(m_cipher)
diff --git a/src/lib/pubkey/ecc_key/ecc_key.cpp b/src/lib/pubkey/ecc_key/ecc_key.cpp
index ad62f6ae3..7274a3cd9 100644
--- a/src/lib/pubkey/ecc_key/ecc_key.cpp
+++ b/src/lib/pubkey/ecc_key/ecc_key.cpp
@@ -177,9 +177,6 @@ EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
.decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE)
.end_cons();
- if(!key_parameters.empty() && key_parameters != alg_id.oid)
- throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match");
-
if(public_key_bits.empty())
{
m_public_key = domain().get_base_point() *
diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp
index df676cfb3..b8fcea64b 100644
--- a/src/lib/pubkey/ecies/ecies.cpp
+++ b/src/lib/pubkey/ecies/ecies.cpp
@@ -363,7 +363,7 @@ secure_vector<uint8_t> ECIES_Decryptor::do_decrypt(uint8_t& valid_mask, const ui
mac->update(m_label);
}
const secure_vector<uint8_t> calculated_mac = mac->final();
- valid_mask = CT::expand_mask<uint8_t>(same_mem(mac_data.data(), calculated_mac.data(), mac_data.size()));
+ valid_mask = CT::expand_mask<uint8_t>(constant_time_compare(mac_data.data(), calculated_mac.data(), mac_data.size()));
if(valid_mask)
{
diff --git a/src/lib/pubkey/ed25519/ed25519.cpp b/src/lib/pubkey/ed25519/ed25519.cpp
index 13f75ac3b..5c9bd2b3d 100644
--- a/src/lib/pubkey/ed25519/ed25519.cpp
+++ b/src/lib/pubkey/ed25519/ed25519.cpp
@@ -90,7 +90,7 @@ bool ed25519_verify(const uint8_t* m, size_t mlen,
ge_double_scalarmult_vartime(rcheck, h, &A, sig + 32);
- return same_mem(rcheck, sig, 32);
+ return constant_time_compare(rcheck, sig, 32);
}
}
diff --git a/src/lib/pubkey/ed25519/ed25519_fe.cpp b/src/lib/pubkey/ed25519/ed25519_fe.cpp
index 8087aaff1..067c9dc18 100644
--- a/src/lib/pubkey/ed25519/ed25519_fe.cpp
+++ b/src/lib/pubkey/ed25519/ed25519_fe.cpp
@@ -150,106 +150,106 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
int32_t f5_2 = 2 * f5;
int32_t f7_2 = 2 * f7;
int32_t f9_2 = 2 * f9;
- int64_t f0g0 = f0 * (int64_t) g0;
- int64_t f0g1 = f0 * (int64_t) g1;
- int64_t f0g2 = f0 * (int64_t) g2;
- int64_t f0g3 = f0 * (int64_t) g3;
- int64_t f0g4 = f0 * (int64_t) g4;
- int64_t f0g5 = f0 * (int64_t) g5;
- int64_t f0g6 = f0 * (int64_t) g6;
- int64_t f0g7 = f0 * (int64_t) g7;
- int64_t f0g8 = f0 * (int64_t) g8;
- int64_t f0g9 = f0 * (int64_t) g9;
- int64_t f1g0 = f1 * (int64_t) g0;
- int64_t f1g1_2 = f1_2 * (int64_t) g1;
- int64_t f1g2 = f1 * (int64_t) g2;
- int64_t f1g3_2 = f1_2 * (int64_t) g3;
- int64_t f1g4 = f1 * (int64_t) g4;
- int64_t f1g5_2 = f1_2 * (int64_t) g5;
- int64_t f1g6 = f1 * (int64_t) g6;
- int64_t f1g7_2 = f1_2 * (int64_t) g7;
- int64_t f1g8 = f1 * (int64_t) g8;
- int64_t f1g9_38 = f1_2 * (int64_t) g9_19;
- int64_t f2g0 = f2 * (int64_t) g0;
- int64_t f2g1 = f2 * (int64_t) g1;
- int64_t f2g2 = f2 * (int64_t) g2;
- int64_t f2g3 = f2 * (int64_t) g3;
- int64_t f2g4 = f2 * (int64_t) g4;
- int64_t f2g5 = f2 * (int64_t) g5;
- int64_t f2g6 = f2 * (int64_t) g6;
- int64_t f2g7 = f2 * (int64_t) g7;
- int64_t f2g8_19 = f2 * (int64_t) g8_19;
- int64_t f2g9_19 = f2 * (int64_t) g9_19;
- int64_t f3g0 = f3 * (int64_t) g0;
- int64_t f3g1_2 = f3_2 * (int64_t) g1;
- int64_t f3g2 = f3 * (int64_t) g2;
- int64_t f3g3_2 = f3_2 * (int64_t) g3;
- int64_t f3g4 = f3 * (int64_t) g4;
- int64_t f3g5_2 = f3_2 * (int64_t) g5;
- int64_t f3g6 = f3 * (int64_t) g6;
- int64_t f3g7_38 = f3_2 * (int64_t) g7_19;
- int64_t f3g8_19 = f3 * (int64_t) g8_19;
- int64_t f3g9_38 = f3_2 * (int64_t) g9_19;
- int64_t f4g0 = f4 * (int64_t) g0;
- int64_t f4g1 = f4 * (int64_t) g1;
- int64_t f4g2 = f4 * (int64_t) g2;
- int64_t f4g3 = f4 * (int64_t) g3;
- int64_t f4g4 = f4 * (int64_t) g4;
- int64_t f4g5 = f4 * (int64_t) g5;
- int64_t f4g6_19 = f4 * (int64_t) g6_19;
- int64_t f4g7_19 = f4 * (int64_t) g7_19;
- int64_t f4g8_19 = f4 * (int64_t) g8_19;
- int64_t f4g9_19 = f4 * (int64_t) g9_19;
- int64_t f5g0 = f5 * (int64_t) g0;
- int64_t f5g1_2 = f5_2 * (int64_t) g1;
- int64_t f5g2 = f5 * (int64_t) g2;
- int64_t f5g3_2 = f5_2 * (int64_t) g3;
- int64_t f5g4 = f5 * (int64_t) g4;
- int64_t f5g5_38 = f5_2 * (int64_t) g5_19;
- int64_t f5g6_19 = f5 * (int64_t) g6_19;
- int64_t f5g7_38 = f5_2 * (int64_t) g7_19;
- int64_t f5g8_19 = f5 * (int64_t) g8_19;
- int64_t f5g9_38 = f5_2 * (int64_t) g9_19;
- int64_t f6g0 = f6 * (int64_t) g0;
- int64_t f6g1 = f6 * (int64_t) g1;
- int64_t f6g2 = f6 * (int64_t) g2;
- int64_t f6g3 = f6 * (int64_t) g3;
- int64_t f6g4_19 = f6 * (int64_t) g4_19;
- int64_t f6g5_19 = f6 * (int64_t) g5_19;
- int64_t f6g6_19 = f6 * (int64_t) g6_19;
- int64_t f6g7_19 = f6 * (int64_t) g7_19;
- int64_t f6g8_19 = f6 * (int64_t) g8_19;
- int64_t f6g9_19 = f6 * (int64_t) g9_19;
- int64_t f7g0 = f7 * (int64_t) g0;
- int64_t f7g1_2 = f7_2 * (int64_t) g1;
- int64_t f7g2 = f7 * (int64_t) g2;
- int64_t f7g3_38 = f7_2 * (int64_t) g3_19;
- int64_t f7g4_19 = f7 * (int64_t) g4_19;
- int64_t f7g5_38 = f7_2 * (int64_t) g5_19;
- int64_t f7g6_19 = f7 * (int64_t) g6_19;
- int64_t f7g7_38 = f7_2 * (int64_t) g7_19;
- int64_t f7g8_19 = f7 * (int64_t) g8_19;
- int64_t f7g9_38 = f7_2 * (int64_t) g9_19;
- int64_t f8g0 = f8 * (int64_t) g0;
- int64_t f8g1 = f8 * (int64_t) g1;
- int64_t f8g2_19 = f8 * (int64_t) g2_19;
- int64_t f8g3_19 = f8 * (int64_t) g3_19;
- int64_t f8g4_19 = f8 * (int64_t) g4_19;
- int64_t f8g5_19 = f8 * (int64_t) g5_19;
- int64_t f8g6_19 = f8 * (int64_t) g6_19;
- int64_t f8g7_19 = f8 * (int64_t) g7_19;
- int64_t f8g8_19 = f8 * (int64_t) g8_19;
- int64_t f8g9_19 = f8 * (int64_t) g9_19;
- int64_t f9g0 = f9 * (int64_t) g0;
- int64_t f9g1_38 = f9_2 * (int64_t) g1_19;
- int64_t f9g2_19 = f9 * (int64_t) g2_19;
- int64_t f9g3_38 = f9_2 * (int64_t) g3_19;
- int64_t f9g4_19 = f9 * (int64_t) g4_19;
- int64_t f9g5_38 = f9_2 * (int64_t) g5_19;
- int64_t f9g6_19 = f9 * (int64_t) g6_19;
- int64_t f9g7_38 = f9_2 * (int64_t) g7_19;
- int64_t f9g8_19 = f9 * (int64_t) g8_19;
- int64_t f9g9_38 = f9_2 * (int64_t) g9_19;
+ int64_t f0g0 = f0 * static_cast<int64_t>(g0);
+ int64_t f0g1 = f0 * static_cast<int64_t>(g1);
+ int64_t f0g2 = f0 * static_cast<int64_t>(g2);
+ int64_t f0g3 = f0 * static_cast<int64_t>(g3);
+ int64_t f0g4 = f0 * static_cast<int64_t>(g4);
+ int64_t f0g5 = f0 * static_cast<int64_t>(g5);
+ int64_t f0g6 = f0 * static_cast<int64_t>(g6);
+ int64_t f0g7 = f0 * static_cast<int64_t>(g7);
+ int64_t f0g8 = f0 * static_cast<int64_t>(g8);
+ int64_t f0g9 = f0 * static_cast<int64_t>(g9);
+ int64_t f1g0 = f1 * static_cast<int64_t>(g0);
+ int64_t f1g1_2 = f1_2 * static_cast<int64_t>(g1);
+ int64_t f1g2 = f1 * static_cast<int64_t>(g2);
+ int64_t f1g3_2 = f1_2 * static_cast<int64_t>(g3);
+ int64_t f1g4 = f1 * static_cast<int64_t>(g4);
+ int64_t f1g5_2 = f1_2 * static_cast<int64_t>(g5);
+ int64_t f1g6 = f1 * static_cast<int64_t>(g6);
+ int64_t f1g7_2 = f1_2 * static_cast<int64_t>(g7);
+ int64_t f1g8 = f1 * static_cast<int64_t>(g8);
+ int64_t f1g9_38 = f1_2 * static_cast<int64_t>(g9_19);
+ int64_t f2g0 = f2 * static_cast<int64_t>(g0);
+ int64_t f2g1 = f2 * static_cast<int64_t>(g1);
+ int64_t f2g2 = f2 * static_cast<int64_t>(g2);
+ int64_t f2g3 = f2 * static_cast<int64_t>(g3);
+ int64_t f2g4 = f2 * static_cast<int64_t>(g4);
+ int64_t f2g5 = f2 * static_cast<int64_t>(g5);
+ int64_t f2g6 = f2 * static_cast<int64_t>(g6);
+ int64_t f2g7 = f2 * static_cast<int64_t>(g7);
+ int64_t f2g8_19 = f2 * static_cast<int64_t>(g8_19);
+ int64_t f2g9_19 = f2 * static_cast<int64_t>(g9_19);
+ int64_t f3g0 = f3 * static_cast<int64_t>(g0);
+ int64_t f3g1_2 = f3_2 * static_cast<int64_t>(g1);
+ int64_t f3g2 = f3 * static_cast<int64_t>(g2);
+ int64_t f3g3_2 = f3_2 * static_cast<int64_t>(g3);
+ int64_t f3g4 = f3 * static_cast<int64_t>(g4);
+ int64_t f3g5_2 = f3_2 * static_cast<int64_t>(g5);
+ int64_t f3g6 = f3 * static_cast<int64_t>(g6);
+ int64_t f3g7_38 = f3_2 * static_cast<int64_t>(g7_19);
+ int64_t f3g8_19 = f3 * static_cast<int64_t>(g8_19);
+ int64_t f3g9_38 = f3_2 * static_cast<int64_t>(g9_19);
+ int64_t f4g0 = f4 * static_cast<int64_t>(g0);
+ int64_t f4g1 = f4 * static_cast<int64_t>(g1);
+ int64_t f4g2 = f4 * static_cast<int64_t>(g2);
+ int64_t f4g3 = f4 * static_cast<int64_t>(g3);
+ int64_t f4g4 = f4 * static_cast<int64_t>(g4);
+ int64_t f4g5 = f4 * static_cast<int64_t>(g5);
+ int64_t f4g6_19 = f4 * static_cast<int64_t>(g6_19);
+ int64_t f4g7_19 = f4 * static_cast<int64_t>(g7_19);
+ int64_t f4g8_19 = f4 * static_cast<int64_t>(g8_19);
+ int64_t f4g9_19 = f4 * static_cast<int64_t>(g9_19);
+ int64_t f5g0 = f5 * static_cast<int64_t>(g0);
+ int64_t f5g1_2 = f5_2 * static_cast<int64_t>(g1);
+ int64_t f5g2 = f5 * static_cast<int64_t>(g2);
+ int64_t f5g3_2 = f5_2 * static_cast<int64_t>(g3);
+ int64_t f5g4 = f5 * static_cast<int64_t>(g4);
+ int64_t f5g5_38 = f5_2 * static_cast<int64_t>(g5_19);
+ int64_t f5g6_19 = f5 * static_cast<int64_t>(g6_19);
+ int64_t f5g7_38 = f5_2 * static_cast<int64_t>(g7_19);
+ int64_t f5g8_19 = f5 * static_cast<int64_t>(g8_19);
+ int64_t f5g9_38 = f5_2 * static_cast<int64_t>(g9_19);
+ int64_t f6g0 = f6 * static_cast<int64_t>(g0);
+ int64_t f6g1 = f6 * static_cast<int64_t>(g1);
+ int64_t f6g2 = f6 * static_cast<int64_t>(g2);
+ int64_t f6g3 = f6 * static_cast<int64_t>(g3);
+ int64_t f6g4_19 = f6 * static_cast<int64_t>(g4_19);
+ int64_t f6g5_19 = f6 * static_cast<int64_t>(g5_19);
+ int64_t f6g6_19 = f6 * static_cast<int64_t>(g6_19);
+ int64_t f6g7_19 = f6 * static_cast<int64_t>(g7_19);
+ int64_t f6g8_19 = f6 * static_cast<int64_t>(g8_19);
+ int64_t f6g9_19 = f6 * static_cast<int64_t>(g9_19);
+ int64_t f7g0 = f7 * static_cast<int64_t>(g0);
+ int64_t f7g1_2 = f7_2 * static_cast<int64_t>(g1);
+ int64_t f7g2 = f7 * static_cast<int64_t>(g2);
+ int64_t f7g3_38 = f7_2 * static_cast<int64_t>(g3_19);
+ int64_t f7g4_19 = f7 * static_cast<int64_t>(g4_19);
+ int64_t f7g5_38 = f7_2 * static_cast<int64_t>(g5_19);
+ int64_t f7g6_19 = f7 * static_cast<int64_t>(g6_19);
+ int64_t f7g7_38 = f7_2 * static_cast<int64_t>(g7_19);
+ int64_t f7g8_19 = f7 * static_cast<int64_t>(g8_19);
+ int64_t f7g9_38 = f7_2 * static_cast<int64_t>(g9_19);
+ int64_t f8g0 = f8 * static_cast<int64_t>(g0);
+ int64_t f8g1 = f8 * static_cast<int64_t>(g1);
+ int64_t f8g2_19 = f8 * static_cast<int64_t>(g2_19);
+ int64_t f8g3_19 = f8 * static_cast<int64_t>(g3_19);
+ int64_t f8g4_19 = f8 * static_cast<int64_t>(g4_19);
+ int64_t f8g5_19 = f8 * static_cast<int64_t>(g5_19);
+ int64_t f8g6_19 = f8 * static_cast<int64_t>(g6_19);
+ int64_t f8g7_19 = f8 * static_cast<int64_t>(g7_19);
+ int64_t f8g8_19 = f8 * static_cast<int64_t>(g8_19);
+ int64_t f8g9_19 = f8 * static_cast<int64_t>(g9_19);
+ int64_t f9g0 = f9 * static_cast<int64_t>(g0);
+ int64_t f9g1_38 = f9_2 * static_cast<int64_t>(g1_19);
+ int64_t f9g2_19 = f9 * static_cast<int64_t>(g2_19);
+ int64_t f9g3_38 = f9_2 * static_cast<int64_t>(g3_19);
+ int64_t f9g4_19 = f9 * static_cast<int64_t>(g4_19);
+ int64_t f9g5_38 = f9_2 * static_cast<int64_t>(g5_19);
+ int64_t f9g6_19 = f9 * static_cast<int64_t>(g6_19);
+ int64_t f9g7_38 = f9_2 * static_cast<int64_t>(g7_19);
+ int64_t f9g8_19 = f9 * static_cast<int64_t>(g8_19);
+ int64_t f9g9_38 = f9_2 * static_cast<int64_t>(g9_19);
int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
int64_t h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
int64_t h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
@@ -278,10 +278,10 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
*/
- carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
/* |h0| <= 2^25 */
@@ -289,10 +289,10 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
/* |h1| <= 1.71*2^59 */
/* |h5| <= 1.71*2^59 */
- carry1 = (h1 + (int64_t)(1<<24)) >> 25;
+ carry1 = (h1 + (static_cast<int64_t>(1) << 24)) >> 25;
h2 += carry1;
h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t)(1<<24)) >> 25;
+ carry5 = (h5 + (static_cast<int64_t>(1) << 24)) >> 25;
h6 += carry5;
h5 -= carry5 << 25;
/* |h1| <= 2^24; from now on fits into int32 */
@@ -300,10 +300,10 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
/* |h2| <= 1.41*2^60 */
/* |h6| <= 1.41*2^60 */
- carry2 = (h2 + (int64_t)(1<<25)) >> 26;
+ carry2 = (h2 + (static_cast<int64_t>(1) << 25)) >> 26;
h3 += carry2;
h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t)(1<<25)) >> 26;
+ carry6 = (h6 + (static_cast<int64_t>(1) << 25)) >> 26;
h7 += carry6;
h6 -= carry6 << 26;
/* |h2| <= 2^25; from now on fits into int32 unchanged */
@@ -311,10 +311,10 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
/* |h3| <= 1.71*2^59 */
/* |h7| <= 1.71*2^59 */
- carry3 = (h3 + (int64_t)(1<<24)) >> 25;
+ carry3 = (h3 + (static_cast<int64_t>(1) << 24)) >> 25;
h4 += carry3;
h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t)(1<<24)) >> 25;
+ carry7 = (h7 + (static_cast<int64_t>(1) << 24)) >> 25;
h8 += carry7;
h7 -= carry7 << 25;
/* |h3| <= 2^24; from now on fits into int32 unchanged */
@@ -322,10 +322,10 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
/* |h4| <= 1.72*2^34 */
/* |h8| <= 1.41*2^60 */
- carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t)(1<<25)) >> 26;
+ carry8 = (h8 + (static_cast<int64_t>(1) << 25)) >> 26;
h9 += carry8;
h8 -= carry8 << 26;
/* |h4| <= 2^25; from now on fits into int32 unchanged */
@@ -333,13 +333,13 @@ FE_25519 FE_25519::mul(const FE_25519& f, const FE_25519& g)
/* |h5| <= 1.01*2^24 */
/* |h9| <= 1.71*2^59 */
- carry9 = (h9 + (int64_t)(1<<24)) >> 25;
+ carry9 = (h9 + (static_cast<int64_t>(1) << 24)) >> 25;
h0 += carry9 * 19;
h9 -= carry9 << 25;
/* |h9| <= 2^24; from now on fits into int32 unchanged */
/* |h0| <= 1.1*2^39 */
- carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
/* |h0| <= 2^25; from now on fits into int32 unchanged */
@@ -393,61 +393,61 @@ FE_25519 FE_25519::sqr_iter(const FE_25519& f, size_t iter)
const int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
const int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
- const int64_t f0f0 = f0 * (int64_t) f0;
- const int64_t f0f1_2 = f0_2 * (int64_t) f1;
- const int64_t f0f2_2 = f0_2 * (int64_t) f2;
- const int64_t f0f3_2 = f0_2 * (int64_t) f3;
- const int64_t f0f4_2 = f0_2 * (int64_t) f4;
- const int64_t f0f5_2 = f0_2 * (int64_t) f5;
- const int64_t f0f6_2 = f0_2 * (int64_t) f6;
- const int64_t f0f7_2 = f0_2 * (int64_t) f7;
- const int64_t f0f8_2 = f0_2 * (int64_t) f8;
- const int64_t f0f9_2 = f0_2 * (int64_t) f9;
- const int64_t f1f1_2 = f1_2 * (int64_t) f1;
- const int64_t f1f2_2 = f1_2 * (int64_t) f2;
- const int64_t f1f3_4 = f1_2 * (int64_t) f3_2;
- const int64_t f1f4_2 = f1_2 * (int64_t) f4;
- const int64_t f1f5_4 = f1_2 * (int64_t) f5_2;
- const int64_t f1f6_2 = f1_2 * (int64_t) f6;
- const int64_t f1f7_4 = f1_2 * (int64_t) f7_2;
- const int64_t f1f8_2 = f1_2 * (int64_t) f8;
- const int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
- const int64_t f2f2 = f2 * (int64_t) f2;
- const int64_t f2f3_2 = f2_2 * (int64_t) f3;
- const int64_t f2f4_2 = f2_2 * (int64_t) f4;
- const int64_t f2f5_2 = f2_2 * (int64_t) f5;
- const int64_t f2f6_2 = f2_2 * (int64_t) f6;
- const int64_t f2f7_2 = f2_2 * (int64_t) f7;
- const int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
- const int64_t f2f9_38 = f2 * (int64_t) f9_38;
- const int64_t f3f3_2 = f3_2 * (int64_t) f3;
- const int64_t f3f4_2 = f3_2 * (int64_t) f4;
- const int64_t f3f5_4 = f3_2 * (int64_t) f5_2;
- const int64_t f3f6_2 = f3_2 * (int64_t) f6;
- const int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
- const int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
- const int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
- const int64_t f4f4 = f4 * (int64_t) f4;
- const int64_t f4f5_2 = f4_2 * (int64_t) f5;
- const int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
- const int64_t f4f7_38 = f4 * (int64_t) f7_38;
- const int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
- const int64_t f4f9_38 = f4 * (int64_t) f9_38;
- const int64_t f5f5_38 = f5 * (int64_t) f5_38;
- const int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
- const int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
- const int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
- const int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
- const int64_t f6f6_19 = f6 * (int64_t) f6_19;
- const int64_t f6f7_38 = f6 * (int64_t) f7_38;
- const int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
- const int64_t f6f9_38 = f6 * (int64_t) f9_38;
- const int64_t f7f7_38 = f7 * (int64_t) f7_38;
- const int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
- const int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
- const int64_t f8f8_19 = f8 * (int64_t) f8_19;
- const int64_t f8f9_38 = f8 * (int64_t) f9_38;
- const int64_t f9f9_38 = f9 * (int64_t) f9_38;
+ const int64_t f0f0 = f0 * static_cast<int64_t>(f0);
+ const int64_t f0f1_2 = f0_2 * static_cast<int64_t>(f1);
+ const int64_t f0f2_2 = f0_2 * static_cast<int64_t>(f2);
+ const int64_t f0f3_2 = f0_2 * static_cast<int64_t>(f3);
+ const int64_t f0f4_2 = f0_2 * static_cast<int64_t>(f4);
+ const int64_t f0f5_2 = f0_2 * static_cast<int64_t>(f5);
+ const int64_t f0f6_2 = f0_2 * static_cast<int64_t>(f6);
+ const int64_t f0f7_2 = f0_2 * static_cast<int64_t>(f7);
+ const int64_t f0f8_2 = f0_2 * static_cast<int64_t>(f8);
+ const int64_t f0f9_2 = f0_2 * static_cast<int64_t>(f9);
+ const int64_t f1f1_2 = f1_2 * static_cast<int64_t>(f1);
+ const int64_t f1f2_2 = f1_2 * static_cast<int64_t>(f2);
+ const int64_t f1f3_4 = f1_2 * static_cast<int64_t>(f3_2);
+ const int64_t f1f4_2 = f1_2 * static_cast<int64_t>(f4);
+ const int64_t f1f5_4 = f1_2 * static_cast<int64_t>(f5_2);
+ const int64_t f1f6_2 = f1_2 * static_cast<int64_t>(f6);
+ const int64_t f1f7_4 = f1_2 * static_cast<int64_t>(f7_2);
+ const int64_t f1f8_2 = f1_2 * static_cast<int64_t>(f8);
+ const int64_t f1f9_76 = f1_2 * static_cast<int64_t>(f9_38);
+ const int64_t f2f2 = f2 * static_cast<int64_t>(f2);
+ const int64_t f2f3_2 = f2_2 * static_cast<int64_t>(f3);
+ const int64_t f2f4_2 = f2_2 * static_cast<int64_t>(f4);
+ const int64_t f2f5_2 = f2_2 * static_cast<int64_t>(f5);
+ const int64_t f2f6_2 = f2_2 * static_cast<int64_t>(f6);
+ const int64_t f2f7_2 = f2_2 * static_cast<int64_t>(f7);
+ const int64_t f2f8_38 = f2_2 * static_cast<int64_t>(f8_19);
+ const int64_t f2f9_38 = f2 * static_cast<int64_t>(f9_38);
+ const int64_t f3f3_2 = f3_2 * static_cast<int64_t>(f3);
+ const int64_t f3f4_2 = f3_2 * static_cast<int64_t>(f4);
+ const int64_t f3f5_4 = f3_2 * static_cast<int64_t>(f5_2);
+ const int64_t f3f6_2 = f3_2 * static_cast<int64_t>(f6);
+ const int64_t f3f7_76 = f3_2 * static_cast<int64_t>(f7_38);
+ const int64_t f3f8_38 = f3_2 * static_cast<int64_t>(f8_19);
+ const int64_t f3f9_76 = f3_2 * static_cast<int64_t>(f9_38);
+ const int64_t f4f4 = f4 * static_cast<int64_t>(f4);
+ const int64_t f4f5_2 = f4_2 * static_cast<int64_t>(f5);
+ const int64_t f4f6_38 = f4_2 * static_cast<int64_t>(f6_19);
+ const int64_t f4f7_38 = f4 * static_cast<int64_t>(f7_38);
+ const int64_t f4f8_38 = f4_2 * static_cast<int64_t>(f8_19);
+ const int64_t f4f9_38 = f4 * static_cast<int64_t>(f9_38);
+ const int64_t f5f5_38 = f5 * static_cast<int64_t>(f5_38);
+ const int64_t f5f6_38 = f5_2 * static_cast<int64_t>(f6_19);
+ const int64_t f5f7_76 = f5_2 * static_cast<int64_t>(f7_38);
+ const int64_t f5f8_38 = f5_2 * static_cast<int64_t>(f8_19);
+ const int64_t f5f9_76 = f5_2 * static_cast<int64_t>(f9_38);
+ const int64_t f6f6_19 = f6 * static_cast<int64_t>(f6_19);
+ const int64_t f6f7_38 = f6 * static_cast<int64_t>(f7_38);
+ const int64_t f6f8_38 = f6_2 * static_cast<int64_t>(f8_19);
+ const int64_t f6f9_38 = f6 * static_cast<int64_t>(f9_38);
+ const int64_t f7f7_38 = f7 * static_cast<int64_t>(f7_38);
+ const int64_t f7f8_38 = f7_2 * static_cast<int64_t>(f8_19);
+ const int64_t f7f9_76 = f7_2 * static_cast<int64_t>(f9_38);
+ const int64_t f8f8_19 = f8 * static_cast<int64_t>(f8_19);
+ const int64_t f8f9_38 = f8 * static_cast<int64_t>(f9_38);
+ const int64_t f9f9_38 = f9 * static_cast<int64_t>(f9_38);
int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
@@ -471,45 +471,45 @@ FE_25519 FE_25519::sqr_iter(const FE_25519& f, size_t iter)
int64_t carry8;
int64_t carry9;
- carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
- carry1 = (h1 + (int64_t)(1<<24)) >> 25;
+ carry1 = (h1 + (static_cast<int64_t>(1) << 24)) >> 25;
h2 += carry1;
h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t)(1<<24)) >> 25;
+ carry5 = (h5 + (static_cast<int64_t>(1) << 24)) >> 25;
h6 += carry5;
h5 -= carry5 << 25;
- carry2 = (h2 + (int64_t)(1<<25)) >> 26;
+ carry2 = (h2 + (static_cast<int64_t>(1) << 25)) >> 26;
h3 += carry2;
h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t)(1<<25)) >> 26;
+ carry6 = (h6 + (static_cast<int64_t>(1) << 25)) >> 26;
h7 += carry6;
h6 -= carry6 << 26;
- carry3 = (h3 + (int64_t)(1<<24)) >> 25;
+ carry3 = (h3 + (static_cast<int64_t>(1) << 24)) >> 25;
h4 += carry3;
h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t)(1<<24)) >> 25;
+ carry7 = (h7 + (static_cast<int64_t>(1) << 24)) >> 25;
h8 += carry7;
h7 -= carry7 << 25;
- carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t)(1<<25)) >> 26;
+ carry8 = (h8 + (static_cast<int64_t>(1) << 25)) >> 26;
h9 += carry8;
h8 -= carry8 << 26;
- carry9 = (h9 + (int64_t)(1<<24)) >> 25;
+ carry9 = (h9 + (static_cast<int64_t>(1) << 24)) >> 25;
h0 += carry9 * 19;
h9 -= carry9 << 25;
- carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
@@ -569,61 +569,61 @@ FE_25519 FE_25519::sqr2(const FE_25519& f)
int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
- int64_t f0f0 = f0 * (int64_t) f0;
- int64_t f0f1_2 = f0_2 * (int64_t) f1;
- int64_t f0f2_2 = f0_2 * (int64_t) f2;
- int64_t f0f3_2 = f0_2 * (int64_t) f3;
- int64_t f0f4_2 = f0_2 * (int64_t) f4;
- int64_t f0f5_2 = f0_2 * (int64_t) f5;
- int64_t f0f6_2 = f0_2 * (int64_t) f6;
- int64_t f0f7_2 = f0_2 * (int64_t) f7;
- int64_t f0f8_2 = f0_2 * (int64_t) f8;
- int64_t f0f9_2 = f0_2 * (int64_t) f9;
- int64_t f1f1_2 = f1_2 * (int64_t) f1;
- int64_t f1f2_2 = f1_2 * (int64_t) f2;
- int64_t f1f3_4 = f1_2 * (int64_t) f3_2;
- int64_t f1f4_2 = f1_2 * (int64_t) f4;
- int64_t f1f5_4 = f1_2 * (int64_t) f5_2;
- int64_t f1f6_2 = f1_2 * (int64_t) f6;
- int64_t f1f7_4 = f1_2 * (int64_t) f7_2;
- int64_t f1f8_2 = f1_2 * (int64_t) f8;
- int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
- int64_t f2f2 = f2 * (int64_t) f2;
- int64_t f2f3_2 = f2_2 * (int64_t) f3;
- int64_t f2f4_2 = f2_2 * (int64_t) f4;
- int64_t f2f5_2 = f2_2 * (int64_t) f5;
- int64_t f2f6_2 = f2_2 * (int64_t) f6;
- int64_t f2f7_2 = f2_2 * (int64_t) f7;
- int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
- int64_t f2f9_38 = f2 * (int64_t) f9_38;
- int64_t f3f3_2 = f3_2 * (int64_t) f3;
- int64_t f3f4_2 = f3_2 * (int64_t) f4;
- int64_t f3f5_4 = f3_2 * (int64_t) f5_2;
- int64_t f3f6_2 = f3_2 * (int64_t) f6;
- int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
- int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
- int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
- int64_t f4f4 = f4 * (int64_t) f4;
- int64_t f4f5_2 = f4_2 * (int64_t) f5;
- int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
- int64_t f4f7_38 = f4 * (int64_t) f7_38;
- int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
- int64_t f4f9_38 = f4 * (int64_t) f9_38;
- int64_t f5f5_38 = f5 * (int64_t) f5_38;
- int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
- int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
- int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
- int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
- int64_t f6f6_19 = f6 * (int64_t) f6_19;
- int64_t f6f7_38 = f6 * (int64_t) f7_38;
- int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
- int64_t f6f9_38 = f6 * (int64_t) f9_38;
- int64_t f7f7_38 = f7 * (int64_t) f7_38;
- int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
- int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
- int64_t f8f8_19 = f8 * (int64_t) f8_19;
- int64_t f8f9_38 = f8 * (int64_t) f9_38;
- int64_t f9f9_38 = f9 * (int64_t) f9_38;
+ int64_t f0f0 = f0 * static_cast<int64_t>(f0);
+ int64_t f0f1_2 = f0_2 * static_cast<int64_t>(f1);
+ int64_t f0f2_2 = f0_2 * static_cast<int64_t>(f2);
+ int64_t f0f3_2 = f0_2 * static_cast<int64_t>(f3);
+ int64_t f0f4_2 = f0_2 * static_cast<int64_t>(f4);
+ int64_t f0f5_2 = f0_2 * static_cast<int64_t>(f5);
+ int64_t f0f6_2 = f0_2 * static_cast<int64_t>(f6);
+ int64_t f0f7_2 = f0_2 * static_cast<int64_t>(f7);
+ int64_t f0f8_2 = f0_2 * static_cast<int64_t>(f8);
+ int64_t f0f9_2 = f0_2 * static_cast<int64_t>(f9);
+ int64_t f1f1_2 = f1_2 * static_cast<int64_t>(f1);
+ int64_t f1f2_2 = f1_2 * static_cast<int64_t>(f2);
+ int64_t f1f3_4 = f1_2 * static_cast<int64_t>(f3_2);
+ int64_t f1f4_2 = f1_2 * static_cast<int64_t>(f4);
+ int64_t f1f5_4 = f1_2 * static_cast<int64_t>(f5_2);
+ int64_t f1f6_2 = f1_2 * static_cast<int64_t>(f6);
+ int64_t f1f7_4 = f1_2 * static_cast<int64_t>(f7_2);
+ int64_t f1f8_2 = f1_2 * static_cast<int64_t>(f8);
+ int64_t f1f9_76 = f1_2 * static_cast<int64_t>(f9_38);
+ int64_t f2f2 = f2 * static_cast<int64_t>(f2);
+ int64_t f2f3_2 = f2_2 * static_cast<int64_t>(f3);
+ int64_t f2f4_2 = f2_2 * static_cast<int64_t>(f4);
+ int64_t f2f5_2 = f2_2 * static_cast<int64_t>(f5);
+ int64_t f2f6_2 = f2_2 * static_cast<int64_t>(f6);
+ int64_t f2f7_2 = f2_2 * static_cast<int64_t>(f7);
+ int64_t f2f8_38 = f2_2 * static_cast<int64_t>(f8_19);
+ int64_t f2f9_38 = f2 * static_cast<int64_t>(f9_38);
+ int64_t f3f3_2 = f3_2 * static_cast<int64_t>(f3);
+ int64_t f3f4_2 = f3_2 * static_cast<int64_t>(f4);
+ int64_t f3f5_4 = f3_2 * static_cast<int64_t>(f5_2);
+ int64_t f3f6_2 = f3_2 * static_cast<int64_t>(f6);
+ int64_t f3f7_76 = f3_2 * static_cast<int64_t>(f7_38);
+ int64_t f3f8_38 = f3_2 * static_cast<int64_t>(f8_19);
+ int64_t f3f9_76 = f3_2 * static_cast<int64_t>(f9_38);
+ int64_t f4f4 = f4 * static_cast<int64_t>(f4);
+ int64_t f4f5_2 = f4_2 * static_cast<int64_t>(f5);
+ int64_t f4f6_38 = f4_2 * static_cast<int64_t>(f6_19);
+ int64_t f4f7_38 = f4 * static_cast<int64_t>(f7_38);
+ int64_t f4f8_38 = f4_2 * static_cast<int64_t>(f8_19);
+ int64_t f4f9_38 = f4 * static_cast<int64_t>(f9_38);
+ int64_t f5f5_38 = f5 * static_cast<int64_t>(f5_38);
+ int64_t f5f6_38 = f5_2 * static_cast<int64_t>(f6_19);
+ int64_t f5f7_76 = f5_2 * static_cast<int64_t>(f7_38);
+ int64_t f5f8_38 = f5_2 * static_cast<int64_t>(f8_19);
+ int64_t f5f9_76 = f5_2 * static_cast<int64_t>(f9_38);
+ int64_t f6f6_19 = f6 * static_cast<int64_t>(f6_19);
+ int64_t f6f7_38 = f6 * static_cast<int64_t>(f7_38);
+ int64_t f6f8_38 = f6_2 * static_cast<int64_t>(f8_19);
+ int64_t f6f9_38 = f6 * static_cast<int64_t>(f9_38);
+ int64_t f7f7_38 = f7 * static_cast<int64_t>(f7_38);
+ int64_t f7f8_38 = f7_2 * static_cast<int64_t>(f8_19);
+ int64_t f7f9_76 = f7_2 * static_cast<int64_t>(f9_38);
+ int64_t f8f8_19 = f8 * static_cast<int64_t>(f8_19);
+ int64_t f8f9_38 = f8 * static_cast<int64_t>(f9_38);
+ int64_t f9f9_38 = f9 * static_cast<int64_t>(f9_38);
int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
@@ -656,46 +656,46 @@ FE_25519 FE_25519::sqr2(const FE_25519& f)
h8 += h8;
h9 += h9;
- carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
- carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
- carry1 = (h1 + (int64_t)(1<<24)) >> 25;
+ carry1 = (h1 + (static_cast<int64_t>(1) << 24)) >> 25;
h2 += carry1;
h1 -= carry1 << 25;
- carry5 = (h5 + (int64_t)(1<<24)) >> 25;
+ carry5 = (h5 + (static_cast<int64_t>(1) << 24)) >> 25;
h6 += carry5;
h5 -= carry5 << 25;
- carry2 = (h2 + (int64_t)(1<<25)) >> 26;
+ carry2 = (h2 + (static_cast<int64_t>(1) << 25)) >> 26;
h3 += carry2;
h2 -= carry2 << 26;
- carry6 = (h6 + (int64_t)(1<<25)) >> 26;
+ carry6 = (h6 + (static_cast<int64_t>(1) << 25)) >> 26;
h7 += carry6;
h6 -= carry6 << 26;
- carry3 = (h3 + (int64_t)(1<<24)) >> 25;
+ carry3 = (h3 + (static_cast<int64_t>(1) << 24)) >> 25;
h4 += carry3;
h3 -= carry3 << 25;
- carry7 = (h7 + (int64_t)(1<<24)) >> 25;
+ carry7 = (h7 + (static_cast<int64_t>(1) << 24)) >> 25;
h8 += carry7;
h7 -= carry7 << 25;
- carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
- carry8 = (h8 + (int64_t)(1<<25)) >> 26;
+ carry8 = (h8 + (static_cast<int64_t>(1) << 25)) >> 26;
h9 += carry8;
h8 -= carry8 << 26;
- carry9 = (h9 + (int64_t)(1<<24)) >> 25;
+ carry9 = (h9 + (static_cast<int64_t>(1) << 24)) >> 25;
h0 += carry9 * 19;
h9 -= carry9 << 25;
- carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
@@ -719,35 +719,35 @@ void FE_25519::from_bytes(const uint8_t s[32])
int64_t h8 = load_3(s + 26) << 4;
int64_t h9 = (load_3(s + 29) & 0x7fffff) << 2;
- const int64_t carry9 = (h9 + (int64_t)(1<<24)) >> 25;
+ const int64_t carry9 = (h9 + (static_cast<int64_t>(1) << 24)) >> 25;
h0 += carry9 * 19;
h9 -= carry9 << 25;
- const int64_t carry1 = (h1 + (int64_t)(1<<24)) >> 25;
+ const int64_t carry1 = (h1 + (static_cast<int64_t>(1) << 24)) >> 25;
h2 += carry1;
h1 -= carry1 << 25;
- const int64_t carry3 = (h3 + (int64_t)(1<<24)) >> 25;
+ const int64_t carry3 = (h3 + (static_cast<int64_t>(1) << 24)) >> 25;
h4 += carry3;
h3 -= carry3 << 25;
- const int64_t carry5 = (h5 + (int64_t)(1<<24)) >> 25;
+ const int64_t carry5 = (h5 + (static_cast<int64_t>(1) << 24)) >> 25;
h6 += carry5;
h5 -= carry5 << 25;
- const int64_t carry7 = (h7 + (int64_t)(1<<24)) >> 25;
+ const int64_t carry7 = (h7 + (static_cast<int64_t>(1) << 24)) >> 25;
h8 += carry7;
h7 -= carry7 << 25;
- const int64_t carry0 = (h0 + (int64_t)(1<<25)) >> 26;
+ const int64_t carry0 = (h0 + (static_cast<int64_t>(1) << 25)) >> 26;
h1 += carry0;
h0 -= carry0 << 26;
- const int64_t carry2 = (h2 + (int64_t)(1<<25)) >> 26;
+ const int64_t carry2 = (h2 + (static_cast<int64_t>(1) << 25)) >> 26;
h3 += carry2;
h2 -= carry2 << 26;
- const int64_t carry4 = (h4 + (int64_t)(1<<25)) >> 26;
+ const int64_t carry4 = (h4 + (static_cast<int64_t>(1) << 25)) >> 26;
h5 += carry4;
h4 -= carry4 << 26;
- const int64_t carry6 = (h6 + (int64_t)(1<<25)) >> 26;
+ const int64_t carry6 = (h6 + (static_cast<int64_t>(1) << 25)) >> 26;
h7 += carry6;
h6 -= carry6 << 26;
- const int64_t carry8 = (h8 + (int64_t)(1<<25)) >> 26;
+ const int64_t carry8 = (h8 + (static_cast<int64_t>(1) << 25)) >> 26;
h9 += carry8;
h8 -= carry8 << 26;
@@ -812,7 +812,7 @@ void FE_25519::to_bytes(uint8_t s[32]) const
int32_t carry8;
int32_t carry9;
- q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
+ q = (19 * h9 + ((static_cast<int32_t>(1) << 24))) >> 25;
q = (h0 + q) >> 26;
q = (h1 + q) >> 25;
q = (h2 + q) >> 26;
diff --git a/src/lib/pubkey/ed25519/ed25519_internal.h b/src/lib/pubkey/ed25519/ed25519_internal.h
index 2a86bb30e..8a0ccf44c 100644
--- a/src/lib/pubkey/ed25519/ed25519_internal.h
+++ b/src/lib/pubkey/ed25519/ed25519_internal.h
@@ -16,24 +16,16 @@
namespace Botan {
-inline uint64_t load_3(const uint8_t* in)
+inline uint64_t load_3(const uint8_t in[3])
{
- uint64_t result;
- result = (uint64_t) in[0];
- result |= ((uint64_t) in[1]) << 8;
- result |= ((uint64_t) in[2]) << 16;
- return result;
+ return static_cast<uint64_t>(in[0]) |
+ (static_cast<uint64_t>(in[1]) << 8) |
+ (static_cast<uint64_t>(in[2]) << 16);
}
inline uint64_t load_4(const uint8_t* in)
{
- uint64_t result;
- result = (uint64_t) in[0];
- result |= ((uint64_t) in[1]) << 8;
- result |= ((uint64_t) in[2]) << 16;
- result |= ((uint64_t) in[3]) << 24;
- return result;
- //return load_le<uint32_t>(in, 0);
+ return load_le<uint32_t>(in, 0);
}
/*
diff --git a/src/lib/pubkey/sm2/sm2_enc.cpp b/src/lib/pubkey/sm2/sm2_enc.cpp
index b05ce12da..aca31941d 100644
--- a/src/lib/pubkey/sm2/sm2_enc.cpp
+++ b/src/lib/pubkey/sm2/sm2_enc.cpp
@@ -190,7 +190,7 @@ class SM2_Decryption_Operation : public PK_Ops::Decryption
hash->update(y2_bytes);
secure_vector<uint8_t> u = hash->final();
- if(same_mem(u.data(), ciphertext + (1+p_bytes*2), hash->output_length()) == false)
+ if(constant_time_compare(u.data(), ciphertext + (1+p_bytes*2), hash->output_length()) == false)
return secure_vector<uint8_t>();
valid_mask = 0xFF;
diff --git a/src/lib/tls/msg_finished.cpp b/src/lib/tls/msg_finished.cpp
index f00311729..0fbfc0738 100644
--- a/src/lib/tls/msg_finished.cpp
+++ b/src/lib/tls/msg_finished.cpp
@@ -81,7 +81,7 @@ bool Finished::verify(const Handshake_State& state,
return true;
#else
return (m_verification_data.size() == computed_verify.size()) &&
- same_mem(m_verification_data.data(), computed_verify.data(), computed_verify.size());
+ constant_time_compare(m_verification_data.data(), computed_verify.data(), computed_verify.size());
#endif
}
diff --git a/src/lib/tls/tls_cbc/tls_cbc.cpp b/src/lib/tls/tls_cbc/tls_cbc.cpp
index e63893d75..244ddfb99 100644
--- a/src/lib/tls/tls_cbc/tls_cbc.cpp
+++ b/src/lib/tls/tls_cbc/tls_cbc.cpp
@@ -397,7 +397,7 @@ void TLS_CBC_HMAC_AEAD_Decryption::finish(secure_vector<uint8_t>& buffer, size_t
const size_t mac_offset = enc_size;
- const bool mac_ok = same_mem(&record_contents[mac_offset], mac_buf.data(), tag_size());
+ const bool mac_ok = constant_time_compare(&record_contents[mac_offset], mac_buf.data(), tag_size());
if(!mac_ok)
{
@@ -459,7 +459,7 @@ void TLS_CBC_HMAC_AEAD_Decryption::finish(secure_vector<uint8_t>& buffer, size_t
const size_t mac_offset = record_len - (tag_size() + pad_size);
- const bool mac_ok = same_mem(&record_contents[mac_offset], mac_buf.data(), tag_size());
+ const bool mac_ok = constant_time_compare(&record_contents[mac_offset], mac_buf.data(), tag_size());
const uint16_t ok_mask = size_ok_mask & CT::expand_mask<uint16_t>(mac_ok) & CT::expand_mask<uint16_t>(pad_size);
diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp
deleted file mode 100644
index ed3fbc4b2..000000000
--- a/src/lib/utils/cpuid.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
-* Runtime CPU detection
-* (C) 2009,2010,2013,2017 Jack Lloyd
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#include <botan/cpuid.h>
-#include <botan/types.h>
-#include <botan/loadstor.h>
-#include <botan/exceptn.h>
-#include <botan/mem_ops.h>
-#include <botan/parsing.h>
-#include <botan/internal/os_utils.h>
-#include <ostream>
-
-#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
-
-/*
-* On Darwin and OpenBSD ppc, use sysctl to detect AltiVec
-*/
-#if defined(BOTAN_TARGET_OS_IS_DARWIN)
- #include <sys/sysctl.h>
-#elif defined(BOTAN_TARGET_OS_IS_OPENBSD)
- #include <sys/param.h>
- #include <sys/sysctl.h>
- #include <machine/cpu.h>
-#endif
-
-#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
-
-/*
-* On ARM, use getauxval if available, otherwise fall back to
-* running probe functions with a SIGILL handler.
-*/
-#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)
- #include <sys/auxv.h>
-#endif
-
-#elif defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
-
-/*
-* On x86, use CPUID instruction
-*/
-
-#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
- #include <intrin.h>
-#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
- #include <ia32intrin.h>
-#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
- #include <cpuid.h>
-#endif
-
-#endif
-
-namespace Botan {
-
-uint64_t CPUID::g_processor_features = 0;
-size_t CPUID::g_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
-CPUID::Endian_status CPUID::g_endian_status = ENDIAN_UNKNOWN;
-
-namespace {
-
-#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
-
-/*
-* PowerPC specific block: check for AltiVec using either
-* sysctl or by reading processor version number register.
-*/
-uint64_t detect_cpu_features(size_t* cache_line_size)
- {
-#if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD)
- // On Darwin/OS X and OpenBSD, use sysctl
-
- int sels[2] = {
-#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
- CTL_MACHDEP, CPU_ALTIVEC
-#else
- CTL_HW, HW_VECTORUNIT
-#endif
- };
-
- int vector_type = 0;
- size_t length = sizeof(vector_type);
- int error = sysctl(sels, 2, &vector_type, &length, NULL, 0);
-
- if(error == 0 && vector_type > 0)
- return CPUID::CPUID_ALTIVEC_BIT;
-
-#else
-
- /*
- On PowerPC, MSR 287 is PVR, the Processor Version Number
- Normally it is only accessible to ring 0, but Linux and NetBSD
- (others, too, maybe?) will trap and emulate it for us.
- */
-
- int pvr = OS::run_cpu_instruction_probe([]() -> int {
- uint32_t pvr = 0;
- asm volatile("mfspr %0, 287" : "=r" (pvr));
- // Top 16 bits suffice to identify the model
- return static_cast<int>(pvr >> 16);
- });
-
- if(pvr > 0)
- {
- const uint16_t ALTIVEC_PVR[] = {
- 0x003E, // IBM POWER6,
- 0x003F, // IBM POWER7,
- 0x004B, // IBM POWER8,
- 0x000C, // G4-7400
- 0x0039, // G5 970
- 0x003C, // G5 970FX
- 0x0044, // G5 970MP
- 0x0070, // Cell PPU
- 0, // end
- };
-
- for(size_t i = 0; ALTIVEC_PVR[i]; ++i)
- {
- if(pvr == ALTIVEC_PVR[i])
- return CPUID::CPUID_ALTIVEC_BIT;
- }
-
- return 0;
- }
-
- // TODO try direct instruction probing
-
-#endif
-
- return 0;
- }
-
-#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
-
-uint64_t detect_cpu_features(size_t* cache_line_size)
- {
- uint64_t detected_features = 0;
-
-#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)
- /*
- * On systems with getauxval these bits should normally be defined
- * in bits/auxv.h but some buggy? glibc installs seem to miss them.
- * These following values are all fixed, for the Linux ELF format,
- * so we just hardcode them in ARM_hwcap_bit enum.
- */
-
- enum ARM_hwcap_bit {
-#if defined(BOTAN_TARGET_ARCH_IS_ARM32)
- NEON_bit = (1 << 12),
- AES_bit = (1 << 0),
- PMULL_bit = (1 << 1),
- SHA1_bit = (1 << 2),
- SHA2_bit = (1 << 3),
-
- ARCH_hwcap_neon = 16, // AT_HWCAP
- ARCH_hwcap_crypto = 26, // AT_HWCAP2
-#elif defined(BOTAN_TARGET_ARCH_IS_ARM64)
- NEON_bit = (1 << 1),
- AES_bit = (1 << 3),
- PMULL_bit = (1 << 4),
- SHA1_bit = (1 << 5),
- SHA2_bit = (1 << 6),
-
- ARCH_hwcap_neon = 16, // AT_HWCAP
- ARCH_hwcap_crypto = 16, // AT_HWCAP
-#endif
- };
-
- const unsigned long hwcap_neon = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_neon);
- if(hwcap_neon & ARM_hwcap_bit::NEON_bit)
- detected_features |= CPUID::CPUID_ARM_NEON_BIT;
-
- /*
- On aarch64 this ends up calling getauxval twice with AT_HWCAP
- It doesn't seem worth optimizing this out, since getauxval is
- just reading a field in the ELF header.
- */
- const unsigned long hwcap_crypto = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_crypto);
- if(hwcap_crypto & ARM_hwcap_bit::AES_bit)
- detected_features |= CPUID::CPUID_ARM_AES_BIT;
- if(hwcap_crypto & ARM_hwcap_bit::PMULL_bit)
- detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
- if(hwcap_crypto & ARM_hwcap_bit::SHA1_bit)
- detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
- if(hwcap_crypto & ARM_hwcap_bit::SHA2_bit)
- detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
-
-#if defined(AT_DCACHEBSIZE)
- const unsigned long dcache_line = ::getauxval(AT_DCACHEBSIZE);
-
- // plausibility check
- if(dcache_line == 32 || dcache_line == 64 || dcache_line == 128)
- *cache_line_size = static_cast<size_t>(dcache_line);
-#endif
-
-#else
- // No getauxval API available, fall back on probe functions
-
- // TODO: probe functions
-
-#endif
-
- return detected_features;
- }
-
-#elif defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
-
-uint64_t detect_cpu_features(size_t* cache_line_size)
- {
-#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
- #define X86_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
- #define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuidex((int*)out, type, level); } while(0)
-
-#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
- #define X86_CPUID(type, out) do { __cpuid(out, type); } while(0)
- #define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuidex((int*)out, type, level); } while(0)
-
-#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && defined(BOTAN_USE_GCC_INLINE_ASM)
- #define X86_CPUID(type, out) \
- asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
- : "0" (type))
-
- #define X86_CPUID_SUBLEVEL(type, level, out) \
- asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
- : "0" (type), "2" (level))
-
-#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
- #define X86_CPUID(type, out) do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0)
-
- #define X86_CPUID_SUBLEVEL(type, level, out) \
- do { __cpuid_count(type, level, out[0], out[1], out[2], out[3]); } while(0)
-#else
- #warning "No way of calling x86 cpuid instruction for this compiler"
- #define X86_CPUID(type, out) do { clear_mem(out, 4); } while(0)
- #define X86_CPUID_SUBLEVEL(type, level, out) do { clear_mem(out, 4); } while(0)
-#endif
-
- uint64_t features_detected = 0;
- uint32_t cpuid[4] = { 0 };
-
- // CPUID 0: vendor identification, max sublevel
- X86_CPUID(0, cpuid);
-
- const uint32_t max_supported_sublevel = cpuid[0];
-
- const uint32_t INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
- const uint32_t AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
- const bool is_intel = same_mem(cpuid + 1, INTEL_CPUID, 3);
- const bool is_amd = same_mem(cpuid + 1, AMD_CPUID, 3);
-
- if(max_supported_sublevel >= 1)
- {
- // CPUID 1: feature bits
- X86_CPUID(1, cpuid);
- const uint64_t flags0 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[3];
-
- enum x86_CPUID_1_bits : uint64_t {
- RDTSC = (1ULL << 4),
- SSE2 = (1ULL << 26),
- CLMUL = (1ULL << 33),
- SSSE3 = (1ULL << 41),
- SSE41 = (1ULL << 51),
- SSE42 = (1ULL << 52),
- AESNI = (1ULL << 57),
- RDRAND = (1ULL << 62)
- };
-
- if(flags0 & x86_CPUID_1_bits::RDTSC)
- features_detected |= CPUID::CPUID_RDTSC_BIT;
- if(flags0 & x86_CPUID_1_bits::SSE2)
- features_detected |= CPUID::CPUID_SSE2_BIT;
- if(flags0 & x86_CPUID_1_bits::CLMUL)
- features_detected |= CPUID::CPUID_CLMUL_BIT;
- if(flags0 & x86_CPUID_1_bits::SSSE3)
- features_detected |= CPUID::CPUID_SSSE3_BIT;
- if(flags0 & x86_CPUID_1_bits::SSE41)
- features_detected |= CPUID::CPUID_SSE41_BIT;
- if(flags0 & x86_CPUID_1_bits::SSE42)
- features_detected |= CPUID::CPUID_SSE42_BIT;
- if(flags0 & x86_CPUID_1_bits::AESNI)
- features_detected |= CPUID::CPUID_AESNI_BIT;
- if(flags0 & x86_CPUID_1_bits::RDRAND)
- features_detected |= CPUID::CPUID_RDRAND_BIT;
- }
-
- if(is_intel)
- {
- // Intel cache line size is in cpuid(1) output
- *cache_line_size = 8 * get_byte(2, cpuid[1]);
- }
- else if(is_amd)
- {
- // AMD puts it in vendor zone
- X86_CPUID(0x80000005, cpuid);
- *cache_line_size = get_byte(3, cpuid[2]);
- }
-
- if(max_supported_sublevel >= 7)
- {
- clear_mem(cpuid, 4);
- X86_CPUID_SUBLEVEL(7, 0, cpuid);
-
- enum x86_CPUID_7_bits : uint64_t {
- AVX2 = (1ULL << 5),
- BMI2 = (1ULL << 8),
- AVX512F = (1ULL << 16),
- RDSEED = (1ULL << 18),
- ADX = (1ULL << 19),
- SHA = (1ULL << 29),
- };
- uint64_t flags7 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[1];
-
- if(flags7 & x86_CPUID_7_bits::AVX2)
- features_detected |= CPUID::CPUID_AVX2_BIT;
- if(flags7 & x86_CPUID_7_bits::BMI2)
- features_detected |= CPUID::CPUID_BMI2_BIT;
- if(flags7 & x86_CPUID_7_bits::AVX512F)
- features_detected |= CPUID::CPUID_AVX512F_BIT;
- if(flags7 & x86_CPUID_7_bits::RDSEED)
- features_detected |= CPUID::CPUID_RDSEED_BIT;
- if(flags7 & x86_CPUID_7_bits::ADX)
- features_detected |= CPUID::CPUID_ADX_BIT;
- if(flags7 & x86_CPUID_7_bits::SHA)
- features_detected |= CPUID::CPUID_SHA_BIT;
- }
-
-#undef X86_CPUID
-#undef X86_CPUID_SUBLEVEL
-
- /*
- * If we don't have access to CPUID, we can still safely assume that
- * any x86-64 processor has SSE2 and RDTSC
- */
-#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
- if(features_detected == 0)
- {
- features_detected |= CPUID::CPUID_SSE2_BIT;
- features_detected |= CPUID::CPUID_RDTSC_BIT;
- }
-#endif
-
- return features_detected;
- }
-
-#endif
-
-}
-
-bool CPUID::has_simd_32()
- {
-#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
- return CPUID::has_sse2();
-#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
- return CPUID::has_altivec();
-#elif defined(BOTAN_TARGET_SUPPORTS_NEON)
- return CPUID::has_neon();
-#else
- return true;
-#endif
- }
-
-//static
-std::string CPUID::to_string()
- {
- std::vector<std::string> flags;
-
-#define CPUID_PRINT(flag) do { if(has_##flag()) { flags.push_back(#flag); } } while(0)
-
-#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
- CPUID_PRINT(sse2);
- CPUID_PRINT(ssse3);
- CPUID_PRINT(sse41);
- CPUID_PRINT(sse42);
- CPUID_PRINT(avx2);
- CPUID_PRINT(avx512f);
-
- CPUID_PRINT(rdtsc);
- CPUID_PRINT(bmi2);
- CPUID_PRINT(adx);
-
- CPUID_PRINT(aes_ni);
- CPUID_PRINT(clmul);
- CPUID_PRINT(rdrand);
- CPUID_PRINT(rdseed);
- CPUID_PRINT(intel_sha);
-#endif
-
-#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
- CPUID_PRINT(altivec);
-#endif
-
-#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
- CPUID_PRINT(neon);
- CPUID_PRINT(arm_sha1);
- CPUID_PRINT(arm_sha2);
- CPUID_PRINT(arm_aes);
- CPUID_PRINT(arm_pmull);
-#endif
-
-#undef CPUID_PRINT
-
- return string_join(flags, ' ');
- }
-
-//static
-void CPUID::print(std::ostream& o)
- {
- o << "CPUID flags: " << CPUID::to_string() << "\n";
- }
-
-//static
-void CPUID::initialize()
- {
- g_processor_features = 0;
-
-#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
- defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
- defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
-
- g_processor_features = detect_cpu_features(&g_cache_line_size);
-
-#endif
-
- g_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
- }
-
-//static
-CPUID::Endian_status CPUID::runtime_check_endian()
- {
- // Check runtime endian
- const uint32_t endian32 = 0x01234567;
- const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
-
- Endian_status endian = ENDIAN_UNKNOWN;
-
- if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
- {
- endian = ENDIAN_BIG;
- }
- else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
- {
- endian = ENDIAN_LITTLE;
- }
- else
- {
- throw Internal_Error("Unexpected endian at runtime, neither big nor little");
- }
-
- // If we were compiled with a known endian, verify it matches at runtime
-#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
- BOTAN_ASSERT(endian == ENDIAN_LITTLE, "Build and runtime endian match");
-#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
- BOTAN_ASSERT(endian == ENDIAN_BIG, "Build and runtime endian match");
-#endif
-
- return endian;
- }
-
-}
diff --git a/src/lib/utils/cpuid/cpuid.cpp b/src/lib/utils/cpuid/cpuid.cpp
new file mode 100644
index 000000000..3948853ac
--- /dev/null
+++ b/src/lib/utils/cpuid/cpuid.cpp
@@ -0,0 +1,169 @@
+/*
+* Runtime CPU detection
+* (C) 2009,2010,2013,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/cpuid.h>
+#include <botan/types.h>
+#include <botan/exceptn.h>
+#include <ostream>
+
+namespace Botan {
+
+uint64_t CPUID::g_processor_features = 0;
+size_t CPUID::g_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
+CPUID::Endian_status CPUID::g_endian_status = ENDIAN_UNKNOWN;
+
+bool CPUID::has_simd_32()
+ {
+#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
+ return CPUID::has_sse2();
+#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
+ return CPUID::has_altivec();
+#elif defined(BOTAN_TARGET_SUPPORTS_NEON)
+ return CPUID::has_neon();
+#else
+ return true;
+#endif
+ }
+
+//static
+std::string CPUID::to_string()
+ {
+ std::vector<std::string> flags;
+
+#define CPUID_PRINT(flag) do { if(has_##flag()) { flags.push_back(#flag); } } while(0)
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+ CPUID_PRINT(sse2);
+ CPUID_PRINT(ssse3);
+ CPUID_PRINT(sse41);
+ CPUID_PRINT(sse42);
+ CPUID_PRINT(avx2);
+ CPUID_PRINT(avx512f);
+
+ CPUID_PRINT(rdtsc);
+ CPUID_PRINT(bmi2);
+ CPUID_PRINT(adx);
+
+ CPUID_PRINT(aes_ni);
+ CPUID_PRINT(clmul);
+ CPUID_PRINT(rdrand);
+ CPUID_PRINT(rdseed);
+ CPUID_PRINT(intel_sha);
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ CPUID_PRINT(altivec);
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+ CPUID_PRINT(neon);
+ CPUID_PRINT(arm_sha1);
+ CPUID_PRINT(arm_sha2);
+ CPUID_PRINT(arm_aes);
+ CPUID_PRINT(arm_pmull);
+#endif
+
+#undef CPUID_PRINT
+
+ return string_join(flags, ' ');
+ }
+
+//static
+void CPUID::print(std::ostream& o)
+ {
+ o << "CPUID flags: " << CPUID::to_string() << "\n";
+ }
+
+//static
+void CPUID::initialize()
+ {
+ g_processor_features = 0;
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
+ defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
+ defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+
+ g_processor_features = CPUID::detect_cpu_features(&g_cache_line_size);
+
+#endif
+
+ g_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
+ }
+
+//static
+CPUID::Endian_status CPUID::runtime_check_endian()
+ {
+ // Check runtime endian
+ const uint32_t endian32 = 0x01234567;
+ const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
+
+ Endian_status endian = ENDIAN_UNKNOWN;
+
+ if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
+ {
+ endian = ENDIAN_BIG;
+ }
+ else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
+ {
+ endian = ENDIAN_LITTLE;
+ }
+ else
+ {
+ throw Internal_Error("Unexpected endian at runtime, neither big nor little");
+ }
+
+ // If we were compiled with a known endian, verify it matches at runtime
+#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
+ BOTAN_ASSERT(endian == ENDIAN_LITTLE, "Build and runtime endian match");
+#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
+ BOTAN_ASSERT(endian == ENDIAN_BIG, "Build and runtime endian match");
+#endif
+
+ return endian;
+ }
+
+std::vector<Botan::CPUID::CPUID_bits>
+CPUID::bit_from_string(const std::string& tok)
+ {
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+ if(tok == "sse2" || tok == "simd")
+ return {Botan::CPUID::CPUID_SSE2_BIT};
+ if(tok == "ssse3")
+ return {Botan::CPUID::CPUID_SSSE3_BIT};
+ if(tok == "aesni")
+ return {Botan::CPUID::CPUID_AESNI_BIT};
+ if(tok == "clmul")
+ return {Botan::CPUID::CPUID_CLMUL_BIT};
+ if(tok == "avx2")
+ return {Botan::CPUID::CPUID_AVX2_BIT};
+ if(tok == "sha")
+ return {Botan::CPUID::CPUID_SHA_BIT};
+
+#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ if(tok == "altivec" || tok == "simd")
+ return {Botan::CPUID::CPUID_ALTIVEC_BIT};
+
+#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+ if(tok == "neon" || tok == "simd")
+ return {Botan::CPUID::CPUID_ARM_NEON_BIT};
+ if(tok == "armv8sha1")
+ return {Botan::CPUID::CPUID_ARM_SHA1_BIT};
+ if(tok == "armv8sha2")
+ return {Botan::CPUID::CPUID_ARM_SHA2_BIT};
+ if(tok == "armv8aes")
+ return {Botan::CPUID::CPUID_ARM_AES_BIT};
+ if(tok == "armv8pmull")
+ return {Botan::CPUID::CPUID_ARM_PMULL_BIT};
+
+#else
+ BOTAN_UNUSED(tok);
+#endif
+
+ return {};
+ }
+
+}
diff --git a/src/lib/utils/cpuid.h b/src/lib/utils/cpuid/cpuid.h
index c27390729..b32d040ea 100644
--- a/src/lib/utils/cpuid.h
+++ b/src/lib/utils/cpuid/cpuid.h
@@ -9,6 +9,7 @@
#define BOTAN_CPUID_H__
#include <botan/types.h>
+#include <vector>
#include <string>
#include <iosfwd>
@@ -272,6 +273,7 @@ class BOTAN_DLL CPUID
return ((g_processor_features & static_cast<uint64_t>(elem)) != 0);
}
+ static std::vector<CPUID::CPUID_bits> bit_from_string(const std::string& tok);
private:
enum Endian_status : uint32_t {
ENDIAN_UNKNOWN = 0x00000000,
@@ -279,6 +281,14 @@ class BOTAN_DLL CPUID
ENDIAN_LITTLE = 0x67452301,
};
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
+ defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
+ defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+
+ static uint64_t detect_cpu_features(size_t* cache_line_size);
+
+#endif
+
static Endian_status runtime_check_endian();
static Endian_status endian_status()
diff --git a/src/lib/utils/cpuid/cpuid_arm.cpp b/src/lib/utils/cpuid/cpuid_arm.cpp
new file mode 100644
index 000000000..39b6db652
--- /dev/null
+++ b/src/lib/utils/cpuid/cpuid_arm.cpp
@@ -0,0 +1,214 @@
+/*
+* Runtime CPU detection for ARM
+* (C) 2009,2010,2013,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/cpuid.h>
+
+#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+
+#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)
+ #include <sys/auxv.h>
+
+#elif defined(BOTAN_TARGET_OS_IS_IOS)
+ #include <sys/types.h>
+ #include <sys/sysctl.h>
+
+#else
+ #include <botan/internal/os_utils.h>
+
+#endif
+
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
+
+#if defined(BOTAN_TARGET_OS_IS_IOS)
+
+namespace {
+
+uint64_t flags_by_ios_machine_type(const std::string& machine)
+ {
+ /*
+ * This relies on a map of known machine names to features. This
+ * will quickly grow out of date as new products are introduced, but
+ * is apparently the best we can do for iOS.
+ */
+
+ struct version_info {
+ std::string name;
+ size_t min_version_neon;
+ size_t min_version_armv8;
+ };
+
+ static const version_info min_versions[] = {
+ { "iPhone", 2, 6 },
+ { "iPad", 1, 4 },
+ { "iPod", 4, 7 },
+ { "AppleTV", 2, 5 },
+ };
+
+ if(machine.size() < 3)
+ return 0;
+
+ auto comma = machine.find(',');
+
+ // Simulator, or something we don't know about
+ if(comma == std::string::npos)
+ return 0;
+
+ std::string product = machine.substr(0, comma);
+
+ size_t version = 0;
+ size_t place = 1;
+ while(product.size() > 1 && ::isdigit(product.back()))
+ {
+ const size_t digit = product.back() - '0';
+ version += digit * place;
+ place *= 10;
+ product.pop_back();
+ }
+
+ if(version == 0)
+ return 0;
+
+ for(const version_info& info : min_versions)
+ {
+ if(info.name != product)
+ continue;
+
+ if(version >= info.min_version_armv8)
+ {
+ return CPUID::CPUID_ARM_AES_BIT |
+ CPUID::CPUID_ARM_PMULL_BIT |
+ CPUID::CPUID_ARM_SHA1_BIT |
+ CPUID::CPUID_ARM_SHA2_BIT |
+ CPUID::CPUID_ARM_NEON_BIT;
+ }
+
+ if(version >= info.min_version_neon)
+ return CPUID::CPUID_ARM_NEON_BIT;
+ }
+
+ // Some other product we don't know about
+ return 0;
+ }
+
+}
+
+#endif
+
+uint64_t CPUID::detect_cpu_features(size_t* cache_line_size)
+ {
+ uint64_t detected_features = 0;
+
+#if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL)
+ /*
+ * On systems with getauxval these bits should normally be defined
+ * in bits/auxv.h but some buggy? glibc installs seem to miss them.
+ * These following values are all fixed, for the Linux ELF format,
+ * so we just hardcode them in ARM_hwcap_bit enum.
+ */
+
+ enum ARM_hwcap_bit {
+#if defined(BOTAN_TARGET_ARCH_IS_ARM32)
+ NEON_bit = (1 << 12),
+ AES_bit = (1 << 0),
+ PMULL_bit = (1 << 1),
+ SHA1_bit = (1 << 2),
+ SHA2_bit = (1 << 3),
+
+ ARCH_hwcap_neon = 16, // AT_HWCAP
+ ARCH_hwcap_crypto = 26, // AT_HWCAP2
+#elif defined(BOTAN_TARGET_ARCH_IS_ARM64)
+ NEON_bit = (1 << 1),
+ AES_bit = (1 << 3),
+ PMULL_bit = (1 << 4),
+ SHA1_bit = (1 << 5),
+ SHA2_bit = (1 << 6),
+
+ ARCH_hwcap_neon = 16, // AT_HWCAP
+ ARCH_hwcap_crypto = 16, // AT_HWCAP
+#endif
+ };
+
+#if defined(AT_DCACHEBSIZE)
+ const unsigned long dcache_line = ::getauxval(AT_DCACHEBSIZE);
+
+ // plausibility check
+ if(dcache_line == 32 || dcache_line == 64 || dcache_line == 128)
+ *cache_line_size = static_cast<size_t>(dcache_line);
+#endif
+
+ const unsigned long hwcap_neon = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_neon);
+ if(hwcap_neon & ARM_hwcap_bit::NEON_bit)
+ detected_features |= CPUID::CPUID_ARM_NEON_BIT;
+
+ /*
+ On aarch64 this ends up calling getauxval twice with AT_HWCAP
+ It doesn't seem worth optimizing this out, since getauxval is
+ just reading a field in the ELF header.
+ */
+ const unsigned long hwcap_crypto = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_crypto);
+ if(hwcap_crypto & ARM_hwcap_bit::AES_bit)
+ detected_features |= CPUID::CPUID_ARM_AES_BIT;
+ if(hwcap_crypto & ARM_hwcap_bit::PMULL_bit)
+ detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
+ if(hwcap_crypto & ARM_hwcap_bit::SHA1_bit)
+ detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
+ if(hwcap_crypto & ARM_hwcap_bit::SHA2_bit)
+ detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
+
+#elif defined(BOTAN_TARGET_OS_IS_IOS)
+
+ char machine[64] = { 0 };
+ size_t size = sizeof(machine) - 1;
+ ::sysctlbyname("hw.machine", machine, &size, nullptr, 0);
+
+ detected_features = flags_by_ios_machine_type(machine);
+
+#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_ARM64)
+
+ /*
+ No getauxval API available, fall back on probe functions. We only
+ bother with Aarch64 here to simplify the code and because going to
+ extreme contortions to support detect NEON on devices that probably
+ don't support it doesn't seem worthwhile.
+
+ NEON registers v0-v7 are caller saved in Aarch64
+ */
+
+ auto neon_probe = []() -> int { asm("and v0.16b, v0.16b, v0.16b"); return 1; };
+ auto aes_probe = []() -> int { asm(".word 0x4e284800"); return 1; };
+ auto pmull_probe = []() -> int { asm(".word 0x0ee0e000"); return 1; };
+ auto sha1_probe = []() -> int { asm(".word 0x5e280800"); return 1; };
+ auto sha2_probe = []() -> int { asm(".word 0x5e282800"); return 1; };
+
+ // Only bother running the crypto detection if we found NEON
+
+ if(OS::run_cpu_instruction_probe(neon_probe) == 1)
+ {
+ detected_features |= CPUID::CPUID_ARM_NEON_BIT;
+
+ if(OS::run_cpu_instruction_probe(aes_probe) == 1)
+ detected_features |= CPUID::CPUID_ARM_AES_BIT;
+ if(OS::run_cpu_instruction_probe(pmull_probe) == 1)
+ detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
+ if(OS::run_cpu_instruction_probe(sha1_probe) == 1)
+ detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
+ if(OS::run_cpu_instruction_probe(sha2_probe) == 1)
+ detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
+ }
+
+#endif
+
+ return detected_features;
+ }
+
+#endif
+
+}
diff --git a/src/lib/utils/cpuid/cpuid_ppc.cpp b/src/lib/utils/cpuid/cpuid_ppc.cpp
new file mode 100644
index 000000000..647672a71
--- /dev/null
+++ b/src/lib/utils/cpuid/cpuid_ppc.cpp
@@ -0,0 +1,101 @@
+/*
+* Runtime CPU detection for POWER/PowerPC
+* (C) 2009,2010,2013,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/cpuid.h>
+#include <botan/internal/os_utils.h>
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+
+/*
+* On Darwin and OpenBSD ppc, use sysctl to detect AltiVec
+*/
+#if defined(BOTAN_TARGET_OS_IS_DARWIN)
+ #include <sys/sysctl.h>
+#elif defined(BOTAN_TARGET_OS_IS_OPENBSD)
+ #include <sys/param.h>
+ #include <sys/sysctl.h>
+ #include <machine/cpu.h>
+#endif
+
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+
+/*
+* PowerPC specific block: check for AltiVec using either
+* sysctl or by reading processor version number register.
+*/
+uint64_t CPUID::detect_cpu_features(size_t* cache_line_size)
+ {
+#if defined(BOTAN_TARGET_OS_IS_DARWIN) || defined(BOTAN_TARGET_OS_IS_OPENBSD)
+ // On Darwin/OS X and OpenBSD, use sysctl
+
+ int sels[2] = {
+#if defined(BOTAN_TARGET_OS_IS_OPENBSD)
+ CTL_MACHDEP, CPU_ALTIVEC
+#else
+ CTL_HW, HW_VECTORUNIT
+#endif
+ };
+
+ int vector_type = 0;
+ size_t length = sizeof(vector_type);
+ int error = ::sysctl(sels, 2, &vector_type, &length, NULL, 0);
+
+ if(error == 0 && vector_type > 0)
+ return CPUID::CPUID_ALTIVEC_BIT;
+
+#else
+
+ /*
+ On PowerPC, MSR 287 is PVR, the Processor Version Number
+ Normally it is only accessible to ring 0, but Linux and NetBSD
+ (others, too, maybe?) will trap and emulate it for us.
+ */
+
+ int pvr = OS::run_cpu_instruction_probe([]() -> int {
+ uint32_t pvr = 0;
+ asm volatile("mfspr %0, 287" : "=r" (pvr));
+ // Top 16 bits suffice to identify the model
+ return static_cast<int>(pvr >> 16);
+ });
+
+ if(pvr > 0)
+ {
+ const uint16_t ALTIVEC_PVR[] = {
+ 0x003E, // IBM POWER6,
+ 0x003F, // IBM POWER7,
+ 0x004B, // IBM POWER8,
+ 0x000C, // G4-7400
+ 0x0039, // G5 970
+ 0x003C, // G5 970FX
+ 0x0044, // G5 970MP
+ 0x0070, // Cell PPU
+ 0, // end
+ };
+
+ for(size_t i = 0; ALTIVEC_PVR[i]; ++i)
+ {
+ if(pvr == ALTIVEC_PVR[i])
+ return CPUID::CPUID_ALTIVEC_BIT;
+ }
+
+ return 0;
+ }
+
+ // TODO try direct instruction probing
+
+#endif
+
+ return 0;
+ }
+
+#endif
+
+}
diff --git a/src/lib/utils/cpuid/cpuid_x86.cpp b/src/lib/utils/cpuid/cpuid_x86.cpp
new file mode 100644
index 000000000..be6c75a55
--- /dev/null
+++ b/src/lib/utils/cpuid/cpuid_x86.cpp
@@ -0,0 +1,167 @@
+/*
+* Runtime CPU detection for x86
+* (C) 2009,2010,2013,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/cpuid.h>
+#include <botan/mem_ops.h>
+#include <botan/loadstor.h>
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+
+#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
+ #include <intrin.h>
+#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
+ #include <ia32intrin.h>
+#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
+ #include <cpuid.h>
+#endif
+
+#endif
+
+namespace Botan {
+
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+
+uint64_t CPUID::detect_cpu_features(size_t* cache_line_size)
+ {
+#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
+ #define X86_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
+ #define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuidex((int*)out, type, level); } while(0)
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_INTEL)
+ #define X86_CPUID(type, out) do { __cpuid(out, type); } while(0)
+ #define X86_CPUID_SUBLEVEL(type, level, out) do { __cpuidex((int*)out, type, level); } while(0)
+
+#elif defined(BOTAN_TARGET_ARCH_IS_X86_64) && defined(BOTAN_USE_GCC_INLINE_ASM)
+ #define X86_CPUID(type, out) \
+ asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
+ : "0" (type))
+
+ #define X86_CPUID_SUBLEVEL(type, level, out) \
+ asm("cpuid\n\t" : "=a" (out[0]), "=b" (out[1]), "=c" (out[2]), "=d" (out[3]) \
+ : "0" (type), "2" (level))
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG)
+ #define X86_CPUID(type, out) do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0)
+
+ #define X86_CPUID_SUBLEVEL(type, level, out) \
+ do { __cpuid_count(type, level, out[0], out[1], out[2], out[3]); } while(0)
+#else
+ #warning "No way of calling x86 cpuid instruction for this compiler"
+ #define X86_CPUID(type, out) do { clear_mem(out, 4); } while(0)
+ #define X86_CPUID_SUBLEVEL(type, level, out) do { clear_mem(out, 4); } while(0)
+#endif
+
+ uint64_t features_detected = 0;
+ uint32_t cpuid[4] = { 0 };
+
+ // CPUID 0: vendor identification, max sublevel
+ X86_CPUID(0, cpuid);
+
+ const uint32_t max_supported_sublevel = cpuid[0];
+
+ const uint32_t INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
+ const uint32_t AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
+ const bool is_intel = same_mem(cpuid + 1, INTEL_CPUID, 3);
+ const bool is_amd = same_mem(cpuid + 1, AMD_CPUID, 3);
+
+ if(max_supported_sublevel >= 1)
+ {
+ // CPUID 1: feature bits
+ X86_CPUID(1, cpuid);
+ const uint64_t flags0 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[3];
+
+ enum x86_CPUID_1_bits : uint64_t {
+ RDTSC = (1ULL << 4),
+ SSE2 = (1ULL << 26),
+ CLMUL = (1ULL << 33),
+ SSSE3 = (1ULL << 41),
+ SSE41 = (1ULL << 51),
+ SSE42 = (1ULL << 52),
+ AESNI = (1ULL << 57),
+ RDRAND = (1ULL << 62)
+ };
+
+ if(flags0 & x86_CPUID_1_bits::RDTSC)
+ features_detected |= CPUID::CPUID_RDTSC_BIT;
+ if(flags0 & x86_CPUID_1_bits::SSE2)
+ features_detected |= CPUID::CPUID_SSE2_BIT;
+ if(flags0 & x86_CPUID_1_bits::CLMUL)
+ features_detected |= CPUID::CPUID_CLMUL_BIT;
+ if(flags0 & x86_CPUID_1_bits::SSSE3)
+ features_detected |= CPUID::CPUID_SSSE3_BIT;
+ if(flags0 & x86_CPUID_1_bits::SSE41)
+ features_detected |= CPUID::CPUID_SSE41_BIT;
+ if(flags0 & x86_CPUID_1_bits::SSE42)
+ features_detected |= CPUID::CPUID_SSE42_BIT;
+ if(flags0 & x86_CPUID_1_bits::AESNI)
+ features_detected |= CPUID::CPUID_AESNI_BIT;
+ if(flags0 & x86_CPUID_1_bits::RDRAND)
+ features_detected |= CPUID::CPUID_RDRAND_BIT;
+ }
+
+ if(is_intel)
+ {
+ // Intel cache line size is in cpuid(1) output
+ *cache_line_size = 8 * get_byte(2, cpuid[1]);
+ }
+ else if(is_amd)
+ {
+ // AMD puts it in vendor zone
+ X86_CPUID(0x80000005, cpuid);
+ *cache_line_size = get_byte(3, cpuid[2]);
+ }
+
+ if(max_supported_sublevel >= 7)
+ {
+ clear_mem(cpuid, 4);
+ X86_CPUID_SUBLEVEL(7, 0, cpuid);
+
+ enum x86_CPUID_7_bits : uint64_t {
+ AVX2 = (1ULL << 5),
+ BMI2 = (1ULL << 8),
+ AVX512F = (1ULL << 16),
+ RDSEED = (1ULL << 18),
+ ADX = (1ULL << 19),
+ SHA = (1ULL << 29),
+ };
+ uint64_t flags7 = (static_cast<uint64_t>(cpuid[2]) << 32) | cpuid[1];
+
+ if(flags7 & x86_CPUID_7_bits::AVX2)
+ features_detected |= CPUID::CPUID_AVX2_BIT;
+ if(flags7 & x86_CPUID_7_bits::BMI2)
+ features_detected |= CPUID::CPUID_BMI2_BIT;
+ if(flags7 & x86_CPUID_7_bits::AVX512F)
+ features_detected |= CPUID::CPUID_AVX512F_BIT;
+ if(flags7 & x86_CPUID_7_bits::RDSEED)
+ features_detected |= CPUID::CPUID_RDSEED_BIT;
+ if(flags7 & x86_CPUID_7_bits::ADX)
+ features_detected |= CPUID::CPUID_ADX_BIT;
+ if(flags7 & x86_CPUID_7_bits::SHA)
+ features_detected |= CPUID::CPUID_SHA_BIT;
+ }
+
+#undef X86_CPUID
+#undef X86_CPUID_SUBLEVEL
+
+ /*
+ * If we don't have access to CPUID, we can still safely assume that
+ * any x86-64 processor has SSE2 and RDTSC
+ */
+#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
+ if(features_detected == 0)
+ {
+ features_detected |= CPUID::CPUID_SSE2_BIT;
+ features_detected |= CPUID::CPUID_RDTSC_BIT;
+ }
+#endif
+
+ return features_detected;
+ }
+
+#endif
+
+}
diff --git a/src/lib/utils/cpuid/info.txt b/src/lib/utils/cpuid/info.txt
new file mode 100644
index 000000000..987d7eae4
--- /dev/null
+++ b/src/lib/utils/cpuid/info.txt
@@ -0,0 +1,7 @@
+<defines>
+CPUID -> 20170917
+</defines>
+
+<header:public>
+cpuid.h
+</header:public>
diff --git a/src/lib/utils/info.txt b/src/lib/utils/info.txt
index 8bbe2925b..644bff901 100644
--- a/src/lib/utils/info.txt
+++ b/src/lib/utils/info.txt
@@ -9,7 +9,6 @@ assert.h
bswap.h
calendar.h
charset.h
-cpuid.h
compiler.h
data_src.h
database.h
@@ -45,3 +44,7 @@ linux -> rt
mingw -> ws2_32
windows -> ws2_32.lib
</libs>
+
+<requires>
+cpuid
+</requires>
diff --git a/src/lib/utils/mem_ops.cpp b/src/lib/utils/mem_ops.cpp
new file mode 100644
index 000000000..45de24cb8
--- /dev/null
+++ b/src/lib/utils/mem_ops.cpp
@@ -0,0 +1,84 @@
+/*
+* (C) 2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+bool constant_time_compare(const uint8_t x[],
+ const uint8_t y[],
+ size_t len)
+ {
+ volatile uint8_t difference = 0;
+
+ for(size_t i = 0; i != len; ++i)
+ difference |= (x[i] ^ y[i]);
+
+ return difference == 0;
+ }
+
+void xor_buf(uint8_t x[],
+ const uint8_t y[],
+ size_t len)
+ {
+ while(len >= 16)
+ {
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ x[2] ^= y[2];
+ x[3] ^= y[3];
+ x[4] ^= y[4];
+ x[5] ^= y[5];
+ x[6] ^= y[6];
+ x[7] ^= y[7];
+ x[8] ^= y[8];
+ x[9] ^= y[9];
+ x[10] ^= y[10];
+ x[11] ^= y[11];
+ x[12] ^= y[12];
+ x[13] ^= y[13];
+ x[14] ^= y[14];
+ x[15] ^= y[15];
+ x += 16; y += 16; len -= 16;
+ }
+
+ for(size_t i = 0; i != len; ++i)
+ {
+ x[i] ^= y[i];
+ }
+ }
+
+void xor_buf(uint8_t out[],
+ const uint8_t in[],
+ const uint8_t in2[],
+ size_t length)
+ {
+ while(length >= 16)
+ {
+ out[0] = in[0] ^ in2[0];
+ out[1] = in[1] ^ in2[1];
+ out[2] = in[2] ^ in2[2];
+ out[3] = in[3] ^ in2[3];
+ out[4] = in[4] ^ in2[4];
+ out[5] = in[5] ^ in2[5];
+ out[6] = in[6] ^ in2[6];
+ out[7] = in[7] ^ in2[7];
+ out[8] = in[8] ^ in2[8];
+ out[9] = in[9] ^ in2[9];
+ out[10] = in[10] ^ in2[10];
+ out[11] = in[11] ^ in2[11];
+ out[12] = in[12] ^ in2[12];
+ out[13] = in[13] ^ in2[13];
+ out[14] = in[14] ^ in2[14];
+ out[15] = in[15] ^ in2[15];
+ in += 16; in2 += 16; out += 16; length -= 16;
+ }
+
+ for(size_t i = 0; i != length; ++i)
+ out[i] = in[i] ^ in2[i];
+ }
+
+}
diff --git a/src/lib/utils/mem_ops.h b/src/lib/utils/mem_ops.h
index 13c987526..2d575d35e 100644
--- a/src/lib/utils/mem_ops.h
+++ b/src/lib/utils/mem_ops.h
@@ -32,6 +32,17 @@ namespace Botan {
BOTAN_DLL void secure_scrub_memory(void* ptr, size_t n);
/**
+* Memory comparison, input insensitive
+* @param x a pointer to an array
+* @param y a pointer to another array
+* @param len the number of Ts in x and y
+* @return true iff x[i] == y[i] forall i in [0...n)
+*/
+BOTAN_DLL bool constant_time_compare(const uint8_t x[],
+ const uint8_t y[],
+ size_t len);
+
+/**
* Zero out some bytes
* @param ptr a pointer to memory to zero
* @param bytes the number of bytes to zero in ptr
@@ -106,19 +117,14 @@ template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
}
/**
-* XOR_ arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
+* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
* @param out the input/output buffer
* @param in the read-only input buffer
* @param length the length of the buffers
*/
-template<typename T>
-void xor_buf(T out[], const T in[], size_t length)
- {
- for(size_t i = 0; i != length; ++i)
- {
- out[i] ^= in[i];
- }
- }
+BOTAN_DLL void xor_buf(uint8_t out[],
+ const uint8_t in[],
+ size_t length);
/**
* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
@@ -127,16 +133,10 @@ void xor_buf(T out[], const T in[], size_t length)
* @param in2 the second output buffer
* @param length the length of the three buffers
*/
-template<typename T> void xor_buf(T out[],
- const T in[],
- const T in2[],
- size_t length)
- {
- for(size_t i = 0; i != length; ++i)
- {
- out[i] = in[i] ^ in2[i];
- }
- }
+BOTAN_DLL void xor_buf(uint8_t out[],
+ const uint8_t in[],
+ const uint8_t in2[],
+ size_t length);
template<typename Alloc, typename Alloc2>
void xor_buf(std::vector<uint8_t, Alloc>& out,
@@ -163,10 +163,10 @@ void xor_buf(std::vector<uint8_t, Alloc>& out,
xor_buf(out.data(), in, in2.data(), n);
}
-template<typename T, typename Alloc, typename Alloc2>
-std::vector<T, Alloc>&
-operator^=(std::vector<T, Alloc>& out,
- const std::vector<T, Alloc2>& in)
+template<typename Alloc, typename Alloc2>
+std::vector<uint8_t, Alloc>&
+operator^=(std::vector<uint8_t, Alloc>& out,
+ const std::vector<uint8_t, Alloc2>& in)
{
if(out.size() < in.size())
out.resize(in.size());
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index 261fb5f1f..275cfac3b 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -47,232 +47,241 @@
namespace Botan {
-std::unique_ptr<OS::Socket>
-OS::open_socket(const std::string& hostname,
- const std::string& service)
- {
+namespace {
+
#if defined(BOTAN_HAS_BOOST_ASIO)
- class Asio_Socket : public OS::Socket
- {
- public:
- Asio_Socket(const std::string& hostname, const std::string& service) :
- m_tcp(m_io)
- {
- boost::asio::ip::tcp::resolver resolver(m_io);
- boost::asio::ip::tcp::resolver::query query(hostname, service);
- boost::asio::connect(m_tcp, resolver.resolve(query));
- }
- void write(const uint8_t buf[], size_t len)
- {
- boost::asio::write(m_tcp, boost::asio::buffer(buf, len));
- }
+class Asio_Socket : public OS::Socket
+ {
+ public:
+ Asio_Socket(const std::string& hostname, const std::string& service) :
+ m_tcp(m_io)
+ {
+ boost::asio::ip::tcp::resolver resolver(m_io);
+ boost::asio::ip::tcp::resolver::query query(hostname, service);
+ boost::asio::connect(m_tcp, resolver.resolve(query));
+ }
- size_t read(uint8_t buf[], size_t len)
- {
- boost::system::error_code error;
- size_t got = m_tcp.read_some(boost::asio::buffer(buf, len), error);
+ void write(const uint8_t buf[], size_t len) override
+ {
+ boost::asio::write(m_tcp, boost::asio::buffer(buf, len));
+ }
- if(error)
- {
- if(error == boost::asio::error::eof)
- return 0;
- throw boost::system::system_error(error); // Some other error.
- }
+ size_t read(uint8_t buf[], size_t len) override
+ {
+ boost::system::error_code error;
+ size_t got = m_tcp.read_some(boost::asio::buffer(buf, len), error);
- return got;
+ if(error)
+ {
+ if(error == boost::asio::error::eof)
+ return 0;
+ throw boost::system::system_error(error); // Some other error.
}
- private:
- boost::asio::io_service m_io;
- boost::asio::ip::tcp::socket m_tcp;
- };
+ return got;
+ }
- return std::unique_ptr<OS::Socket>(new Asio_Socket(hostname, service));
+ private:
+ boost::asio::io_service m_io;
+ boost::asio::ip::tcp::socket m_tcp;
+ };
#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
- class Winsock_Socket : public OS::Socket
- {
- public:
- Winsock_Socket(const std::string& hostname, const std::string& service)
- {
- WSAData wsa_data;
- WORD wsa_version = MAKEWORD(2, 2);
-
- if (::WSAStartup(wsa_version, &wsa_data) != 0)
- {
- throw Exception("WSAStartup() failed: " + std::to_string(WSAGetLastError()));
- }
-
- if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
- {
- ::WSACleanup();
- throw Exception("Could not find a usable version of Winsock.dll");
- }
+class Winsock_Socket : public OS::Socket
+ {
+ public:
+ Winsock_Socket(const std::string& hostname, const std::string& service)
+ {
+ WSAData wsa_data;
+ WORD wsa_version = MAKEWORD(2, 2);
- addrinfo hints;
- ::memset(&hints, 0, sizeof(addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- addrinfo* res;
+ if (::WSAStartup(wsa_version, &wsa_data) != 0)
+ {
+ throw Exception("WSAStartup() failed: " + std::to_string(WSAGetLastError()));
+ }
- if(::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res) != 0)
- {
- throw Exception("Name resolution failed for " + hostname);
- }
+ if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
+ {
+ ::WSACleanup();
+ throw Exception("Could not find a usable version of Winsock.dll");
+ }
- for(addrinfo* rp = res; (m_socket == INVALID_SOCKET) && (rp != nullptr); rp = rp->ai_next)
- {
- m_socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ addrinfo hints;
+ ::memset(&hints, 0, sizeof(addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ addrinfo* res;
- // unsupported socket type?
- if(m_socket == INVALID_SOCKET)
- continue;
-
- if(::connect(m_socket, rp->ai_addr, rp->ai_addrlen) != 0)
- {
- ::closesocket(m_socket);
- m_socket = INVALID_SOCKET;
- continue;
- }
- }
+ if(::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res) != 0)
+ {
+ throw Exception("Name resolution failed for " + hostname);
+ }
- ::freeaddrinfo(res);
+ for(addrinfo* rp = res; (m_socket == INVALID_SOCKET) && (rp != nullptr); rp = rp->ai_next)
+ {
+ m_socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ // unsupported socket type?
if(m_socket == INVALID_SOCKET)
+ continue;
+
+ if(::connect(m_socket, rp->ai_addr, rp->ai_addrlen) != 0)
{
- throw Exception("Connecting to " + hostname +
- " for service " + service + " failed");
+ ::closesocket(m_socket);
+ m_socket = INVALID_SOCKET;
+ continue;
}
}
- ~Winsock_Socket()
- {
- ::closesocket(m_socket);
- m_socket = INVALID_SOCKET;
- ::WSACleanup();
- }
+ ::freeaddrinfo(res);
- void write(const uint8_t buf[], size_t len)
+ if(m_socket == INVALID_SOCKET)
{
- size_t sent_so_far = 0;
- while(sent_so_far != len)
- {
- const size_t left = len - sent_so_far;
- int sent = ::send(m_socket,
- reinterpret_cast<const char*>(buf + sent_so_far),
- static_cast<int>(left),
- 0);
-
- if(sent == SOCKET_ERROR)
- throw Exception("Socket write failed with error " +
- std::to_string(::WSAGetLastError()));
- else
- sent_so_far += static_cast<size_t>(sent);
- }
+ throw Exception("Connecting to " + hostname +
+ " for service " + service + " failed");
}
+ }
- size_t read(uint8_t buf[], size_t len)
- {
- int got = ::recv(m_socket,
- reinterpret_cast<char*>(buf),
- static_cast<int>(len), 0);
+ ~Winsock_Socket()
+ {
+ ::closesocket(m_socket);
+ m_socket = INVALID_SOCKET;
+ ::WSACleanup();
+ }
- if(got == SOCKET_ERROR)
- throw Exception("Socket read failed with error " +
+ void write(const uint8_t buf[], size_t len) override
+ {
+ size_t sent_so_far = 0;
+ while(sent_so_far != len)
+ {
+ const size_t left = len - sent_so_far;
+ int sent = ::send(m_socket,
+ reinterpret_cast<const char*>(buf + sent_so_far),
+ static_cast<int>(left),
+ 0);
+
+ if(sent == SOCKET_ERROR)
+ throw Exception("Socket write failed with error " +
std::to_string(::WSAGetLastError()));
- return static_cast<size_t>(got);
+ else
+ sent_so_far += static_cast<size_t>(sent);
}
+ }
- private:
- SOCKET m_socket = INVALID_SOCKET;
- };
+ size_t read(uint8_t buf[], size_t len) override
+ {
+ int got = ::recv(m_socket,
+ reinterpret_cast<char*>(buf),
+ static_cast<int>(len), 0);
+
+ if(got == SOCKET_ERROR)
+ throw Exception("Socket read failed with error " +
+ std::to_string(::WSAGetLastError()));
+ return static_cast<size_t>(got);
+ }
- return std::unique_ptr<OS::Socket>(new Winsock_Socket(hostname, service));
+ private:
+ SOCKET m_socket = INVALID_SOCKET;
+ };
#elif defined(BOTAN_TARGET_OS_TYPE_IS_UNIX)
+class BSD_Socket : public OS::Socket
+ {
+ public:
+ BSD_Socket(const std::string& hostname, const std::string& service)
+ {
+ addrinfo hints;
+ ::memset(&hints, 0, sizeof(addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ addrinfo* res;
- class BSD_Socket : public OS::Socket
- {
- public:
- BSD_Socket(const std::string& hostname, const std::string& service)
+ if(::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res) != 0)
{
- addrinfo hints;
- ::memset(&hints, 0, sizeof(addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- addrinfo* res;
+ throw Exception("Name resolution failed for " + hostname);
+ }
- if(::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res) != 0)
- {
- throw Exception("Name resolution failed for " + hostname);
- }
+ m_fd = -1;
- m_fd = -1;
+ for(addrinfo* rp = res; (m_fd < 0) && (rp != nullptr); rp = rp->ai_next)
+ {
+ m_fd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- for(addrinfo* rp = res; (m_fd < 0) && (rp != nullptr); rp = rp->ai_next)
+ if(m_fd < 0)
{
- m_fd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
-
- if(m_fd < 0)
- {
- // unsupported socket type?
- continue;
- }
-
- if(::connect(m_fd, rp->ai_addr, rp->ai_addrlen) != 0)
- {
- ::close(m_fd);
- m_fd = -1;
- continue;
- }
+ // unsupported socket type?
+ continue;
}
- ::freeaddrinfo(res);
-
- if(m_fd < 0)
+ if(::connect(m_fd, rp->ai_addr, rp->ai_addrlen) != 0)
{
- throw Exception("Connecting to " + hostname +
- " for service " + service + " failed");
+ ::close(m_fd);
+ m_fd = -1;
+ continue;
}
}
- ~BSD_Socket()
- {
- ::close(m_fd);
- m_fd = -1;
- }
+ ::freeaddrinfo(res);
- void write(const uint8_t buf[], size_t len)
+ if(m_fd < 0)
{
- size_t sent_so_far = 0;
- while(sent_so_far != len)
- {
- const size_t left = len - sent_so_far;
- ssize_t sent = ::write(m_fd, &buf[sent_so_far], left);
- if(sent < 0)
- throw Exception("Socket write failed with error '" +
- std::string(::strerror(errno)) + "'");
- else
- sent_so_far += static_cast<size_t>(sent);
- }
+ throw Exception("Connecting to " + hostname +
+ " for service " + service + " failed");
}
+ }
- size_t read(uint8_t buf[], size_t len)
- {
- ssize_t got = ::read(m_fd, buf, len);
+ ~BSD_Socket()
+ {
+ ::close(m_fd);
+ m_fd = -1;
+ }
- if(got < 0)
- throw Exception("Socket read failed with error '" +
+ void write(const uint8_t buf[], size_t len) override
+ {
+ size_t sent_so_far = 0;
+ while(sent_so_far != len)
+ {
+ const size_t left = len - sent_so_far;
+ ssize_t sent = ::write(m_fd, &buf[sent_so_far], left);
+ if(sent < 0)
+ throw Exception("Socket write failed with error '" +
std::string(::strerror(errno)) + "'");
- return static_cast<size_t>(got);
+ else
+ sent_so_far += static_cast<size_t>(sent);
}
+ }
+
+ size_t read(uint8_t buf[], size_t len) override
+ {
+ ssize_t got = ::read(m_fd, buf, len);
+
+ if(got < 0)
+ throw Exception("Socket read failed with error '" +
+ std::string(::strerror(errno)) + "'");
+ return static_cast<size_t>(got);
+ }
+
+ private:
+ int m_fd;
+ };
+
+#endif
+
+}
- private:
- int m_fd;
- };
+std::unique_ptr<OS::Socket>
+OS::open_socket(const std::string& hostname,
+ const std::string& service)
+ {
+#if defined(BOTAN_HAS_BOOST_ASIO)
+ return std::unique_ptr<OS::Socket>(new Asio_Socket(hostname, service));
+
+#elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
+ return std::unique_ptr<OS::Socket>(new Winsock_Socket(hostname, service));
+#elif defined(BOTAN_TARGET_OS_TYPE_IS_UNIX)
return std::unique_ptr<OS::Socket>(new BSD_Socket(hostname, service));
#else
@@ -323,21 +332,23 @@ uint32_t OS::get_process_id()
uint64_t OS::get_processor_timestamp()
{
+ uint64_t rtc = 0;
+
#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER)
LARGE_INTEGER tv;
::QueryPerformanceCounter(&tv);
- return tv.QuadPart;
+ rtc = tv.QuadPart;
#elif defined(BOTAN_USE_GCC_INLINE_ASM)
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
- if(CPUID::has_rdtsc() == false)
- return 0;
-
- uint32_t rtc_low = 0, rtc_high = 0;
- asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
- return (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
+ if(CPUID::has_rdtsc())
+ {
+ uint32_t rtc_low = 0, rtc_high = 0;
+ asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
+ rtc = (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
+ }
#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
uint32_t rtc_low = 0, rtc_high = 0;
@@ -349,43 +360,32 @@ uint64_t OS::get_processor_timestamp()
*/
if(rtc_high > 0 || rtc_low > 0)
{
- return (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
+ rtc = (static_cast<uint64_t>(rtc_high) << 32) | rtc_low;
}
#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
- uint64_t rtc = 0;
asm volatile("rpcc %0" : "=r" (rtc));
- return rtc;
// OpenBSD does not trap access to the %tick register
#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD)
- uint64_t rtc = 0;
asm volatile("rd %%tick, %0" : "=r" (rtc));
- return rtc;
#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
- uint64_t rtc = 0;
asm volatile("mov %0=ar.itc" : "=r" (rtc));
- return rtc;
#elif defined(BOTAN_TARGET_ARCH_IS_S390X)
- uint64_t rtc = 0;
asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc");
- return rtc;
#elif defined(BOTAN_TARGET_ARCH_IS_HPPA)
- uint64_t rtc = 0;
asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only?
- return rtc;
#else
//#warning "OS::get_processor_timestamp not implemented"
- return 0;
#endif
-#else
- return 0;
#endif
+
+ return rtc;
}
uint64_t OS::get_high_resolution_clock()
diff --git a/src/lib/utils/simd/simd_32.h b/src/lib/utils/simd/simd_32.h
index 6d9223a38..f2b6351c6 100644
--- a/src/lib/utils/simd/simd_32.h
+++ b/src/lib/utils/simd/simd_32.h
@@ -58,13 +58,16 @@ class SIMD_4x32 final
SIMD_4x32() // zero initialized
{
#if defined(BOTAN_SIMD_USE_SSE2)
- ::memset(&m_sse, 0, sizeof(m_sse));
+ m_sse = _mm_setzero_si128();
#elif defined(BOTAN_SIMD_USE_ALTIVEC)
m_vmx = vec_splat_u32(0);
#elif defined(BOTAN_SIMD_USE_NEON)
m_neon = vdupq_n_u32(0);
#else
- ::memset(m_scalar, 0, sizeof(m_scalar));
+ m_scalar[0] = 0;
+ m_scalar[1] = 0;
+ m_scalar[2] = 0;
+ m_scalar[3] = 0;
#endif
}
diff --git a/src/scripts/ci/setup_travis.sh b/src/scripts/ci/setup_travis.sh
index 39340b962..cfe78442a 100755
--- a/src/scripts/ci/setup_travis.sh
+++ b/src/scripts/ci/setup_travis.sh
@@ -75,5 +75,5 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
fi
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
- export PATH=$PATH:botan-ci-tools/macos
+ HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache
fi
diff --git a/src/scripts/ci/travis.yml b/src/scripts/ci/travis.yml
index ad5f34b9b..a26fc3989 100644
--- a/src/scripts/ci/travis.yml
+++ b/src/scripts/ci/travis.yml
@@ -94,7 +94,7 @@ install:
- ./src/scripts/ci/setup_travis.sh
script:
- - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then ./src/scripts/ci_build.py --os=$TRAVIS_OS_NAME --cc=$CC --cc-bin=$CXX $BUILD_MODE; fi
+ - ./src/scripts/ci_build.py --os=$TRAVIS_OS_NAME --cc=$CC --cc-bin=$CXX --compiler-cache=ccache $BUILD_MODE
# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
branches:
@@ -121,7 +121,6 @@ addons:
project:
name: "randombit/botan"
notification_email: [email protected]
- build_command_prepend: "./configure.py --no-optimizations --with-zlib"
+ build_command_prepend: "./configure.py --no-optimizations --with-zlib --with-openssl"
build_command: "make -j2"
branch_pattern: coverity_scan
-
diff --git a/src/scripts/ci_build.py b/src/scripts/ci_build.py
index bc4ea41e0..d2b83fd5e 100755
--- a/src/scripts/ci_build.py
+++ b/src/scripts/ci_build.py
@@ -279,11 +279,15 @@ def have_prog(prog):
return True
def main(args=None):
- # pylint: disable=too-many-branches,too-many-statements,too-many-locals
-
+ # pylint: disable=too-many-branches,too-many-statements,too-many-locals,too-many-return-statements
"""
Parse options, do the things
"""
+
+ if os.getenv('COVERITY_SCAN_BRANCH') == '1':
+ print('Skipping build COVERITY_SCAN_BRANCH set in environment')
+ return 0
+
(options, args) = parse_args(args or sys.argv)
if len(args) != 2:
diff --git a/src/tests/data/aead/gcm.vec b/src/tests/data/aead/gcm.vec
index 65a75873e..4a3c955b5 100644
--- a/src/tests/data/aead/gcm.vec
+++ b/src/tests/data/aead/gcm.vec
@@ -63,6 +63,21 @@ In = 00000000000000000000000000000000000000000000000000000000000000000000000
Out = A833DCC2EC04BEF5ED9E7E7FB08D61244CD795C21FEE194E7AAF7D9BD66B324F39FFC46DB5A7B9E1D6703F95290027DE6AC274CAE11C632F16261B71CE97EEA6CBE8A82B4F55F5A8B5CE1B268A7B35D8
+[AES-128/GCM(12)]
+# Nist | Test Case 5 with 12 byte tag
+Key = FEFFE9928665731C6D6A8F9467308308
+Nonce = CAFEBABEFACEDBAD
+In = D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39
+AD = FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2
+Out = 61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14A
+
+# Nist | Test Case 6 with 12 byte tag
+Key = FEFFE9928665731C6D6A8F9467308308
+Nonce = 9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B
+In = D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39
+AD = FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2
+Out = 8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C
+
[AES-192/GCM]
# Nist | Test Case 7
@@ -104,6 +119,23 @@ In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9
AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
Out = d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373bdcf566ff291c25bbb8568fc3d376a6d9
+
+[AES-192/GCM(12)]
+# Nist | Test Case 10 with 12 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
+Nonce = cafebabefacedbaddecaf888
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd
+
+# Nist | Test Case 11 with 12 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c
+Nonce = cafebabefacedbad
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca4
+
+
[AES-256/GCM]
# Nist | Test Case 13
Key = 0000000000000000000000000000000000000000000000000000000000000000
@@ -144,43 +176,132 @@ In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c9
AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
Out = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5ae9f19a
-[AES-128/GCM(8)]
-Key = 00000000000000000000000000000000
-Nonce = 000000000000000000000000
-In =
-Out = 58E2FCCEFA7E3061
+
+[AES-256/GCM(12)]
+# Nist | Test Case 16 with 12 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbaddecaf888
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853
+
+# Nist | Test Case 17 with 12 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbad
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913
+
+
+[AES-256/GCM(13)]
+# Nist | Test Case 16 with 13 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbaddecaf888
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb
+
+# Nist | Test Case 17 with 13 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbad
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe
+
+
+[AES-256/GCM(14)]
+# Nist | Test Case 16 with 14 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbaddecaf888
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb2d
+
+# Nist | Test Case 17 with 14 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbad
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe2e
+
+
+[AES-256/GCM(15)]
+# Nist | Test Case 16 with 15 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbaddecaf888
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb2d55
+
+# Nist | Test Case 17 with 15 byte tag
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+Nonce = cafebabefacedbad
+In = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+AD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Out = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe2ea8
# Wycheproof GCM tests
[AES-128/GCM(8)]
-# This was a 96 bit tag test, truncated since Botan GCM supports only 64/128
Key = 5b9604fe14eadba931b0ccf34843dab9
Nonce = 921d2507fa8007b7bd067d34
AD = 00112233445566778899aabbccddeeff
-In = 001d0c231287c1182784554ca3a21908
+In = 001d0c231287c1182784554ca3a21908
Out = 49d8b9783e911913d87094d1f63cc7651e348ba07cca2cf0
-[AES-128/GCM]
+[AES-128/GCM(12)]
+Key = 5b9604fe14eadba931b0ccf34843dab9
+Nonce = 921d2507fa8007b7bd067d34
+AD = 00112233445566778899aabbccddeeff
In = 001d0c231287c1182784554ca3a21908
+Out = 49d8b9783e911913d87094d1f63cc7651e348ba07cca2cf04c618cb4
+
+[AES-128/GCM]
Key = 5b9604fe14eadba931b0ccf34843dab9
Nonce = 028318abc1824029138141a2
+AD =
+In = 001d0c231287c1182784554ca3a21908
Out = 26073cc1d851beff176384dc9896d5ff0a3ea7a5487cb5f7d70fb6c58d038554
-In = 2035af313d1346ab00154fea78322105
Key = aa023d0478dcb2b2312498293d9a9129
Nonce = 0432bc49ac34412081288127
AD = aac39231129872a2
+In = 2035af313d1346ab00154fea78322105
Out = eea945f3d0f98cc0fbab472a0cf24e874bb9b4812519dadf9e1232016d068133
-In = 2035af313d1346ab00154fea78322105
Key = aa023d0478dcb2b2312498293d9a9129
Nonce = 0432bc49ac344120
AD = aac39231129872a2
+In = 2035af313d1346ab00154fea78322105
Out = 64c36bb3b732034e3a7d04efc5197785b7d0dd70b00d65b97cfd080ff4b819d1
-In = 02efd2e5782312827ed5d230189a2a342b277ce048462193
Key = 2034a82547276c83dd3212a813572bce
Nonce = 3254202d854734812398127a3d134421
AD = 1a0293d8f90219058902139013908190bc490890d3ff12a3
+In = 02efd2e5782312827ed5d230189a2a342b277ce048462193
Out = 64069c2d58690561f27ee199e6b479b6369eec688672bde99b7abadd6e69c1d9ec925786534f5075
+
+Key = 00112233445566778899aabbccddeeff
+Nonce = 7b95b8c356810a84711d68150a1b7750
+AD =
+In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000
+Out = 84d4c9c08b4f482861e3a9c6c35bc4d91df927374513bfd49f436bd73f325285daef4ff7e13d46a6213a3cb93855d18e69337eee66aeec07
+
+Key = 00112233445566778899aabbccddeeff
+Nonce = 1a552e67cdc4dc1a33b824874ebf0bed
+AD =
+In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000
+Out = 948ca37a8e6649e88aeffb1c598f3607007702417ea0e0bc3c60ad5a949886de968cf53ea6462aed99b381bfa2af9751c39d1b6e86d1be6a
+
+Key = 00112233445566778899aabbccddeeff
+Nonce = 99821c2dd5daecded07300f577f7aff1
+AD =
+In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000
+Out = 127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4af37d0fe9af033052bd537c4ae978f6007eb2fe4a958f8434d40684899507c7c
+
+Key = 00112233445566778899aabbccddeeff
+Nonce = 5e4a3900142358d1c774d8d124d8d27d
+AD =
+In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000
+Out = 0cf6ae47156b14dce03c8a07a2e172b1127af9b39ecdfc57bb11a2847c7c2d3d8f938f40f877e0c4f145c2dcaf339eede427be934357eac0
diff --git a/src/tests/data/ecc/ecc_private_with_rfc5915_parameters.pem b/src/tests/data/ecc/ecc_private_with_rfc5915_parameters.pem
new file mode 100644
index 000000000..9044ba49e
--- /dev/null
+++ b/src/tests/data/ecc/ecc_private_with_rfc5915_parameters.pem
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgQsaM/yuLh6H7UPb+
+1oizCkiyxY9Q4M9A+lfRxmwgZMWgCgYIKoZIzj0DAQehRANCAAScslLLwFzPl93W
+50kyRwyO222/yBoKAeheP45kM7QVuxul7flLp+heb0kk9zL0m0xH3PEoRBw32+77
+2L1OXOsH
+-----END PRIVATE KEY-----
diff --git a/src/tests/test_filters.cpp b/src/tests/test_filters.cpp
index 6199f88e2..7de68accb 100644
--- a/src/tests/test_filters.cpp
+++ b/src/tests/test_filters.cpp
@@ -43,6 +43,7 @@ class Filter_Tests : public Test
results.push_back(test_pipe_mac());
results.push_back(test_pipe_stream());
results.push_back(test_pipe_cbc());
+ results.push_back(test_pipe_cfb());
results.push_back(test_pipe_compress());
results.push_back(test_pipe_codec());
results.push_back(test_fork());
@@ -274,6 +275,76 @@ class Filter_Tests : public Test
return result;
}
+ Test::Result test_pipe_cfb()
+ {
+ Test::Result result("Pipe CFB");
+
+#if defined(BOTAN_HAS_BLOWFISH) && defined(BOTAN_HAS_MODE_CFB)
+
+ // Generated with Botan 1.10
+
+ const Botan::InitializationVector iv("AABBCCDDEEFF0123");
+ const Botan::SymmetricKey key("AABBCCDDEEFF0123");
+
+ const uint8_t msg_bits[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ const std::string cfb_expected[] = {
+ "A4",
+ "BEA4",
+ "06AD98",
+ "E4AFC5AC",
+ "A9B531559C",
+ "38B60DA66445",
+ "194F5E93199839",
+ "093B6381D2E5D806",
+ "B44FA624226EECF027",
+ "80B8DC3332A835AC11A8",
+ "2C0E910A1E5C38344CC5BB",
+ "3CB6180AE2E189342F681023",
+ "DE0F4B10C7D9CADDB5A9078199",
+ "FAE18B0ED873F234CCD6E1555B2D",
+ "7195FFE735B0A95065BA244C77A11F",
+ };
+
+ Botan::Keyed_Filter* cfb_enc =
+ new Botan::Cipher_Mode_Filter(Botan::get_cipher_mode("Blowfish/CFB", Botan::ENCRYPTION));
+ cfb_enc->set_key(key);
+ cfb_enc->set_iv(iv);
+ Botan::Pipe enc_pipe(cfb_enc, new Botan::Hex_Encoder);
+
+ Botan::Keyed_Filter* cfb_dec =
+ new Botan::Cipher_Mode_Filter(Botan::get_cipher_mode("Blowfish/CFB", Botan::DECRYPTION));
+ cfb_dec->set_key(key);
+ cfb_dec->set_iv(iv);
+ Botan::Pipe dec_pipe(new Botan::Hex_Decoder, cfb_dec, new Botan::Hex_Encoder);
+
+ for(size_t i = 1; i != sizeof(msg_bits); ++i)
+ {
+ enc_pipe.start_msg();
+ enc_pipe.write(msg_bits, i);
+ enc_pipe.end_msg();
+
+ dec_pipe.process_msg(cfb_expected[i-1]);
+ }
+
+ result.test_eq("enc pipe msg count", enc_pipe.message_count(), sizeof(msg_bits) - 1);
+ result.test_eq("dec pipe msg count", dec_pipe.message_count(), sizeof(msg_bits) - 1);
+
+ for(size_t i = 0; i != enc_pipe.message_count(); ++i)
+ {
+ result.test_eq("encrypt", enc_pipe.read_all_as_string(i), cfb_expected[i]);
+ }
+
+ for(size_t i = 0; i != dec_pipe.message_count(); ++i)
+ {
+ result.test_eq("decrypt", dec_pipe.read_all_as_string(i),
+ Botan::hex_encode(msg_bits, i+1));
+ }
+#endif
+
+ return result;
+ }
+
Test::Result test_pipe_cbc()
{
Test::Result result("Pipe CBC");
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index d7917bcc6..930d7c623 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -872,52 +872,13 @@ std::string strip_ws(const std::string& in)
return in.substr(first_c, last_c - first_c + 1);
}
-std::vector<Botan::CPUID::CPUID_bits> map_cpuid_string(const std::string& tok)
- {
-#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
- if(tok == "sse2" || tok == "simd")
- return {Botan::CPUID::CPUID_SSE2_BIT};
- if(tok == "ssse3")
- return {Botan::CPUID::CPUID_SSSE3_BIT};
- if(tok == "aesni")
- return {Botan::CPUID::CPUID_AESNI_BIT};
- if(tok == "clmul")
- return {Botan::CPUID::CPUID_CLMUL_BIT};
- if(tok == "avx2")
- return {Botan::CPUID::CPUID_AVX2_BIT};
- if(tok == "sha")
- return {Botan::CPUID::CPUID_SHA_BIT};
-
-#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
- if(tok == "altivec" || tok == "simd")
- return {Botan::CPUID::CPUID_ALTIVEC_BIT};
-
-#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
- if(tok == "neon" || tok == "simd")
- return {Botan::CPUID::CPUID_ARM_NEON_BIT};
- if(tok == "armv8sha1")
- return {Botan::CPUID::CPUID_ARM_SHA1_BIT};
- if(tok == "armv8sha2")
- return {Botan::CPUID::CPUID_ARM_SHA2_BIT};
- if(tok == "armv8aes")
- return {Botan::CPUID::CPUID_ARM_AES_BIT};
- if(tok == "armv8pmull")
- return {Botan::CPUID::CPUID_ARM_PMULL_BIT};
-
-#else
- BOTAN_UNUSED(tok);
-#endif
-
- return {};
- }
-
std::vector<Botan::CPUID::CPUID_bits>
parse_cpuid_bits(const std::vector<std::string>& tok)
{
std::vector<Botan::CPUID::CPUID_bits> bits;
for(size_t i = 1; i < tok.size(); ++i)
{
- const std::vector<Botan::CPUID::CPUID_bits> more = map_cpuid_string(tok[i]);
+ const std::vector<Botan::CPUID::CPUID_bits> more = Botan::CPUID::bit_from_string(tok[i]);
bits.insert(bits.end(), more.begin(), more.end());
}
diff --git a/src/tests/unit_ecdsa.cpp b/src/tests/unit_ecdsa.cpp
index ea622ade4..2654753eb 100644
--- a/src/tests/unit_ecdsa.cpp
+++ b/src/tests/unit_ecdsa.cpp
@@ -370,18 +370,40 @@ Test::Result test_ecc_key_with_rfc5915_extensions()
std::unique_ptr<Botan::Private_Key> pkcs8(
Botan::PKCS8::load_key(Test::data_file("ecc/ecc_private_with_rfc5915_ext.pem"), Test::rng()));
- result.confirm("loaded RFC 5914 key", pkcs8.get());
+ result.confirm("loaded RFC 5915 key", pkcs8.get());
result.test_eq("key is ECDSA", pkcs8->algo_name(), "ECDSA");
result.confirm("key type is ECDSA", dynamic_cast<Botan::ECDSA_PrivateKey*>(pkcs8.get()));
}
catch(std::exception& e)
{
- result.test_failure("load_rfc5915", e.what());
+ result.test_failure("load_rfc5915_ext", e.what());
}
return result;
}
+Test::Result test_ecc_key_with_rfc5915_parameters()
+ {
+ Test::Result result("ECDSA Unit");
+
+ try
+ {
+ std::unique_ptr<Botan::Private_Key> pkcs8(
+ Botan::PKCS8::load_key(Test::data_file("ecc/ecc_private_with_rfc5915_parameters.pem"), Test::rng()));
+
+ result.confirm("loaded RFC 5915 key", pkcs8.get());
+ result.test_eq("key is ECDSA", pkcs8->algo_name(), "ECDSA");
+ result.confirm("key type is ECDSA", dynamic_cast<Botan::ECDSA_PrivateKey*>(pkcs8.get()));
+ }
+ catch(std::exception& e)
+ {
+ result.test_failure("load_rfc5915_params", e.what());
+ }
+
+ return result;
+ }
+
+
class ECDSA_Unit_Tests : public Test
{
@@ -402,6 +424,7 @@ class ECDSA_Unit_Tests : public Test
results.push_back(test_unusual_curve());
results.push_back(test_curve_registry());
results.push_back(test_ecc_key_with_rfc5915_extensions());
+ results.push_back(test_ecc_key_with_rfc5915_parameters());
return results;
}
};