Explicitly guarantee BN_MONT_CTX::{RR,N} have the same width.

This is so the *_small functions can assume somewhat more uniform
widths, to simplify their error-handling.

Change-Id: I0420cb237084b253e918c64b0c170a5dfd99ab40
Reviewed-on: https://boringssl-review.googlesource.com/27584
Reviewed-by: Adam Langley <alangley@gmail.com>
diff --git a/crypto/fipsmodule/bn/bn_test.cc b/crypto/fipsmodule/bn/bn_test.cc
index 6230be1..5d7c8ce 100644
--- a/crypto/fipsmodule/bn/bn_test.cc
+++ b/crypto/fipsmodule/bn/bn_test.cc
@@ -2279,11 +2279,12 @@
   EXPECT_TRUE(BN_is_pow2(eight.get()));
 
   // |BN_MONT_CTX| is always stored minimally and uses the same R independent of
-  // input width.
+  // input width. Additionally, mont->RR is always the same width as mont->N,
+  // even if it fits in a smaller value.
   static const uint8_t kP[] = {
-      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
-      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
   };
   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
   ASSERT_TRUE(p);
@@ -2311,6 +2312,10 @@
   EXPECT_EQ(0, BN_cmp(&mont->RR, &mont2->RR));
   EXPECT_EQ(0, BN_cmp(&mont->RR, &mont3->RR));
   EXPECT_EQ(0, BN_cmp(&mont->RR, &mont4->RR));
+  EXPECT_EQ(mont->N.width, mont->RR.width);
+  EXPECT_EQ(mont->N.width, mont2->RR.width);
+  EXPECT_EQ(mont->N.width, mont3->RR.width);
+  EXPECT_EQ(mont->N.width, mont4->RR.width);
 }
 
 TEST_F(BNTest, CountLowZeroBits) {
diff --git a/crypto/fipsmodule/bn/montgomery.c b/crypto/fipsmodule/bn/montgomery.c
index 9e7cbc4..67e3f52 100644
--- a/crypto/fipsmodule/bn/montgomery.c
+++ b/crypto/fipsmodule/bn/montgomery.c
@@ -232,7 +232,8 @@
   unsigned lgBigR = mont->N.width * BN_BITS2;
   BN_zero(&mont->RR);
   int ok = BN_set_bit(&mont->RR, lgBigR * 2) &&
-           BN_mod(&mont->RR, &mont->RR, &mont->N, ctx);
+           BN_mod(&mont->RR, &mont->RR, &mont->N, ctx) &&
+           bn_resize_words(&mont->RR, mont->N.width);
   BN_CTX_free(new_ctx);
   return ok;
 }
@@ -254,7 +255,8 @@
     goto err;
   }
   unsigned lgBigR = mont->N.width * BN_BITS2;
-  if (!bn_mod_exp_base_2_consttime(&mont->RR, lgBigR * 2, &mont->N, ctx)) {
+  if (!bn_mod_exp_base_2_consttime(&mont->RR, lgBigR * 2, &mont->N, ctx) ||
+      !bn_resize_words(&mont->RR, mont->N.width)) {
     goto err;
   }
   return mont;
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index b0f8a2d..90b4b36 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -957,9 +957,10 @@
 };
 
 struct bn_mont_ctx_st {
-  // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form.
+  // RR is R^2, reduced modulo |N|. It is used to convert to Montgomery form. It
+  // is guaranteed to have the same width as |N|.
   BIGNUM RR;
-  // N is the modulus. It is always stored in minimal form, so |N.top|
+  // N is the modulus. It is always stored in minimal form, so |N.width|
   // determines R.
   BIGNUM N;
   BN_ULONG n0[2];  // least significant words of (R*Ri-1)/N