commit bcf13fa153a11b3e0ad54e2af6962441cea3adf1
Author: Jack Lloyd <lloyd@randombit.net>
Date:   Sat Apr 23 07:01:19 2016 -0400

    Fixes for CVE-2015-7827 and CVE-2016-2849

diff --git a/src/math/mp/mp_asm.cpp b/src/math/mp/mp_asm.cpp
index 3ba52c4b1..523f9390f 100644
--- a/src/math/mp/mp_asm.cpp
+++ b/src/math/mp/mp_asm.cpp
@@ -9,6 +9,7 @@
 #include <botan/internal/mp_asm.h>
 #include <botan/internal/mp_asmi.h>
 #include <botan/internal/mp_core.h>
+#include <botan/internal/ct_utils.h>
 #include <botan/exceptn.h>
 #include <botan/mem_ops.h>
 
@@ -17,6 +18,76 @@ namespace Botan {
 extern "C" {
 
 /*
+* If cond == 0, does nothing.
+* If cond > 0, swaps x[0:size] with y[0:size]
+* Runs in constant time
+*/
+void bigint_cnd_swap(word cnd, word x[], word y[], size_t size)
+   {
+   const word mask = CT::expand_mask(cnd);
+
+   for(size_t i = 0; i != size; ++i)
+      {
+      word a = x[i];
+      word b = y[i];
+      x[i] = CT::select(mask, b, a);
+      y[i] = CT::select(mask, a, b);
+      }
+   }
+
+/*
+* If cond > 0 adds x[0:size] to y[0:size] and returns carry
+* Runs in constant time
+*/
+word bigint_cnd_add(word cnd, word x[], const word y[], size_t size)
+   {
+   const word mask = CT::expand_mask(cnd);
+
+   word carry = 0;
+   for(size_t i = 0; i != size; ++i)
+      {
+      /*
+      Here we are relying on asm version of word_add being
+      a single addcl or equivalent. Fix this.
+      */
+      const word z = word_add(x[i], y[i], &carry);
+      x[i] = CT::select(mask, z, x[i]);
+      }
+
+   return carry & mask;
+   }
+
+/*
+* If cond > 0 subs x[0:size] to y[0:size] and returns borrow
+* Runs in constant time
+*/
+word bigint_cnd_sub(word cnd, word x[], const word y[], size_t size)
+   {
+   const word mask = CT::expand_mask(cnd);
+
+   word carry = 0;
+   for(size_t i = 0; i != size; ++i)
+      {
+      const word z = word_sub(x[i], y[i], &carry);
+      x[i] = CT::select(mask, z, x[i]);
+      }
+
+   return carry & mask;
+   }
+
+void bigint_cnd_abs(word cnd, word x[], size_t size)
+   {
+   const word mask = CT::expand_mask(cnd);
+
+   word carry = mask & 1;
+   for(size_t i = 0; i != size; ++i)
+      {
+      const word z = word_add(~x[i], 0, &carry);
+      x[i] = CT::select(mask, z, x[i]);
+      }
+   }
+
+/*
 * Two Operand Addition, No Carry
 */
 word bigint_add2_nc(word x[], size_t x_size, const word y[], size_t y_size)
diff --git a/src/math/mp/mp_core.h b/src/math/mp/mp_core.h
index 82bdbad53..ac3ef6cad 100644
--- a/src/math/mp/mp_core.h
+++ b/src/math/mp/mp_core.h
@@ -20,6 +20,32 @@ const size_t MP_WORD_BITS = BOTAN_MP_WORD_BITS;
 extern "C" {
 
 /*
+* If cond == 0, does nothing.
+* If cond > 0, swaps x[0:size] with y[0:size]
+* Runs in constant time
+*/
+void bigint_cnd_swap(word cnd, word x[], word y[], size_t size);
+
+/*
+* If cond > 0 adds x[0:size] to y[0:size] and returns carry
+* Runs in constant time
+*/
+word bigint_cnd_add(word cnd, word x[], const word y[], size_t size);
+
+/*
+* If cond > 0 subs x[0:size] to y[0:size] and returns borrow
+* Runs in constant time
+*/
+word bigint_cnd_sub(word cnd, word x[], const word y[], size_t size);
+
+/*
+* 2s complement absolute value
+* If cond > 0 sets x to ~x + 1
+* Runs in constant time
+*/
+void bigint_cnd_abs(word cnd, word x[], size_t size);
+
+/*
 * Addition/Subtraction Operations
 */
 void bigint_add2(word x[], size_t x_size,
diff --git a/src/math/numbertheory/numthry.cpp b/src/math/numbertheory/numthry.cpp
index 535ca6772..4ffb9aff5 100644
--- a/src/math/numbertheory/numthry.cpp
+++ b/src/math/numbertheory/numthry.cpp
@@ -7,6 +7,7 @@
 
 #include <botan/numthry.h>
 #include <botan/reducer.h>
+#include <botan/internal/mp_core.h>
 #include <botan/internal/bit_ops.h>
 #include <algorithm>
 
@@ -196,6 +197,117 @@ BigInt lcm(const BigInt& a, const BigInt& b)
    return ((a * b) / gcd(a, b));
    }
 
+namespace {
+
+BigInt ct_inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod)
+   {
+   if(n.is_negative() || mod.is_negative())
+      throw Invalid_Argument("ct_inverse_mod_odd_modulus: arguments must be non-negative");
+   if(mod < 3 || mod.is_even())
+      throw Invalid_Argument("Bad modulus to ct_inverse_mod_odd_modulus");
+
+   /*
+   This uses a modular inversion algorithm designed by Niels Möller
+   and implemented in Nettle. The same algorithm was later also
+   adapted to GMP in mpn_sec_invert.
+
+   It can be easily implemented in a way that does not depend on
+   secret branches or memory lookups, providing resistance against
+   some forms of side channel attack.
+
+   There is also a description of the algorithm in Appendix 5 of "Fast
+   Software Polynomial Multiplication on ARM Processors using the NEON Engine"
+   by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo
+   Dahab in LNCS 8182
+      http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf
+
+   Thanks to Niels for creating the algorithm, explaining some things
+   about it, and the reference to the paper.
+   */
+
+   // todo allow this to be pre-calculated and passed in as arg
+   BigInt mp1o2 = (mod + 1) >> 1;
+
+   const size_t mod_words = mod.sig_words();
+
+   BigInt a = n;
+   BigInt b = mod;
+   BigInt u = 1, v = 0;
+
+   a.grow_to(mod_words);
+   u.grow_to(mod_words);
+   v.grow_to(mod_words);
+   mp1o2.grow_to(mod_words);
+
+   SecureVector<word>& a_w = a.get_reg();
+   SecureVector<word>& b_w = b.get_reg();
+   SecureVector<word>& u_w = u.get_reg();
+   SecureVector<word>& v_w = v.get_reg();
+
+   // Only n.bits() + mod.bits() iterations are required, but avoid leaking the size of n
+   size_t bits = 2 * mod.bits();
+
+   while(bits--)
+      {
+#if 1
+      const word odd = a.is_odd();
+      a -= odd * b;
+      const word underflow = a.is_negative();
+      b += a * underflow;
+      a.set_sign(BigInt::Positive);
+
+      a >>= 1;
+
+      if(underflow)
+         {
+         std::swap(u, v);
+         }
+
+      u -= odd * v;
+      u += u.is_negative() * mod;
+
+      const word odd_u = u.is_odd();
+
+      u >>= 1;
+      u += mp1o2 * odd_u;
+#else
+      const word odd_a = a_w[0] & 1;
+
+      //if(odd_a) a -= b
+      word underflow = bigint_cnd_sub(odd_a, a_w.begin(), b_w.begin(), mod_words);
+
+      //if(underflow) { b -= a; a = abs(a); swap(u, v); }
+      bigint_cnd_add(underflow, b_w.begin(), a_w.begin(), mod_words);
+      bigint_cnd_abs(underflow, a_w.begin(), mod_words);
+      bigint_cnd_swap(underflow, u_w.begin(), v_w.begin(), mod_words);
+
+      // a >>= 1
+      bigint_shr1(a_w.begin(), mod_words, 0, 1);
+
+      //if(odd_a) u -= v;
+      word borrow = bigint_cnd_sub(odd_a, u_w.begin(), v_w.begin(), mod_words);
+
+      // if(borrow) u += p
+      bigint_cnd_add(borrow, u_w.begin(), mod.data(), mod_words);
+
+      const word odd_u = u_w[0] & 1;
+
+      // u >>= 1
+      bigint_shr1(u_w.begin(), mod_words, 0, 1);
+
+      //if(odd_u) u += mp1o2;
+      bigint_cnd_add(odd_u, u_w.begin(), mp1o2.data(), mod_words);
+#endif
+      }
+
+   if(b != 1)
+      return 0;
+
+   return v;
+   }
+
+}
+
 /*
 * Find the Modular Inverse
 */
@@ -209,6 +321,9 @@ BigInt inverse_mod(const BigInt& n, const BigInt& mod)
    if(n.is_zero() || (n.is_even() && mod.is_even()))
       return 0;
 
+   if(mod.is_odd())
+      return ct_inverse_mod_odd_modulus(n % mod, mod);
+
    BigInt x = mod, y = n, u = mod, v = n;
    BigInt A = 1, B = 0, C = 0, D = 1;
 
diff --git a/src/pk_pad/eme_pkcs/eme_pkcs.cpp b/src/pk_pad/eme_pkcs/eme_pkcs.cpp
index c4d6838b1..7f0393ed8 100644
--- a/src/pk_pad/eme_pkcs/eme_pkcs.cpp
+++ b/src/pk_pad/eme_pkcs/eme_pkcs.cpp
@@ -6,6 +6,7 @@
 */
 
 #include <botan/eme_pkcs.h>
+#include <botan/internal/ct_utils.h>
 
 namespace Botan {
 
@@ -40,20 +41,31 @@ SecureVector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
 SecureVector<byte> EME_PKCS1v15::unpad(const byte in[], size_t inlen,
                                        size_t key_len) const
    {
-   if(inlen != key_len / 8 || inlen < 10 || in[0] != 0x02)
-      throw Decoding_Error("PKCS1::unpad");
-
-   size_t seperator = 0;
-   for(size_t j = 0; j != inlen; ++j)
-      if(in[j] == 0)
-         {
-         seperator = j;
-         break;
-         }
-   if(seperator < 9)
-      throw Decoding_Error("PKCS1::unpad");
-
-   return SecureVector<byte>(in + seperator + 1, inlen - seperator - 1);
+
+   byte bad_input_m = 0;
+   byte seen_zero_m = 0;
+   size_t delim_idx = 0;
+
+   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<byte>(in[i]);
+
+      delim_idx += CT::select<byte>(~seen_zero_m, 1, 0);
+
+      bad_input_m |= is_zero_m & CT::expand_mask<byte>(i < 9);
+      seen_zero_m |= is_zero_m;
+      }
+
+   bad_input_m |= ~seen_zero_m;
+   bad_input_m |= CT::is_less<size_t>(delim_idx, 8);
+
+   SecureVector<byte> output(&in[delim_idx + 1], inlen - (delim_idx + 1));
+
+   if(bad_input_m)
+      throw Decoding_Error("EME_PKCS1v15::unpad invalid ciphertext");
+   return output;
    }
 
 /*
diff --git a/src/utils/ct_utils.h b/src/utils/ct_utils.h
new file mode 100644
index 000000000..0eab90636
--- /dev/null
+++ b/src/utils/ct_utils.h
@@ -0,0 +1,137 @@
+/*
+* Functions for constant time operations on data and testing of
+* constant time annotations using valgrind.
+*
+* For more information about constant time programming see
+* Wagner, Molnar, et al "The Program Counter Security Model"
+*
+* (C) 2010 Falko Strenzke
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_TIMING_ATTACK_CM_H__
+#define BOTAN_TIMING_ATTACK_CM_H__
+
+#include <botan/secmem.h>
+#include <vector>
+
+namespace Botan {
+
+namespace CT {
+
+/*
+* T should be an unsigned machine integer type
+* Expand to a mask used for other operations
+* @param in an integer
+* @return If n is zero, returns zero. Otherwise
+* returns a T with all bits set for use as a mask with
+* select.
+*/
+template<typename T>
+inline T expand_mask(T x)
+   {
+   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;
+   r = ~(r - 1);
+   return r;
+   }
+
+template<typename T>
+inline T select(T mask, T from0, T from1)
+   {
+   return (from0 & mask) | (from1 & ~mask);
+   }
+
+template<typename PredT, typename ValT>
+inline ValT val_or_zero(PredT pred_val, ValT val)
+   {
+   return select(CT::expand_mask<ValT>(pred_val), val, static_cast<ValT>(0));
+   }
+
+template<typename T>
+inline T is_zero(T x)
+   {
+   return ~expand_mask(x);
+   }
+
+template<typename T>
+inline T is_equal(T x, T y)
+   {
+   return is_zero(x ^ y);
+   }
+
+template<typename T>
+inline T is_less(T x, T y)
+   {
+   /*
+   This expands to a constant time sequence with GCC 5.2.0 on x86-64
+   but something more complicated may be needed for portable const time.
+   */
+   return expand_mask<T>(x < y);
+   }
+
+template<typename T>
+inline T is_lte(T x, T y)
+   {
+   return expand_mask<T>(x <= y);
+   }
+
+template<typename T>
+inline void conditional_copy_mem(T value,
+                                 T* to,
+                                 const T* from0,
+                                 const T* from1,
+                                 size_t elems)
+   {
+   const T mask = CT::expand_mask(value);
+
+   for(size_t i = 0; i != elems; ++i)
+      {
+      to[i] = CT::select(mask, from0[i], from1[i]);
+      }
+   }
+
+template<typename T>
+inline void cond_zero_mem(T cond,
+                          T* array,
+                          size_t elems)
+   {
+   const T mask = CT::expand_mask(cond);
+   const T zero(0);
+
+   for(size_t i = 0; i != elems; ++i)
+      {
+      array[i] = CT::select(mask, zero, array[i]);
+      }
+   }
+
+template<typename T>
+inline T expand_top_bit(T a)
+   {
+   return expand_mask<T>(a >> (sizeof(T)*8-1));
+   }
+
+template<typename T>
+inline T max(T a, T b)
+   {
+   const T a_larger = b - a; // negative if a is larger
+   return select(expand_top_bit(a), a, b);
+   }
+
+template<typename T>
+inline T min(T a, T b)
+   {
+   const T a_larger = b - a; // negative if a is larger
+   return select(expand_top_bit(b), b, a);
+   }
+
+}
+
+}
+
+#endif
diff --git a/src/utils/info.txt b/src/utils/info.txt
index fcf16bd5a..57b6a2740 100644
--- a/src/utils/info.txt
+++ b/src/utils/info.txt
@@ -16,6 +16,7 @@ version.cpp
 <header:internal>
 assert.h
 bit_ops.h
+ct_utils.h
 mlock.h
 prefetch.h
 rounding.h
