Add another bn modexp test.

Add a test based on multiplication optimizations from OpenSSL HEAD
(1.1.0-dev) Based on openssl-SNAP-20111003
diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
index 16ce65f..79b918a 100644
--- a/crypto/bn/bn.h
+++ b/crypto/bn/bn.h
@@ -709,9 +709,6 @@
 int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1,
                      const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
                      BN_CTX *ctx, BN_MONT_CTX *m_ctx);
-int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                      const BIGNUM *m, BN_CTX *ctx);
-
 
 
 /* Private functions */
diff --git a/crypto/bn/bn_test.c b/crypto/bn/bn_test.c
index 1a89802..c29aec8 100644
--- a/crypto/bn/bn_test.c
+++ b/crypto/bn/bn_test.c
@@ -98,6 +98,7 @@
 int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
 int test_exp(BIO *bp, BN_CTX *ctx);
 int test_mod_sqrt(BIO *bp, BN_CTX *ctx);
+int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
 #if 0
 int test_gf2m_add(BIO *bp);
 int test_gf2m_mod(BIO *bp);
@@ -243,8 +244,10 @@
   (void)BIO_flush(out);
 
   message(out, "BN_mod_exp_mont_consttime");
-  if (!test_mod_exp_mont_consttime(out, ctx))
+  if (!test_mod_exp_mont_consttime(out, ctx) ||
+      !test_mod_exp_mont5(out, ctx)) {
     goto err;
+  }
   (void)BIO_flush(out);
 
   message(out, "BN_exp");
@@ -1000,6 +1003,75 @@
   return (1);
 }
 
+/* Test constant-time modular exponentiation with 1024-bit inputs,
+ * which on x86_64 cause a different code branch to be taken. */
+int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx) {
+  BIGNUM *a, *p, *m, *d, *e;
+
+  BN_MONT_CTX *mont;
+
+  a = BN_new();
+  p = BN_new();
+  m = BN_new();
+  d = BN_new();
+  e = BN_new();
+
+  mont = BN_MONT_CTX_new();
+
+  BN_rand(m, 1024, 0, 1); /* must be odd for montgomery */
+  /* Zero exponent */
+  BN_rand(a, 1024, 0, 0);
+  BN_zero(p);
+  if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
+    return 0;
+  if (!BN_is_one(d)) {
+    fprintf(stderr, "Modular exponentiation test failed!\n");
+    return 0;
+  }
+  /* Zero input */
+  BN_rand(p, 1024, 0, 0);
+  BN_zero(a);
+  if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
+    return 0;
+  if (!BN_is_zero(d)) {
+    fprintf(stderr, "Modular exponentiation test failed!\n");
+    return 0;
+  }
+  /* Craft an input whose Montgomery representation is 1,
+   * i.e., shorter than the modulus m, in order to test
+   * the const time precomputation scattering/gathering.
+   */
+  BN_one(a);
+  BN_MONT_CTX_set(mont, m, ctx);
+  if (!BN_from_montgomery(e, a, mont, ctx) ||
+      !BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL) ||
+      !BN_mod_exp(a, e, p, m, ctx)) {
+    return 0;
+  }
+  if (BN_cmp(a, d) != 0) {
+    fprintf(stderr, "Modular exponentiation test failed!\n");
+    return 0;
+  }
+  /* Finally, some regular test vectors. */
+  BN_rand(e, 1024, 0, 0);
+  if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
+    return 0;
+  if (!BN_mod_exp(a, e, p, m, ctx))
+    return 0;
+  if (BN_cmp(a, d) != 0) {
+    fprintf(stderr, "Modular exponentiation test failed!\n");
+    return 0;
+  }
+
+  BN_MONT_CTX_free(mont);
+  BN_free(a);
+  BN_free(p);
+  BN_free(m);
+  BN_free(d);
+  BN_free(e);
+  return (1);
+}
+
 int test_exp(BIO *bp, BN_CTX *ctx) {
   BIGNUM *a, *b, *d, *e, *one;
   int i;