Be strict about requiring ServerKeyExchange.

Missing ServerKeyExchange is handled, but only because it hits an
ERR_R_INTERNAL_ERROR in ssl3_send_client_key_exchange in trying to find the
server ECDH parameters. Be strict about requiring it for ECDHE.

Change-Id: Ifce5b73c8bd14746b8a2185f479d550e9e3f84df
Reviewed-on: https://boringssl-review.googlesource.com/1157
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 4c4bb67..28287a2 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1883,3 +1883,28 @@
 	/* All other ciphers include it. */
 	return 1;
 	}
+
+/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher|
+ * requires a ServerKeyExchange message. Otherwise it returns 0.
+ *
+ * Unlike ssl_cipher_has_server_public_key, some ciphers take optional
+ * ServerKeyExchanges. PSK and RSA_PSK only use the ServerKeyExchange
+ * to communicate a psk_identity_hint, so it is optional.
+ *
+ * Also, as implemented, the RSA key exchange takes an optional
+ * ServerKeyExchange containing a signed ephemeral RSA encryption key.
+ *
+ * TODO(davidben): Can we remove the RSA one? This is a remnant of
+ * RSA_EXPORT ciphers which required this (it was used to generate an
+ * ephemeral 512-bit RSA encryption key), but it's allowed for all RSA
+ * ciphers. There's even a SSL_OP_EPHEMERAL_RSA to always use it. */
+int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher)
+	{
+	/* Ephemeral Diffie-Hellman key exchanges require a
+	 * ServerKeyExchange. */
+	if (cipher->algorithm_mkey & SSL_kEDH ||
+		cipher->algorithm_mkey & SSL_kEECDH)
+		return 1;
+	/* It is optional in all others. */
+	return 0;
+	}