aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--doc/manual/tls.rst68
-rw-r--r--doc/manual/x509.rst6
-rw-r--r--doc/news.rst8
-rw-r--r--src/lib/block/idea/idea.cpp28
-rw-r--r--src/lib/block/idea_sse2/idea_sse2.cpp12
-rw-r--r--src/lib/cert/x509/x509cert.cpp6
-rw-r--r--src/lib/cert/x509/x509cert.h4
-rw-r--r--src/lib/math/mp/mp_monty.cpp23
-rw-r--r--src/lib/pk_pad/eme_oaep/oaep.cpp16
-rw-r--r--src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp16
-rw-r--r--src/lib/pubkey/curve25519/donna.cpp10
-rw-r--r--src/lib/pubkey/pk_keys.cpp6
-rw-r--r--src/lib/utils/ct_utils.h119
-rwxr-xr-xsrc/scripts/ci/travis/build.sh8
-rwxr-xr-xsrc/scripts/ci/travis/install_osx_packages.sh2
16 files changed, 162 insertions, 172 deletions
diff --git a/.travis.yml b/.travis.yml
index 2efbb1f91..b4f11be7d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -83,6 +83,8 @@ addons:
- zlib1g-dev
- libbz2-dev
- liblzma-dev
+ - python2
+ - python3
coverity_scan:
project:
diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst
index 554846c25..4226f3694 100644
--- a/doc/manual/tls.rst
+++ b/doc/manual/tls.rst
@@ -194,19 +194,20 @@ TLS Clients
.. cpp:class:: TLS::Client
- .. cpp:function:: TLS::Client( \
- output_fn output, \
- data_cb data, \
- alert_cb alert, \
- handshake_cb handshake_complete, \
- TLS::Session_Manager& session_manager, \
- Credentials_Manager& credendials_manager, \
- const TLS::Policy& policy, \
- RandomNumberGenerator& rng, \
- const Server_Information& server_info, \
- const Protocol_Version offer_version, \
- const std::vector<std::string>& app_protocols,
- size_t reserved_io_buffer_size)
+ .. cpp:function:: Client( \
+ output_fn out, \
+ data_cb app_data_cb, \
+ alert_cb alert_cb, \
+ handshake_cb hs_cb, \
+ Session_Manager& session_manager, \
+ Credentials_Manager& creds, \
+ const Policy& policy, \
+ RandomNumberGenerator& rng, \
+ const Server_Information& server_info = Server_Information(), \
+ const Protocol_Version offer_version = Protocol_Version::latest_tls_version(), \
+ const std::vector<std::string>& next_protocols = {}, \
+ size_t reserved_io_buffer_size = 16*1024 \
+ )
Initialize a new TLS client. The constructor will immediately
initiate a new session.
@@ -284,20 +285,21 @@ TLS Servers
.. cpp:class:: TLS::Server
- .. cpp:function:: TLS::Server( \
- std::function<void, const byte*, size_t> output_fn, \
- std::function<void, const byte*, size_t> data_cb, \
- std::function<TLS::Alert, const byte*, size_t> alert_cb, \
- TLS::Session_Manager& session_manager, \
- Credentials_Manager& creds, \
- const TLS::Policy& policy, \
- RandomNumberGenerator& rng, \
- std::function<std::string, std::vector<std::string> > proto_chooser,
- const std::vector<std::string>& protocols, \
- bool is_datagram = false, \
- bool reserved_io_buffer_size)
-
-The first 7 arguments as well as the final argument
+ .. cpp:function:: Server( \
+ output_fn output, \
+ data_cb data_cb, \
+ alert_cb alert_cb, \
+ handshake_cb handshake_cb, \
+ Session_Manager& session_manager, \
+ Credentials_Manager& creds, \
+ const Policy& policy, \
+ RandomNumberGenerator& rng, \
+ next_protocol_fn next_proto = next_protocol_fn(), \
+ bool is_datagram = false, \
+ size_t reserved_io_buffer_size = 16*1024 \
+ )
+
+The first 8 arguments as well as the final argument
*reserved_io_buffer_size*, are treated similiarly to the :ref:`client
<tls_client>`.
@@ -742,20 +744,10 @@ The ``TLS::Protocol_Version`` class represents a specific version:
.. cpp:class:: TLS::Protocol_Version
- .. cpp:type:: enum Version_Code
+ .. cpp:enum:: Version_Code
``TLS_V10``, ``TLS_V11``, ``TLS_V12``, ``DTLS_V10``, ``DTLS_V12``
- .. cpp:function:: static Protocol_Version latest_tls_version()
-
- Returns the latest version of TLS supported by this implementation
- (currently TLS v1.2)
-
- .. cpp:function:: static Protocol_Version latest_dtls_version()
-
- Returns the latest version of DTLS supported by this implementation
- (currently DTLS v1.2)
-
.. cpp:function:: Protocol_Version(Version_Code named_version)
Create a specific version
diff --git a/doc/manual/x509.rst b/doc/manual/x509.rst
index d4500d692..84263ae3d 100644
--- a/doc/manual/x509.rst
+++ b/doc/manual/x509.rst
@@ -20,13 +20,13 @@ in the :doc:`tls` protocol. A X.509 certificate is represented by
Returns the public key of the subject
- .. cpp:function:: X509_DN subject_dn() const
+ .. cpp:function:: X509_DN issuer_dn() const
- Returns the distinguished name of the issuer
+ Returns the distinguished name (DN) of the certificate's issuer
.. cpp:function:: X509_DN subject_dn() const
- Returns the distinguished name of the issuer
+ Returns the distinguished name (DN) of the certificate's subject
.. cpp:function:: std::string start_time() const
diff --git a/doc/news.rst b/doc/news.rst
index 00a102427..72ab4ad9f 100644
--- a/doc/news.rst
+++ b/doc/news.rst
@@ -14,12 +14,16 @@ Version 1.11.22, Not Yet Released
By writing the code such that it does not depend on secret inputs for branch
or memory indexes, such a side channel would be much less likely to exist.
+ The OAEP code has previously made an attempt at constant time operation, but
+ it used a construct which many compilers converted into a conditional jump.
+
* Add support for using ctgrind (https://github.com/agl/ctgrind) to test that
sections of code do not use secret inputs to decide branches or memory indexes.
The testing relies on dynamic checking using valgrind.
- So far PKCS #1 decoding, OAEP decoding, IDEA, and Curve25519 have been notated
- and confirmed to be constant time.
+ So far PKCS #1 decoding, OAEP decoding, Montgomery reduction, IDEA, and
+ Curve25519 have been notated and confirmed to be constant time on Linux/x86-64
+ when compiled by gcc.
* Public key operations can now be used with specified providers by passing an
additional parameter to the constructor of the PK operation.
diff --git a/src/lib/block/idea/idea.cpp b/src/lib/block/idea/idea.cpp
index c7706b372..8069e16f7 100644
--- a/src/lib/block/idea/idea.cpp
+++ b/src/lib/block/idea/idea.cpp
@@ -20,7 +20,7 @@ inline u16bit mul(u16bit x, u16bit y)
{
const u32bit P = static_cast<u32bit>(x) * y;
- const u16bit Z_mask = static_cast<u16bit>(ct_expand_mask_32(P) & 0xFFFF);
+ const u16bit Z_mask = static_cast<u16bit>(CT::expand_mask(P) & 0xFFFF);
const u32bit P_hi = P >> 16;
const u32bit P_lo = P & 0xFFFF;
@@ -28,7 +28,7 @@ inline u16bit mul(u16bit x, u16bit y)
const u16bit r_1 = (P_lo - P_hi) + (P_lo < P_hi);
const u16bit r_2 = 1 - x - y;
- return ct_select_mask_16(Z_mask, r_1, r_2);
+ return CT::select(Z_mask, r_1, r_2);
}
/*
@@ -62,9 +62,9 @@ void idea_op(const byte in[], byte out[], size_t blocks, const u16bit K[52])
{
const size_t BLOCK_SIZE = 8;
- BOTAN_CONST_TIME_POISON(in, blocks * 8);
- BOTAN_CONST_TIME_POISON(out, blocks * 8);
- BOTAN_CONST_TIME_POISON(K, 52 * 2);
+ CT::poison(in, blocks * 8);
+ CT::poison(out, blocks * 8);
+ CT::poison(K, 52);
for(size_t i = 0; i != blocks; ++i)
{
@@ -101,9 +101,9 @@ void idea_op(const byte in[], byte out[], size_t blocks, const u16bit K[52])
store_be(out + BLOCK_SIZE*i, X1, X3, X2, X4);
}
- BOTAN_CONST_TIME_UNPOISON(in, blocks * 8);
- BOTAN_CONST_TIME_UNPOISON(out, blocks * 8);
- BOTAN_CONST_TIME_UNPOISON(K, 52 * 2);
+ CT::unpoison(in, blocks * 8);
+ CT::unpoison(out, blocks * 8);
+ CT::unpoison(K, 52);
}
}
@@ -132,9 +132,9 @@ void IDEA::key_schedule(const byte key[], size_t)
EK.resize(52);
DK.resize(52);
- BOTAN_CONST_TIME_POISON(key, 16);
- BOTAN_CONST_TIME_POISON(EK.data(), 52 * 2);
- BOTAN_CONST_TIME_POISON(DK.data(), 52 * 2);
+ CT::poison(key, 16);
+ CT::poison(EK.data(), 52);
+ CT::poison(DK.data(), 52);
for(size_t i = 0; i != 8; ++i)
EK[i] = load_be<u16bit>(key, i);
@@ -168,9 +168,9 @@ void IDEA::key_schedule(const byte key[], size_t)
DK[1] = -EK[49];
DK[0] = mul_inv(EK[48]);
- BOTAN_CONST_TIME_UNPOISON(key, 16);
- BOTAN_CONST_TIME_UNPOISON(EK.data(), 52 * 2);
- BOTAN_CONST_TIME_UNPOISON(DK.data(), 52 * 2);
+ CT::unpoison(key, 16);
+ CT::unpoison(EK.data(), 52);
+ CT::unpoison(DK.data(), 52);
}
void IDEA::clear()
diff --git a/src/lib/block/idea_sse2/idea_sse2.cpp b/src/lib/block/idea_sse2/idea_sse2.cpp
index 51b5e909b..c7d846e8b 100644
--- a/src/lib/block/idea_sse2/idea_sse2.cpp
+++ b/src/lib/block/idea_sse2/idea_sse2.cpp
@@ -131,9 +131,9 @@ void transpose_out(__m128i& B0, __m128i& B1, __m128i& B2, __m128i& B3)
*/
void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52])
{
- BOTAN_CONST_TIME_POISON(in, 64);
- BOTAN_CONST_TIME_POISON(out, 64);
- BOTAN_CONST_TIME_POISON(EK, 52*2);
+ CT::poison(in, 64);
+ CT::poison(out, 64);
+ CT::poison(EK, 52);
const __m128i* in_mm = reinterpret_cast<const __m128i*>(in);
@@ -195,9 +195,9 @@ void idea_op_8(const byte in[64], byte out[64], const u16bit EK[52])
_mm_storeu_si128(out_mm + 2, B1);
_mm_storeu_si128(out_mm + 3, B3);
- BOTAN_CONST_TIME_UNPOISON(in, 64);
- BOTAN_CONST_TIME_UNPOISON(out, 64);
- BOTAN_CONST_TIME_UNPOISON(EK, 52*2);
+ CT::unpoison(in, 64);
+ CT::unpoison(out, 64);
+ CT::unpoison(EK, 52);
}
}
diff --git a/src/lib/cert/x509/x509cert.cpp b/src/lib/cert/x509/x509cert.cpp
index 0cfc1cd99..3d1ebbbad 100644
--- a/src/lib/cert/x509/x509cert.cpp
+++ b/src/lib/cert/x509/x509cert.cpp
@@ -337,9 +337,6 @@ std::vector<byte> X509_Certificate::serial_number() const
return subject.get1_memvec("X509.Certificate.serial");
}
-/*
-* Return the distinguished name of the issuer
-*/
X509_DN X509_Certificate::issuer_dn() const
{
return create_dn(issuer);
@@ -350,9 +347,6 @@ std::vector<byte> X509_Certificate::raw_issuer_dn() const
return issuer.get1_memvec("X509.Certificate.dn_bits");
}
-/*
-* Return the distinguished name of the subject
-*/
X509_DN X509_Certificate::subject_dn() const
{
return create_dn(subject);
diff --git a/src/lib/cert/x509/x509cert.h b/src/lib/cert/x509/x509cert.h
index d57d4f23f..578360a80 100644
--- a/src/lib/cert/x509/x509cert.h
+++ b/src/lib/cert/x509/x509cert.h
@@ -46,13 +46,13 @@ class BOTAN_DLL X509_Certificate : public X509_Object
std::vector<byte> subject_public_key_bits() const;
/**
- * Get the issuer certificate DN.
+ * Get the certificate's issuer distinguished name (DN).
* @return issuer DN of this certificate
*/
X509_DN issuer_dn() const;
/**
- * Get the subject certificate DN.
+ * Get the certificate's subject distinguished name (DN).
* @return subject DN of this certificate
*/
X509_DN subject_dn() const;
diff --git a/src/lib/math/mp/mp_monty.cpp b/src/lib/math/mp/mp_monty.cpp
index 820f41e6c..7e427b540 100644
--- a/src/lib/math/mp/mp_monty.cpp
+++ b/src/lib/math/mp/mp_monty.cpp
@@ -9,6 +9,7 @@
#include <botan/internal/mp_core.h>
#include <botan/internal/mp_madd.h>
#include <botan/internal/mp_asmi.h>
+#include <botan/internal/ct_utils.h>
#include <botan/mem_ops.h>
namespace Botan {
@@ -22,6 +23,10 @@ void bigint_monty_redc(word z[],
{
const size_t z_size = 2*(p_size+1);
+ CT::poison(z, z_size);
+ CT::poison(p, p_size);
+ CT::poison(ws, 2*(p_size+1));
+
const size_t blocks_of_8 = p_size - (p_size % 8);
for(size_t i = 0; i != p_size; ++i)
@@ -47,10 +52,10 @@ void bigint_monty_redc(word z[],
carry = (z_sum < z_i[p_size]);
z_i[p_size] = z_sum;
- for(size_t j = p_size + 1; carry && j != z_size - i; ++j)
+ for(size_t j = p_size + 1; j < z_size - i; ++j)
{
- ++z_i[j];
- carry = !z_i[j];
+ z_i[j] += carry;
+ carry = carry & !z_i[j];
}
}
@@ -73,12 +78,18 @@ void bigint_monty_redc(word z[],
ws[p_size] = word_sub(z[p_size+p_size], 0, &borrow);
- BOTAN_ASSERT(borrow == 0 || borrow == 1, "Expected borrow");
-
copy_mem(ws + p_size + 1, z + p_size, p_size + 1);
- copy_mem(z, ws + borrow*(p_size+1), p_size + 1);
+ CT::conditional_copy_mem(borrow, z, ws + (p_size + 1), ws, (p_size + 1));
clear_mem(z + p_size + 1, z_size - p_size - 1);
+
+ CT::unpoison(z, z_size);
+ CT::unpoison(p, p_size);
+ CT::unpoison(ws, 2*(p_size+1));
+
+ // This check comes after we've used it but that's ok here
+ CT::unpoison(&borrow, 1);
+ BOTAN_ASSERT(borrow == 0 || borrow == 1, "Expected borrow");
}
void bigint_monty_mul(word z[], size_t z_size,
diff --git a/src/lib/pk_pad/eme_oaep/oaep.cpp b/src/lib/pk_pad/eme_oaep/oaep.cpp
index b114afb8b..370a9fe45 100644
--- a/src/lib/pk_pad/eme_oaep/oaep.cpp
+++ b/src/lib/pk_pad/eme_oaep/oaep.cpp
@@ -84,7 +84,7 @@ secure_vector<byte> OAEP::unpad(const byte in[], size_t in_length,
secure_vector<byte> input(key_length);
buffer_insert(input, key_length - in_length, in, in_length);
- BOTAN_CONST_TIME_POISON(input.data(), input.size());
+ CT::poison(input.data(), input.size());
const size_t hlen = m_Phash.size();
@@ -102,25 +102,25 @@ secure_vector<byte> OAEP::unpad(const byte in[], size_t in_length,
for(size_t i = delim_idx; i < input.size(); ++i)
{
- const byte zero_m = ct_is_zero_8(input[i]);
- const byte one_m = ct_is_equal_8(input[i], 1);
+ const byte zero_m = CT::is_zero<byte>(input[i]);
+ const byte one_m = CT::is_equal<byte>(input[i], 1);
const byte add_m = waiting_for_delim & zero_m;
bad_input |= waiting_for_delim & ~(zero_m | one_m);
- delim_idx += ct_select_mask_8(add_m, 1, 0);
+ delim_idx += CT::select<byte>(add_m, 1, 0);
waiting_for_delim &= zero_m;
}
// If we never saw any non-zero byte, then it's not valid input
bad_input |= waiting_for_delim;
- bad_input |= ct_expand_mask_8(!same_mem(&input[hlen], m_Phash.data(), hlen));
+ bad_input |= CT::expand_mask<byte>(!same_mem(&input[hlen], m_Phash.data(), hlen));
- BOTAN_CONST_TIME_UNPOISON(input.data(), input.size());
- BOTAN_CONST_TIME_UNPOISON(&bad_input, sizeof(bad_input));
- BOTAN_CONST_TIME_UNPOISON(&delim_idx, sizeof(delim_idx));
+ CT::unpoison(input.data(), input.size());
+ CT::unpoison(&bad_input, 1);
+ CT::unpoison(&delim_idx, 1);
if(bad_input)
throw Decoding_Error("Invalid OAEP encoding");
diff --git a/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp b/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp
index 219e93251..6b3bce0aa 100644
--- a/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp
+++ b/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp
@@ -44,29 +44,29 @@ secure_vector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen,
if(inlen != key_len / 8 || inlen < 10)
throw Decoding_Error("PKCS1::unpad");
- BOTAN_CONST_TIME_POISON(in, inlen);
+ CT::poison(in, inlen);
byte bad_input_m = 0;
byte seen_zero_m = 0;
size_t delim_idx = 0;
- bad_input_m |= ~ct_is_equal_8(in[0], 2);
+ bad_input_m |= ~CT::is_equal<byte>(in[0], 2);
for(size_t i = 1; i != inlen; ++i)
{
- const byte is_zero_m = ct_is_zero_8(in[i]);
+ const byte is_zero_m = CT::is_zero<byte>(in[i]);
- delim_idx += ct_select_mask_8(~seen_zero_m, 1, 0);
+ delim_idx += CT::select<byte>(~seen_zero_m, 1, 0);
- bad_input_m |= is_zero_m & ct_expand_mask_8(i < 9);
+ bad_input_m |= is_zero_m & CT::expand_mask<byte>(i < 9);
seen_zero_m |= is_zero_m;
}
bad_input_m |= ~seen_zero_m;
- BOTAN_CONST_TIME_UNPOISON(in, inlen);
- BOTAN_CONST_TIME_UNPOISON(&bad_input_m, sizeof(bad_input_m));
- BOTAN_CONST_TIME_UNPOISON(&delim_idx, sizeof(delim_idx));
+ CT::unpoison(in, inlen);
+ CT::unpoison(&bad_input_m, 1);
+ CT::unpoison(&delim_idx, 1);
if(bad_input_m)
throw Decoding_Error("Invalid PKCS #1 v1.5 encryption padding");
diff --git a/src/lib/pubkey/curve25519/donna.cpp b/src/lib/pubkey/curve25519/donna.cpp
index ab9363761..78966f745 100644
--- a/src/lib/pubkey/curve25519/donna.cpp
+++ b/src/lib/pubkey/curve25519/donna.cpp
@@ -420,8 +420,8 @@ crecip(felem out, const felem z) {
int
curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
- BOTAN_CONST_TIME_POISON(secret, 32);
- BOTAN_CONST_TIME_POISON(basepoint, 32);
+ CT::poison(secret, 32);
+ CT::poison(basepoint, 32);
limb bp[5], x[5], z[5], zmone[5];
uint8_t e[32];
@@ -438,9 +438,9 @@ curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
fmul(z, x, zmone);
fcontract(mypublic, z);
- BOTAN_CONST_TIME_UNPOISON(secret, 32);
- BOTAN_CONST_TIME_UNPOISON(basepoint, 32);
- BOTAN_CONST_TIME_UNPOISON(mypublic, 32);
+ CT::unpoison(secret, 32);
+ CT::unpoison(basepoint, 32);
+ CT::unpoison(mypublic, 32);
return 0;
}
diff --git a/src/lib/pubkey/pk_keys.cpp b/src/lib/pubkey/pk_keys.cpp
index f92492fa9..635934037 100644
--- a/src/lib/pubkey/pk_keys.cpp
+++ b/src/lib/pubkey/pk_keys.cpp
@@ -31,7 +31,7 @@ OID Public_Key::get_oid() const
void Public_Key::load_check(RandomNumberGenerator& rng) const
{
if(!check_key(rng, BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD))
- throw Invalid_Argument(algo_name() + ": Invalid public key");
+ throw Invalid_Argument("Invalid public key");
}
/*
@@ -40,7 +40,7 @@ void Public_Key::load_check(RandomNumberGenerator& rng) const
void Private_Key::load_check(RandomNumberGenerator& rng) const
{
if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_LOAD))
- throw Invalid_Argument(algo_name() + ": Invalid private key");
+ throw Invalid_Argument("Invalid private key");
}
/*
@@ -49,7 +49,7 @@ void Private_Key::load_check(RandomNumberGenerator& rng) const
void Private_Key::gen_check(RandomNumberGenerator& rng) const
{
if(!check_key(rng, BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE))
- throw Self_Test_Failure(algo_name() + " private key generation failed");
+ throw Self_Test_Failure("Private key generation failed");
}
}
diff --git a/src/lib/utils/ct_utils.h b/src/lib/utils/ct_utils.h
index 4ae735330..52a3bc388 100644
--- a/src/lib/utils/ct_utils.h
+++ b/src/lib/utils/ct_utils.h
@@ -27,105 +27,82 @@ extern "C" void ct_unpoison(const void* address, size_t length);
namespace Botan {
-#if defined(BOTAN_USE_CTGRIND)
-
-#define BOTAN_CONST_TIME_POISON(p, l) ct_poison(p, l)
-#define BOTAN_CONST_TIME_UNPOISON(p, l) ct_unpoison(p, l)
+namespace CT {
+template<typename T>
+inline void poison(T* p, size_t n)
+ {
+#if defined(BOTAN_USE_CTGRIND)
+ ct_poison(p, sizeof(T)*n);
#else
+ BOTAN_UNUSED(p);
+ BOTAN_UNUSED(n);
+#endif
+ }
-#define BOTAN_CONST_TIME_POISON(p, l)
-#define BOTAN_CONST_TIME_UNPOISON(p, l)
-
+template<typename T>
+inline void unpoison(T* p, size_t n)
+ {
+#if defined(BOTAN_USE_CTGRIND)
+ ct_unpoison(p, sizeof(T)*n);
+#else
+ BOTAN_UNUSED(p);
+ BOTAN_UNUSED(n);
#endif
+ }
/*
+* T should be an unsigned machine integer type
* Expand to a mask used for other operations
* @param in an integer
-* @return 0 if in == 0 else 0xFFFFFFFF
+* @return If n is zero, returns zero. Otherwise
+* returns a T with all bits set for use as a mask with
+* select.
*/
-inline uint32_t ct_expand_mask_32(uint32_t x)
+template<typename T>
+inline T expand_mask(T x)
{
- // First fold x down to a single bit:
- uint32_t r = x;
- r |= r >> 16;
- r |= r >> 8;
- r |= r >> 4;
- r |= r >> 2;
- r |= r >> 1;
+ T r = x;
+ // First fold r down to a single bit
+ for(size_t i = 1; i != sizeof(T)*8; i *= 2)
+ r |= r >> i;
r &= 1;
- // assumes 2s complement signed representation
r = ~(r - 1);
return r;
}
-inline uint32_t ct_select_mask_32(uint32_t mask, uint32_t a, uint32_t b)
+template<typename T>
+inline T select(T mask, T from0, T from1)
{
- return (a & mask) | (b & ~mask);
+ return (from0 & mask) | (from1 & ~mask);
}
-inline uint32_t ct_is_zero_32(uint32_t x)
+template<typename T>
+inline T is_zero(T x)
{
- return ~ct_expand_mask_32(x);
+ return ~expand_mask(x);
}
-inline uint32_t ct_is_equal_32(uint32_t x, uint32_t y)
+template<typename T>
+inline T is_equal(T x, T y)
{
- return ct_is_zero_32(x ^ y);
+ return is_zero(x ^ y);
}
-inline uint16_t ct_expand_mask_16(uint16_t x)
+template<typename T>
+inline void conditional_copy_mem(T value,
+ T* to,
+ const T* from0,
+ const T* from1,
+ size_t bytes)
{
- uint16_t r = x;
- r |= r >> 8;
- r |= r >> 4;
- r |= r >> 2;
- r |= r >> 1;
- r &= 1;
- r = ~(r - 1);
- return r;
- }
+ const T mask = CT::expand_mask(value);
-inline uint16_t ct_select_mask_16(uint16_t mask, uint16_t a, uint16_t b)
- {
- return (a & mask) | (b & ~mask);
- }
-
-inline uint16_t ct_is_zero_16(uint16_t x)
- {
- return ~ct_expand_mask_16(x);
+ for(size_t i = 0; i != bytes; ++i)
+ to[i] = CT::select(mask, from0[i], from1[i]);
}
-inline uint16_t ct_is_equal_16(uint16_t x, uint16_t y)
- {
- return ct_is_zero_16(x ^ y);
- }
-
-inline uint8_t ct_expand_mask_8(uint8_t x)
- {
- uint8_t r = x;
- r |= r >> 4;
- r |= r >> 2;
- r |= r >> 1;
- r &= 1;
- r = ~(r - 1);
- return r;
- }
-
-inline uint8_t ct_select_mask_8(uint8_t mask, uint8_t a, uint8_t b)
- {
- return (a & mask) | (b & ~mask);
- }
-
-inline uint8_t ct_is_zero_8(uint8_t x)
- {
- return ~ct_expand_mask_8(x);
- }
-
-inline uint8_t ct_is_equal_8(uint8_t x, uint8_t y)
- {
- return ct_is_zero_8(x ^ y);
- }
+}
}
diff --git a/src/scripts/ci/travis/build.sh b/src/scripts/ci/travis/build.sh
index 369450091..bb52f0648 100755
--- a/src/scripts/ci/travis/build.sh
+++ b/src/scripts/ci/travis/build.sh
@@ -60,4 +60,12 @@ if [ "$MODULES" != "min" ] && [ "${TARGETOS:0:3}" != "ios" ]; then
./botan-test
fi
+if [ "$MODULES" != "min" ] && [ "$BUILD_MODE" = "shared" ] && [ "$TARGETOS" = "desktop" ]
+then
+ python2 --version
+ python3 --version
+ LD_LIBRARY_PATH=. python2 src/python/botan.py
+ LD_LIBRARY_PATH=. python3 src/python/botan.py
+fi
+
make install
diff --git a/src/scripts/ci/travis/install_osx_packages.sh b/src/scripts/ci/travis/install_osx_packages.sh
index 1d4a5e001..588855cc0 100755
--- a/src/scripts/ci/travis/install_osx_packages.sh
+++ b/src/scripts/ci/travis/install_osx_packages.sh
@@ -6,3 +6,5 @@ which shellcheck > /dev/null && shellcheck "$0" # Run shellcheck on this if avai
brew update || brew update
brew install xz
+brew install python # python2
+brew install python3