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;