Suite B support for DTLS 1.2

Check for Suite B support using method flags instead of version numbers:
anything supporting TLS 1.2 cipher suites will also support Suite B.

Return an error if an attempt to use DTLS 1.0 is made in Suite B mode.
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 27f31b6..c628db5 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -667,7 +667,7 @@
 				 */
 				if (!s->s3->handshake_buffer)
 					{
-					SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR);
+					SSLerr(SSL_F_DTLS1_ACCEPT,ERR_R_INTERNAL_ERROR);
 					return -1;
 					}
 				s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 44ff247..018a9f5 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -701,6 +701,11 @@
 			/* If DTLS 1.2 disabled correct the version number */
 			if (options & SSL_OP_NO_DTLSv1_2)
 				{
+				if (tls1_suiteb(s))
+					{
+					SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+					goto err;
+					}
 				/* Disabling all versions is silly: return an
 				 * error.
 				 */
@@ -954,11 +959,23 @@
 		if (hversion == DTLS1_2_VERSION
 			&& !(options & SSL_OP_NO_DTLSv1_2))
 			s->method = DTLSv1_2_client_method();
+		else if (tls1_suiteb(s))
+			{
+			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+			s->version = hversion;
+			al = SSL_AD_PROTOCOL_VERSION;
+			goto f_err;
+			}
 		else if (hversion == DTLS1_VERSION
 			&& !(options & SSL_OP_NO_DTLSv1))
 			s->method = DTLSv1_client_method();
 		else
+			{
 			SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
+			s->version = hversion;
+			al = SSL_AD_PROTOCOL_VERSION;
+			goto f_err;
+			}
 		s->version = s->client_version = s->method->version;
 		}
 
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index d915155..ea4e132 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1096,6 +1096,13 @@
 				s->version = DTLS1_2_VERSION;
 				s->method = DTLSv1_2_server_method();
 				}
+			else if (tls1_suiteb(s))
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+				s->version = s->client_version;
+				al = SSL_AD_PROTOCOL_VERSION;
+				goto f_err;
+				}
 			else if (s->client_version <= DTLS1_VERSION &&
 				!(s->options & SSL_OP_NO_DTLSv1))
 				{
diff --git a/ssl/ssl.h b/ssl/ssl.h
index cba5f4d..e14a8d4 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2724,6 +2724,7 @@
 #define SSL_R_NULL_SSL_METHOD_PASSED			 196
 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED		 197
 #define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
+#define SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE	 387
 #define SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE	 379
 #define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE		 297
 #define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG			 327
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 4d87d2d..1683f7b 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1377,11 +1377,15 @@
 
 	if (!suiteb_flags)
 		return 1;
-	/* Check version */
+	/* Check version: if TLS 1.2 ciphers allowed we can use Suite B */
 
-	if (meth->version != TLS1_2_VERSION)
+	if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS))
 		{
-		SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
+		if (meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
+			SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
+				SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
+		else
+			SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
 				SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
 		return 0;
 		}
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index b978177..7642758 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
 /* ssl/ssl_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2012 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2013 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -479,6 +479,7 @@
 {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
 {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
 {ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),"old session compression algorithm not returned"},
+{ERR_REASON(SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE),"only DTLS 1 2 allowed in suiteb mode"},
 {ERR_REASON(SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE),"only TLS 1.2 allowed in Suite B mode"},
 {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
 {ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),"opaque PRF input too long"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index f1cbc6f..d06f912 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -871,7 +871,7 @@
 	ssl23_get_cipher, \
 	s_get_meth, \
 	ssl23_default_timeout, \
-	&ssl3_undef_enc_method, \
+	&TLSv1_2_enc_data, \
 	ssl_undefined_void_function, \
 	ssl3_callback_ctrl, \
 	ssl3_ctx_callback_ctrl, \