Blob Blame History Raw
diff -up openssl-1.0.1e/crypto/bio/bio.h.sctp openssl-1.0.1e/crypto/bio/bio.h
--- openssl-1.0.1e/crypto/bio/bio.h.sctp	2016-04-07 13:54:03.296270801 +0200
+++ openssl-1.0.1e/crypto/bio/bio.h	2016-04-07 14:02:53.436214294 +0200
@@ -175,6 +175,8 @@ extern "C" {
 #define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT   45 /* Next DTLS handshake timeout to
                                               * adjust socket timeouts */
 
+#define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD   49
+
 #ifndef OPENSSL_NO_SCTP
 /* SCTP stuff */
 #define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE	50
@@ -607,6 +609,8 @@ int BIO_ctrl_reset_read_request(BIO *b);
          (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer)
 #define BIO_dgram_set_peer(b,peer) \
          (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer)
+#define BIO_dgram_get_mtu_overhead(b) \
+         (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL)
 
 /* These two aren't currently implemented */
 /* int BIO_get_ex_num(BIO *bio); */
diff -up openssl-1.0.1e/crypto/bio/bss_dgram.c.sctp openssl-1.0.1e/crypto/bio/bss_dgram.c
--- openssl-1.0.1e/crypto/bio/bss_dgram.c.sctp	2013-02-11 16:26:04.000000000 +0100
+++ openssl-1.0.1e/crypto/bio/bss_dgram.c	2016-04-07 14:02:53.437214317 +0200
@@ -454,6 +454,36 @@ static int dgram_write(BIO *b, const cha
 	return(ret);
 	}
 
+static long dgram_get_mtu_overhead(bio_dgram_data *data)
+	{
+	long ret;
+
+	switch (data->peer.sa.sa_family)
+		{
+		case AF_INET:
+			/* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP */
+			ret = 28;
+			break;
+#if OPENSSL_USE_IPV6
+		case AF_INET6:
+#ifdef IN6_IS_ADDR_V4MAPPED
+			if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
+				/* Assume this is UDP - 20 bytes for IP, 8 bytes for UDP */
+				ret = 28;
+			else
+#endif
+				/* Assume this is UDP - 40 bytes for IP, 8 bytes for UDP */
+				ret = 48;
+			break;
+#endif
+		default:
+			/* We don't know. Go with the historical default */
+			ret = 28;
+			break;
+		}
+	return ret;
+	}
+
 static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
 	{
 	long ret=1;
@@ -630,23 +660,24 @@ static long dgram_ctrl(BIO *b, int cmd,
 #endif
 		break;
 	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
+		ret = -dgram_get_mtu_overhead(data);
 		switch (data->peer.sa.sa_family)
 			{
 			case AF_INET:
-				ret = 576 - 20 - 8;
+				ret += 576;
 				break;
 #if OPENSSL_USE_IPV6
 			case AF_INET6:
 #ifdef IN6_IS_ADDR_V4MAPPED
 				if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
-					ret = 576 - 20 - 8;
+					ret += 576;
 				else
 #endif
-					ret = 1280 - 40 - 8;
+					ret += 1280;
 				break;
 #endif
 			default:
-				ret = 576 - 20 - 8;
+				ret += 576;
 				break;
 			}
 		break;
@@ -847,6 +878,9 @@ static long dgram_ctrl(BIO *b, int cmd,
 			ret = 0;
 		break;
 #endif
+	case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
+		ret = dgram_get_mtu_overhead(data);
+		break;
 	default:
 		ret=0;
 		break;
@@ -906,8 +940,8 @@ BIO *BIO_new_dgram_sctp(int fd, int clos
 	memset(authchunks, 0, sizeof(sockopt_len));
 	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
 	OPENSSL_assert(ret >= 0);
-	
-	for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
+
+	for (p = (unsigned char*) authchunks->gauth_chunks;
 	     p < (unsigned char*) authchunks + sockopt_len;
 	     p += sizeof(uint8_t))
 		{
@@ -1197,7 +1231,7 @@ static int dgram_sctp_read(BIO *b, char
 			ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
 			OPENSSL_assert(ii >= 0);
 
-			for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
+			for (p = (unsigned char*) authchunks->gauth_chunks;
 				 p < (unsigned char*) authchunks + optlen;
 				 p += sizeof(uint8_t))
 				{
@@ -1367,6 +1401,10 @@ static long dgram_sctp_ctrl(BIO *b, int
 		 * Returns always 1.
 		 */
 		break;
+	case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
+		/* We allow transport protocol fragmentation so this is irrelevant */
+		ret = 0;
+		break;
 	case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
 		if (num > 0)
 			data->in_handshake = 1;
@@ -1399,6 +1437,7 @@ static long dgram_sctp_ctrl(BIO *b, int
 		memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t));
 
 		ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
+		OPENSSL_free(authkey);
 		if (ret < 0) break;
 
 		/* Reset active key */
diff -up openssl-1.0.1e/ssl/d1_both.c.sctp openssl-1.0.1e/ssl/d1_both.c
--- openssl-1.0.1e/ssl/d1_both.c.sctp	2016-04-07 14:09:35.193261496 +0200
+++ openssl-1.0.1e/ssl/d1_both.c	2016-04-07 14:11:18.838592357 +0200
@@ -1458,14 +1458,17 @@ int dtls1_shutdown(SSL *s)
 	{
 	int ret;
 #ifndef OPENSSL_NO_SCTP
-	if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
+	BIO *wbio;
+
+	wbio = SSL_get_wbio(s);
+	if (wbio != NULL && BIO_dgram_is_sctp(wbio) &&
 	    !(s->shutdown & SSL_SENT_SHUTDOWN))
 		{
-		ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+		ret = BIO_dgram_sctp_wait_for_dry(wbio);
 		if (ret < 0) return -1;
 
 		if (ret == 0)
-			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, NULL);
+			BIO_ctrl(wbio, BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, NULL);
 		}
 #endif
 	ret = ssl3_shutdown(s);
diff -up openssl-1.0.1e/ssl/d1_clnt.c.sctp openssl-1.0.1e/ssl/d1_clnt.c
--- openssl-1.0.1e/ssl/d1_clnt.c.sctp	2016-04-07 13:54:03.505275509 +0200
+++ openssl-1.0.1e/ssl/d1_clnt.c	2016-04-07 14:06:48.581511870 +0200
@@ -338,9 +338,13 @@ int dtls1_connect(SSL *s)
 					snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
 					         DTLS1_SCTP_AUTH_LABEL);
 
-					SSL_export_keying_material(s, sctpauthkey,
+					if (SSL_export_keying_material(s, sctpauthkey,
 					                           sizeof(sctpauthkey), labelbuffer,
-					                           sizeof(labelbuffer), NULL, 0, 0);
+					                           sizeof(labelbuffer), NULL, 0, 0) <= 0)
+						{
+						ret = -1;
+						goto end;
+						}
 
 					BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
 							 sizeof(sctpauthkey), sctpauthkey);
@@ -479,9 +483,13 @@ int dtls1_connect(SSL *s)
 			snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
 			         DTLS1_SCTP_AUTH_LABEL);
 
-			SSL_export_keying_material(s, sctpauthkey,
+			if (SSL_export_keying_material(s, sctpauthkey,
 			                           sizeof(sctpauthkey), labelbuffer,
-			                           sizeof(labelbuffer), NULL, 0, 0);
+			                           sizeof(labelbuffer), NULL, 0, 0) <= 0)
+				{
+				ret = -1;
+				goto end;
+				}
 
 			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
 					 sizeof(sctpauthkey), sctpauthkey);
@@ -538,13 +546,6 @@ int dtls1_connect(SSL *s)
 				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
 			if (ret <= 0) goto end;
 
-#ifndef OPENSSL_NO_SCTP
-			/* Change to new shared key of SCTP-Auth,
-			 * will be ignored if no SCTP used.
-			 */
-			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
-#endif
-
 			s->state=SSL3_ST_CW_FINISHED_A;
 			s->init_num=0;
 
@@ -571,6 +572,16 @@ int dtls1_connect(SSL *s)
 				goto end;
 				}
 			
+#ifndef OPENSSL_NO_SCTP
+				if (s->hit)
+					{
+					/* Change to new shared key of SCTP-Auth,
+					 * will be ignored if no SCTP used.
+					 */
+					BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+					}
+#endif
+
 			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
 			break;
 
@@ -613,6 +624,13 @@ int dtls1_connect(SSL *s)
 				}
 			else
 				{
+#ifndef OPENSSL_NO_SCTP
+				/* Change to new shared key of SCTP-Auth,
+				 * will be ignored if no SCTP used.
+				 */
+				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+#endif
+
 #ifndef OPENSSL_NO_TLSEXT
 				/* Allow NewSessionTicket if ticket expected */
 				if (s->tlsext_ticket_expected)
diff -up openssl-1.0.1e/ssl/d1_srvr.c.sctp openssl-1.0.1e/ssl/d1_srvr.c
--- openssl-1.0.1e/ssl/d1_srvr.c.sctp	2016-04-07 13:54:03.529276050 +0200
+++ openssl-1.0.1e/ssl/d1_srvr.c	2016-04-07 14:08:56.110382568 +0200
@@ -395,9 +395,13 @@ int dtls1_accept(SSL *s)
 				snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
 				         DTLS1_SCTP_AUTH_LABEL);
 
-				SSL_export_keying_material(s, sctpauthkey,
+				if (SSL_export_keying_material(s, sctpauthkey,
 				                           sizeof(sctpauthkey), labelbuffer,
-				                           sizeof(labelbuffer), NULL, 0, 0);
+				                           sizeof(labelbuffer), NULL, 0, 0) <= 0)
+					{
+					ret = -1;
+					goto end;
+					}
 				
 				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
                          sizeof(sctpauthkey), sctpauthkey);
@@ -609,9 +613,13 @@ int dtls1_accept(SSL *s)
 			snprintf((char *) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
 			         DTLS1_SCTP_AUTH_LABEL);
 
-			SSL_export_keying_material(s, sctpauthkey,
+			if (SSL_export_keying_material(s, sctpauthkey,
 			                           sizeof(sctpauthkey), labelbuffer,
-			                           sizeof(labelbuffer), NULL, 0, 0);
+			                           sizeof(labelbuffer), NULL, 0, 0) <= 0)
+				{
+				ret = -1;
+				goto end;
+				}
 
 			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
 			         sizeof(sctpauthkey), sctpauthkey);
@@ -713,10 +721,13 @@ int dtls1_accept(SSL *s)
 			if (ret <= 0) goto end;
 
 #ifndef OPENSSL_NO_SCTP
-			/* Change to new shared key of SCTP-Auth,
-			 * will be ignored if no SCTP used.
-			 */
-			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+			if (!s->hit)
+				{
+				/* Change to new shared key of SCTP-Auth,
+				 * will be ignored if no SCTP used.
+				 */
+				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+				}
 #endif
 
 			s->state=SSL3_ST_SW_FINISHED_A;
@@ -741,7 +752,16 @@ int dtls1_accept(SSL *s)
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_SW_FLUSH;
 			if (s->hit)
+				{
 				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+
+#ifndef OPENSSL_NO_SCTP
+				/* Change to new shared key of SCTP-Auth,
+				 * will be ignored if no SCTP used.
+				 */
+				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+#endif
+				}
 			else
 				{
 				s->s3->tmp.next_state=SSL_ST_OK;