diff options
Diffstat (limited to 'src')
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; } }; |