Support and test P-224 certificates.

Previously we only needed to be able to serve P-224 certificates, but
now we anticipate a need to be able to connect and validate them also.
Since this requires advertising support for P-224 in the handshake, we
need to support P-224 ECDHE too.

P-224 support is disabled by default and so clients need to both set the
enabled curves explicitly and set a maximum version of TLS 1.2.

Change-Id: Idc69580f47334e0912eb431a0db0e78ee2eb5bbe
Reviewed-on: https://boringssl-review.googlesource.com/14225
Reviewed-by: Adam Langley <alangley@gmail.com>
Commit-Queue: Adam Langley <alangley@gmail.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 5182df7..b476592 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2105,6 +2105,7 @@
 OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
 
 /* SSL_CURVE_* define TLS curve IDs. */
+#define SSL_CURVE_SECP224R1 21
 #define SSL_CURVE_SECP256R1 23
 #define SSL_CURVE_SECP384R1 24
 #define SSL_CURVE_SECP521R1 25
diff --git a/ssl/ssl_ecdh.c b/ssl/ssl_ecdh.c
index f49d566..25e3df9 100644
--- a/ssl/ssl_ecdh.c
+++ b/ssl/ssl_ecdh.c
@@ -300,6 +300,17 @@
 
 static const SSL_ECDH_METHOD kMethods[] = {
     {
+        NID_secp224r1,
+        SSL_CURVE_SECP224R1,
+        "P-224",
+        ssl_ec_point_cleanup,
+        ssl_ec_point_offer,
+        ssl_ec_point_accept,
+        ssl_ec_point_finish,
+        CBS_get_u8_length_prefixed,
+        CBB_add_u8_length_prefixed,
+    },
+    {
         NID_X9_62_prime256v1,
         SSL_CURVE_SECP256R1,
         "P-256",
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index dccf0c9..70ea664 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -1793,7 +1793,8 @@
   }
   if (config->enable_all_curves) {
     static const int kAllCurves[] = {
-      NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519,
+        NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1,
+        NID_secp521r1, NID_X25519,
     };
     if (!SSL_set1_curves(ssl.get(), kAllCurves,
                          OPENSSL_ARRAY_SIZE(kAllCurves))) {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 3bdb865..a6d08ef 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -6662,6 +6662,10 @@
 	{"RSA-PKCS1-SHA384", signatureRSAPKCS1WithSHA384, testCertRSA},
 	{"RSA-PKCS1-SHA512", signatureRSAPKCS1WithSHA512, testCertRSA},
 	{"ECDSA-SHA1", signatureECDSAWithSHA1, testCertECDSAP256},
+	// The “P256” in the following line is not a mistake. In TLS 1.2 the
+	// hash function doesn't have to match the curve and so the same
+	// signature algorithm works with P-224.
+	{"ECDSA-P224-SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP224},
 	{"ECDSA-P256-SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256},
 	{"ECDSA-P384-SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384},
 	{"ECDSA-P521-SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521},
@@ -6718,7 +6722,13 @@
 				shouldVerifyFail = true
 			}
 			// RSA-PKCS1 does not exist in TLS 1.3.
-			if ver.version == VersionTLS13 && hasComponent(alg.name, "PKCS1") {
+			if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") {
+				shouldSignFail = true
+				shouldVerifyFail = true
+			}
+			// SHA-224 has been removed from TLS 1.3 and, in 1.3,
+			// the curve has to match the hash size.
+			if ver.version >= VersionTLS13 && alg.cert == testCertECDSAP224 {
 				shouldSignFail = true
 				shouldVerifyFail = true
 			}
@@ -7486,31 +7496,6 @@
 		},
 		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
 	})
-
-	// A server certificate with a P-224 key will only work up to TLS 1.2
-	// and we only test it with BoringSSL acting as a server because that's
-	// all Alphabet requires with it.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "P224-Server",
-		config: Config{
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				// TLS 1.2 does not require that the curve
-				// match the hash, thus P-256 with SHA-256 is
-				// the same signature algorithm value as P-224
-				// with SHA-256.
-				signatureECDSAWithP256AndSHA256,
-			},
-			// P-256 must be offered as well because ECDHE requires
-			// it.
-			CurvePreferences: []CurveID{CurveP224, CurveP256},
-		},
-		flags: []string{
-			"-max-version", strconv.Itoa(VersionTLS12),
-			"-cert-file", path.Join(*resourceDir, ecdsaP224CertificateFile),
-			"-key-file", path.Join(*resourceDir, ecdsaP224KeyFile),
-		},
-	})
 }
 
 // timeouts is the retransmit schedule for BoringSSL. It doubles and
@@ -8146,6 +8131,7 @@
 	name string
 	id   CurveID
 }{
+	{"P-224", CurveP224},
 	{"P-256", CurveP256},
 	{"P-384", CurveP384},
 	{"P-521", CurveP521},