Allow |RSA_FLAG_NO_BLINDING| to be set with |e| set.

This change allows blinding to be disabled without also having to remove
|e|, which would disable the CRT and the glitch checks. This is to
support disabling blinding in the FIPS power-on tests.

(Note: the case where |e| isn't set is tested by RSATest.OnlyDGiven.)

Change-Id: I28f18beda33b1687bf145f4cbdfd37ce262dd70f
Reviewed-on: https://boringssl-review.googlesource.com/17146
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/rsa/rsa_impl.c b/crypto/fipsmodule/rsa/rsa_impl.c
index e09a37c..342f1c2 100644
--- a/crypto/fipsmodule/rsa/rsa_impl.c
+++ b/crypto/fipsmodule/rsa/rsa_impl.c
@@ -567,20 +567,18 @@
     goto err;
   }
 
-  /* We cannot do blinding or verification without |e|, and continuing without
-   * those countermeasures is dangerous. However, the Java/Android RSA API
-   * requires support for keys where only |d| and |n| (and not |e|) are known.
-   * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */
-  int disable_security = (rsa->flags & RSA_FLAG_NO_BLINDING) && rsa->e == NULL;
+  const int do_blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
 
-  if (!disable_security) {
-    /* Keys without public exponents must have blinding explicitly disabled to
-     * be used. */
-    if (rsa->e == NULL) {
-      OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
-      goto err;
-    }
+  if (rsa->e == NULL && do_blinding) {
+    /* We cannot do blinding or verification without |e|, and continuing without
+     * those countermeasures is dangerous. However, the Java/Android RSA API
+     * requires support for keys where only |d| and |n| (and not |e|) are known.
+     * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */
+    OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
+    goto err;
+  }
 
+  if (do_blinding) {
     blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
     if (blinding == NULL) {
       OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
@@ -610,7 +608,7 @@
    * than the CRT attack, but there have likely been improvements since 1997.
    *
    * This check is cheap assuming |e| is small; it almost always is. */
-  if (!disable_security) {
+  if (rsa->e != NULL) {
     BIGNUM *vrfy = BN_CTX_get(ctx);
     if (vrfy == NULL ||
         !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) ||
@@ -619,9 +617,11 @@
       goto err;
     }
 
-    if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
-      goto err;
-    }
+  }
+
+  if (do_blinding &&
+      !BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
+    goto err;
   }
 
   if (!BN_bn2bin_padded(out, len, result)) {
diff --git a/crypto/rsa_extra/rsa_test.cc b/crypto/rsa_extra/rsa_test.cc
index a53d04d..162ac05 100644
--- a/crypto/rsa_extra/rsa_test.cc
+++ b/crypto/rsa_extra/rsa_test.cc
@@ -679,6 +679,24 @@
   EXPECT_EQ(1152u, BN_num_bits(rsa->n));
 }
 
+TEST(RSATest, BlindingDisabled) {
+  bssl::UniquePtr<RSA> rsa(
+      RSA_private_key_from_bytes(kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1));
+  ASSERT_TRUE(rsa);
+
+  rsa->flags |= RSA_FLAG_NO_BLINDING;
+
+  uint8_t sig[256];
+  ASSERT_GE(sizeof(sig), RSA_size(rsa.get()));
+
+  static const uint8_t kZeros[32] = {0};
+  unsigned sig_len;
+  ASSERT_TRUE(
+      RSA_sign(NID_sha256, kZeros, sizeof(kZeros), sig, &sig_len, rsa.get()));
+  EXPECT_TRUE(
+      RSA_verify(NID_sha256, kZeros, sizeof(kZeros), sig, sig_len, rsa.get()));
+}
+
 #if !defined(BORINGSSL_SHARED_LIBRARY)
 TEST(RSATest, SqrtTwo) {
   bssl::UniquePtr<BIGNUM> sqrt(BN_new()), pow2(BN_new());