aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey/ec_group/point_mul.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pubkey/ec_group/point_mul.cpp')
-rw-r--r--src/lib/pubkey/ec_group/point_mul.cpp39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/lib/pubkey/ec_group/point_mul.cpp b/src/lib/pubkey/ec_group/point_mul.cpp
index 0a8f76d58..60e72d3ac 100644
--- a/src/lib/pubkey/ec_group/point_mul.cpp
+++ b/src/lib/pubkey/ec_group/point_mul.cpp
@@ -8,6 +8,7 @@
#include <botan/rng.h>
#include <botan/reducer.h>
#include <botan/internal/rounding.h>
+#include <botan/internal/ct_utils.h>
namespace Botan {
@@ -106,7 +107,9 @@ PointGFp PointGFp_Base_Point_Precompute::mul(const BigInt& k,
size_t windows = round_up(scalar.bits(), 2) / 2;
- BOTAN_ASSERT(windows <= m_W.size() / (3*2*m_p_words),
+ const size_t elem_size = 2*m_p_words;
+
+ BOTAN_ASSERT(windows <= m_W.size() / (3*elem_size),
"Precomputed sufficient values for scalar mult");
PointGFp R = m_base_point.zero();
@@ -114,24 +117,42 @@ PointGFp PointGFp_Base_Point_Precompute::mul(const BigInt& k,
if(ws.size() < PointGFp::WORKSPACE_SIZE)
ws.resize(PointGFp::WORKSPACE_SIZE);
+ // the precomputed multiples are not secret so use std::vector
+ std::vector<word> Wt(elem_size);
+
for(size_t i = 0; i != windows; ++i)
{
- if(i == 4)
+ const size_t base_addr = (3*i)*elem_size;
+
+ if(i == 5)
{
+ /*
+ * There is a small (1/1024) chance that the bottom 10 bits of the
+ * (randomized) scalar are all zero, in which case R is zero and so this
+ * randomization is ineffective. Instead we could randomize after the
+ * first non-zero exponent bits are processed, but that unfortunately
+ * introduces a side channel on the exponent, albeit likely not
+ * exploitable.
+ */
R.randomize_repr(rng, ws[0].get_word_vector());
}
- const uint32_t w = scalar.get_substring(2*i, 2);
+ const word w = scalar.get_substring(2*i, 2);
- // side channel here, we are relying on scalar blinding
- // TODO use masked lookup
+ const word w_is_1 = CT::is_equal<word>(w, 1);
+ const word w_is_2 = CT::is_equal<word>(w, 2);
+ const word w_is_3 = CT::is_equal<word>(w, 3);
- if(w > 0)
+ for(size_t j = 0; j != elem_size; ++j)
{
- const size_t idx = (3*i + w - 1)*2*m_p_words;
- R.add_affine(&m_W[idx], m_p_words,
- &m_W[idx + m_p_words], m_p_words, ws);
+ const word w1 = m_W[base_addr + 0*elem_size + j];
+ const word w2 = m_W[base_addr + 1*elem_size + j];
+ const word w3 = m_W[base_addr + 2*elem_size + j];
+
+ Wt[j] = CT::select3<word>(w_is_1, w1, w_is_2, w2, w_is_3, w3, 0);
}
+
+ R.add_affine(&Wt[0], m_p_words, &Wt[m_p_words], m_p_words, ws);
}
BOTAN_DEBUG_ASSERT(R.on_the_curve());