Add PWCT for RSA and ECDSA for FIPS 140-2.

Since only the consumers knows whether an EC key will be used for
ECDSA or ECDHE, it is part of the FIPS policy for the consumer to
check the validity of the generated key before signing with it.

Change-Id: Ie250f655c8fcb6a59cc7210def1e87eb958e9349
Reviewed-on: https://boringssl-review.googlesource.com/14745
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index 82783a9..702068f 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -70,6 +70,7 @@
 #include <string.h>
 
 #include <openssl/ec.h>
+#include <openssl/ecdsa.h>
 #include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/ex_data.h>
@@ -345,6 +346,26 @@
   return ok;
 }
 
+int EC_KEY_check_fips(const EC_KEY *key) {
+  uint8_t data[16] = {0};
+  unsigned sig_len = ECDSA_size(key);
+  uint8_t *sig = OPENSSL_malloc(sig_len);
+  if (sig == NULL) {
+    OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  int ret = 1;
+  if (!ECDSA_sign(0, data, sizeof(data), sig, &sig_len, key) ||
+      !ECDSA_verify(0, data, sizeof(data), sig, sig_len, key)) {
+    OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
+    ret = 0;
+  }
+
+  OPENSSL_free(sig);
+  return ret;
+}
+
 int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
                                              BIGNUM *y) {
   BN_CTX *ctx = NULL;
diff --git a/crypto/ec/ec_test.cc b/crypto/ec/ec_test.cc
index 02b9ef2..2bc87aa 100644
--- a/crypto/ec/ec_test.cc
+++ b/crypto/ec/ec_test.cc
@@ -314,6 +314,15 @@
                                                    x.get(), y.get(), nullptr));
 }
 
+TEST_P(ECCurveTest, CheckFIPS) {
+  // Generate an EC_KEY.
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
+
+  EXPECT_TRUE(EC_KEY_check_fips(key.get()));
+}
+
 TEST_P(ECCurveTest, AddingEqualPoints) {
   bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
   ASSERT_TRUE(key);
diff --git a/crypto/rsa/rsa.c b/crypto/rsa/rsa.c
index b16d55c..0556bdb 100644
--- a/crypto/rsa/rsa.c
+++ b/crypto/rsa/rsa.c
@@ -644,7 +644,7 @@
 };
 static const BIGNUM kSmallFactors = STATIC_BIGNUM(kSmallFactorsLimbs);
 
-int RSA_check_fips(const RSA *key) {
+int RSA_check_fips(RSA *key) {
   if (RSA_is_opaque(key)) {
     /* Opaque keys can't be checked. */
     OPENSSL_PUT_ERROR(RSA, RSA_R_PUBLIC_KEY_VALIDATION_FAILED);
@@ -682,6 +682,30 @@
   BN_free(&small_gcd);
   BN_CTX_free(ctx);
 
+  if (!ret) {
+    return ret;
+  }
+
+  /* FIPS pairwise consistency test (FIPS 140-2 4.9.2). Per FIPS 140-2 IG,
+   * section 9.9, it is not known whether |rsa| will be used for signing or
+   * encryption, so either pair-wise consistency self-test is acceptable. We
+   * perform a signing test. */
+  uint8_t data[32] = {0};
+  unsigned sig_len = RSA_size(key);
+  uint8_t *sig = OPENSSL_malloc(sig_len);
+  if (sig == NULL) {
+    OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  if (!RSA_sign(NID_sha256, data, sizeof(data), sig, &sig_len, key) ||
+      !RSA_verify(NID_sha256, data, sizeof(data), sig, sig_len, key)) {
+    OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
+    ret = 0;
+  }
+
+  OPENSSL_free(sig);
+
   return ret;
 }
 
diff --git a/crypto/rsa/rsa_test.cc b/crypto/rsa/rsa_test.cc
index cd1ff6d..e7ed795 100644
--- a/crypto/rsa/rsa_test.cc
+++ b/crypto/rsa/rsa_test.cc
@@ -98,6 +98,43 @@
     "\x9d\xa8\xe9\x0b\x1d\x34\x1f\x71\xd0\x9b\x76\xa8\xa9\x43\xe1\x1d\x10\xb2"
     "\x4d\x24\x9f\x2d\xea\xfe\xf8\x0c\x18\x26";
 
+// kFIPSKey is a DER-encoded RSAPrivateKey that is FIPS-compliant.
+static const uint8_t kFIPSKey[] =
+    "\x30\x82\x02\x5c\x02\x01\x00\x02\x81\x81\x00\xa1\x71\x90\x77\x86\x8a\xc7"
+    "\xb8\xfc\x2a\x45\x82\x6d\xee\xeb\x35\x3a\x18\x3f\xb6\xb0\x1e\xb1\xd3\x09"
+    "\x6b\x05\x4d\xec\x1c\x37\x6f\x09\x31\x32\xda\x21\x8a\x49\x0e\x16\x28\xed"
+    "\x9a\x30\xf3\x14\x53\xfd\x5b\xb0\xf6\x4a\x5d\x52\xe1\xda\xe1\x40\x6e\x65"
+    "\xbf\xca\x45\xd9\x62\x96\x4a\x1e\x11\xc4\x61\x83\x1f\x58\x8d\x5e\xd0\x12"
+    "\xaf\xa5\xec\x9b\x97\x2f\x6c\xb2\x82\x4a\x73\xd0\xd3\x9a\xc9\x69\x6b\x24"
+    "\x3c\x82\x6f\xee\x4d\x0c\x7e\xdf\xd7\xae\xea\x3a\xeb\x04\x27\x8d\x43\x81"
+    "\x59\xa7\x90\x56\xc1\x69\x42\xb3\xaf\x1c\x8d\x4e\xbf\x02\x03\x01\x00\x01"
+    "\x02\x81\x80\x60\x82\xcd\x44\x46\xcf\xeb\xf9\x6f\xf5\xad\x3b\xfd\x90\x18"
+    "\x57\xe7\x74\xdb\x91\xd0\xd3\x68\xa6\xaa\x38\xaa\x21\x1d\x06\xf9\x34\x8d"
+    "\xa0\x35\xb0\x24\xe0\xd0\x2f\x75\x9b\xdd\xfe\x91\x48\x9f\x5c\x5e\x57\x54"
+    "\x00\xc8\x0f\xe6\x1e\x52\x84\xd9\xc9\xa5\x55\xf4\x0a\xbe\x88\x46\x7a\xfb"
+    "\x18\x37\x8e\xe6\x6e\xa2\x5f\x80\x48\x34\x3f\x5c\xbe\x0e\x1e\xe8\x2f\x50"
+    "\xba\x14\x96\x3c\xea\xfb\xd2\x49\x33\xdc\x12\xb8\xa7\x8a\xb5\x27\xf9\x00"
+    "\x4b\xf5\xd2\x2a\xd0\x2c\x1d\x9b\xd5\x6c\x3e\x4b\xb9\x7e\x39\xf7\x3e\x39"
+    "\xc9\x47\x5e\xbe\x91\x02\x41\x00\xcd\x33\xcf\x37\x01\xd7\x59\xcc\xbe\xa0"
+    "\x1c\xb9\xf5\xe7\x44\x9f\x62\x91\xa7\xa7\x7b\x0c\x52\xcd\x7e\xe6\x31\x11"
+    "\x8b\xd8\x2c\x8a\x63\xe1\x07\xc9\xcb\xce\x01\x45\x63\xf5\x5d\x44\xfb\xeb"
+    "\x8d\x74\x16\x20\x7d\x3b\xb4\xa1\x61\xb0\xa8\x29\x51\xc9\xef\xb6\xa1\xd5"
+    "\x02\x41\x00\xc9\x68\xa6\xd3\x88\xd5\x49\x9d\x6b\x44\x96\xfd\xbf\x66\x27"
+    "\xb4\x1f\x90\x76\x86\x2f\xe2\xce\x20\x5d\xee\x9b\xeb\xc4\xb4\x62\x47\x79"
+    "\x99\xb1\x99\xbc\xa2\xa6\xb6\x96\x64\xd5\x77\x9b\x45\xd4\xf0\x99\xb5\x9e"
+    "\x61\x4d\xf5\x12\xdd\x84\x14\xaf\x1e\xdd\x83\x24\x43\x02\x40\x60\x29\x7f"
+    "\x59\xcf\xcb\x13\x92\x17\x63\x01\x13\x44\x61\x74\x8f\x1c\xaa\x15\x5f\x2f"
+    "\x12\xbf\x5a\xfd\xb4\xf2\x19\xbe\xe7\x37\x38\x43\x46\x19\x58\x3f\xe1\xf2"
+    "\x46\x8a\x69\x59\xa4\x12\x4a\x78\xa7\x86\x17\x03\x99\x0f\x34\xf1\x8a\xcf"
+    "\xc3\x4d\x48\xcc\xc5\x51\x61\x02\x41\x00\xc2\x12\xb3\x5d\xf5\xe5\xff\xcf"
+    "\x4e\x43\x83\x72\xf2\xf1\x4e\xa4\xc4\x1d\x81\xf7\xff\x40\x7e\xfa\xb5\x48"
+    "\x6c\xba\x1c\x8a\xec\x80\x8e\xed\xc8\x32\xa9\x8f\xd9\x30\xeb\x6e\x32\x3b"
+    "\xd4\x44\xcf\xd1\x1f\x6b\xe0\x37\x46\xd5\x35\xde\x79\x9d\x2c\xb9\x83\x1d"
+    "\x10\xdd\x02\x40\x0f\x14\x95\x96\xa0\xe2\x6c\xd4\x88\xa7\x0b\x82\x14\x10"
+    "\xad\x26\x0d\xe4\xa1\x5e\x01\x3d\x21\xd2\xfb\x0e\xf9\x58\xa5\xca\x1e\x21"
+    "\xb3\xf5\x9a\x6c\x3d\x5a\x72\xb1\x2d\xfe\xac\x09\x4f\xdd\xe5\x44\xd1\x4e"
+    "\xf8\x59\x85\x3a\x65\xe2\xcd\xbc\x27\x1d\x9b\x48\x9f\xb9";
+
 // kOAEPCiphertext1 is a sample encryption of |kPlaintext| with |kKey1| using
 // RSA OAEP.
 static const uint8_t kOAEPCiphertext1[] =
@@ -426,6 +463,15 @@
   EXPECT_EQ(Bytes("hello world"), Bytes(out, out_len));
 }
 
+TEST(RSATest, CheckFIPS) {
+  bssl::UniquePtr<RSA> rsa(
+      RSA_private_key_from_bytes(kFIPSKey, sizeof(kFIPSKey) - 1));
+  ASSERT_TRUE(rsa);
+
+  EXPECT_TRUE(RSA_check_key(rsa.get()));
+  EXPECT_TRUE(RSA_check_fips(rsa.get()));
+}
+
 TEST(RSATest, BadKey) {
   bssl::UniquePtr<RSA> key(RSA_new());
   bssl::UniquePtr<BIGNUM> e(BN_new());
diff --git a/include/openssl/ec_key.h b/include/openssl/ec_key.h
index 1dbae62..cb7ef10 100644
--- a/include/openssl/ec_key.h
+++ b/include/openssl/ec_key.h
@@ -159,6 +159,10 @@
  * about the problem can be found on the error stack. */
 OPENSSL_EXPORT int EC_KEY_check_key(const EC_KEY *key);
 
+/* EC_KEY_check_fips performs a signing pairwise consistency test (FIPS 140-2
+ * 4.9.2). It returns one if it passes and zero otherwise. */
+OPENSSL_EXPORT int EC_KEY_check_fips(const EC_KEY *key);
+
 /* EC_KEY_set_public_key_affine_coordinates sets the public key in |key| to
  * (|x|, |y|). It returns one on success and zero otherwise. */
 OPENSSL_EXPORT int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key,
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 7f5e4c5..ee1bdde 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -292,14 +292,14 @@
  * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */
 OPENSSL_EXPORT RSA *RSAPrivateKey_dup(const RSA *rsa);
 
-/* RSA_check_key performs basic validatity tests on |rsa|. It returns one if
+/* RSA_check_key performs basic validity tests on |rsa|. It returns one if
  * they pass and zero otherwise. Opaque keys and public keys always pass. If it
  * returns zero then a more detailed error is available on the error queue. */
 OPENSSL_EXPORT int RSA_check_key(const RSA *rsa);
 
-/* RSA_check_fips performs public key validatity tests on |key|. It returns one
+/* RSA_check_fips performs public key validity tests on |key|. It returns one
  * if they pass and zero otherwise. Opaque keys always fail. */
-OPENSSL_EXPORT int RSA_check_fips(const RSA *key);
+OPENSSL_EXPORT int RSA_check_fips(RSA *key);
 
 /* RSA_recover_crt_params uses |rsa->n|, |rsa->d| and |rsa->e| in order to
  * calculate the two primes used and thus the precomputed, CRT values. These