[openssl.org #2869] [PATCH] DTLS Mobility support
This patch adds support for DTLS Mobility, as published in our paper: http://link.springer.com/chapter/10.1007/978-3-642-25959-3_33?null After negotiating support with HelloExtensions, an extended RecordHeader is used to allow changing IP addresses with an unconnected UDP socket. Address changes are detected and the new address is verified with the Heatbeat protocol. With this extension a DTLS connection can be kept alive on mobile clients, which usually move between cell phone and WiFi networks. Best regards Robin dtls-mobility.patch Description: Binary data
[openssl.org #2830] [PATCH] Allow setting the Don't Fragment bit for DTLS
This patch adds the BIO_CTRL_DGRAM_SET_DONT_FRAG option for BIO_ctrl() to activate the Don't Fragment bit for the current socket, if possible on the platform. This a necessary feature to realize a Path MTU Discovery with Heatbeats and to use SCTP over DTLS for RTCWeb (Real-time Browser to Browser Communication). Best regards Robin dtls-dont-fragment-0.9.8.patch Description: Binary data dtls-dont-fragment-1.0.1.patch Description: Binary data dtls-dont-fragment-1.0.0.patch Description: Binary data
[openssl.org #2809] [PATCH] DTLS/SCTP struct authchunks Bug
DTLS/SCTP requires DATA and FORWARD-TSN chunks to be protected with SCTP-AUTH. It is checked if this has been activated successfully for the local and remote peer. Due to a bug, however, the gauth_number_of_chunks field of the authchunks struct is missing on FreeBSD, and was therefore not considered in the OpenSSL implementation. This patch sets the corresponding pointer for the check correctly whether or not this bug is present. Best regards Robin dtls-sctp-authchunks-bug-1.0.1.patch Description: Binary data
Re: [openssl.org #2755] [PATCH] DTLS does not lower MTU after retransmissions
On Mar 6, 2012, at 7:29 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Mon Mar 05 15:26:38 2012]: The DTLS implementation does not lower the assumed MTU after unsuccessful retransmissions, which results in a failing handshake in case fragmentation is necessary. With this patch the MTU is reduced to a safe value of 576 - 20 - 8 for IPv4 and 1280 - 40 - 8 for IPv6, respectively, after 2 retransmissions. Should this be applied to OpenSSL 0.9.8? The patch seems to work (with some complaints) but it wont compile. I forgot to add a patch for 0.9.8. The issue is that DTLS in 0.9.8 has no IPv6 support, so the sockaddr structures are different. That's why it doesn't compile. Is there any reason why the IPv6 patch was never applied? Since only IPv4 is possible, the attached version of the patch for 0.9.8 simply always returns the value for IPv4. Best regards Robin Steve. -- Dr Stephen N. Henson. OpenSSL project core developer. Commercial tech support now available see: http://www.openssl.org __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org dtls-timer-mtu-bug-0.9.8.patch Description: Binary data
[openssl.org #2756] [PATCH] DTLS timeout handling bug
DTLS does not handle timeouts correctly, because the timeout counter is reset every time anything has been received, and not only after a full handshake flight. The reset should only be done when the retransmission timer is stopped, otherwise the maximum number of retransmission is never met in case a flight always arrives incomplete, so retransmissions continue and the connection is not terminated. Additionally, the retransmission counter is not increased when the server retransmits its last flight, which is triggered by the retransmission of the client's last flight. This is a problem if the server's last flight exceeds the path MTU, for example. In this case the flight will never arrive at the client, because the server is not counting retransmissions and will not reduce its MTU, or simply give up when the maximum number of retransmissions is reached. Best regards Robin dtls-timeout-handling-bug-1.0.0.patch Description: Binary data dtls-timeout-handling-bug-1.0.1.patch Description: Binary data dtls-timeout-handling-bug-0.9.8.patch Description: Binary data
[openssl.org #2755] [PATCH] DTLS does not lower MTU after retransmissions
The DTLS implementation does not lower the assumed MTU after unsuccessful retransmissions, which results in a failing handshake in case fragmentation is necessary. With this patch the MTU is reduced to a safe value of 576 - 20 - 8 for IPv4 and 1280 - 40 - 8 for IPv6, respectively, after 2 retransmissions. Best regards Robin dtls-timer-mtu-bug-1.0.0.patch Description: Binary data dtls-timer-mtu-bug-1.0.1.patch Description: Binary data
[openssl.org #2748] [PATCH] Possible timer deadlock with DTLS bug
DTLS maintains timers for every handshake flight in case retransmissions are necessary. In the current implementation the timer is stopped as soon as any message of the following flight arrived. This can lead to a deadlock, if the flight was incomplete for some reason and the missing message is awaited forever with no timer running anymore. This patch changes the timer behavior so that a timer is not stopped until the entire following flight has been received to avoid this issue. This is also required by the DTLS specification. Thanks to Lindani Phiri for reporting this bug! Best regards Robin dtls-timer-deadlock-bug-1.0.0.patch Description: Binary data dtls-timer-deadlock-bug-1.0.1.patch Description: Binary data
[openssl.org #2739] [PATCH] TLS/DTLS Heartbeat Response padding bug in 1.0.1
This patch fixes two padding related bugs for the Heartbeat Response messages. For DTLS, the wrong pointer was used, which may overwrite the payload with the random padding. For TLS, there was no random padding at all. Best regards Robin tls-heartbeat-padding-bug-1.0.1.patch Description: Binary data
Re: [openssl.org #2658] [PATCH] Add TLS/DTLS Heartbeats
A new version with auto-generated error codes (instead adding them manually) and improved extension state initialization. Best regards Robin dtls-tls-heartbeats-1.0.1.patch Description: Binary data
Re: [openssl.org #2658] [PATCH] Add TLS/DTLS Heartbeats
New version with less binary operations. SSL_OP_NO_HB_REQUEST is replaced with SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS and the alias SSL_set_tlsext_heartbeat_no_requests(ssl, arg). SSL_heartbeat_pending(ssl) is replaced with SSL_get_tlsext_heartbeat_pending(ssl) for consistency's sake. Best regards Robin dtls-tls-heartbeats-1.0.1.patch Description: Binary data
Re: [openssl.org #2658] [PATCH] Add TLS/DTLS Heartbeats
Remove more unnecessary binary operations. Best regards Robin dtls-tls-heartbeats-1.0.1.patch Description: Binary data
Re: [openssl.org #2051] [PATCH] IPv6 support for s_client and s_server
Here is an updated version of the patch for the current 1.0.1 branch. Best regards Robin ipv6.patch Description: Binary data
Re: [openssl.org #2658] [PATCH] Add TLS/DTLS Heartbeats
Updated version with less defines and without breaking binary compatibility. Best regards Robin dtls-tls-heartbeats-1.0.1.patch Description: Binary data
Re: [openssl.org #2658] [PATCH] Add TLS/DTLS Heartbeats
Here is an updated version with the numbers for the Heartbeat Protocol and the Hello Extension assigned by IANA. Best regards Robin Here is an updated version with the numbers for the Heartbeat Protocol and the Hello Extensionassigned by IANA. Best regardsRobin dtls-tls-heartbeats-1.0.1.patch Description: Binary data
[openssl.org #2658] [PATCH] Add TLS/DTLS Heartbeats
This patch adds TLS/DTLS Heartbeats, as described in tools.ietf.org/html/draft-ietf-tls-dtls-heartbeat Heartbeats can be sent any time when no handshake is in progress to check the availability of the peer. The retransmission feature of DTLS is used to repeat lost Heartbeats. If no response is received, the peer is considered unavailable and an SSL timeout error occurs. Heartbeats can be sent with SSL_heartbeat() and SSL_heartbeat_pending() can be used to check if one is still in flight. The option SSL_OP_NO_HB_REQUEST can be set to not allow the peer to send HeartbeatRequests, which is useful for devices powered with a battery. This is a preliminary version, because the IANA has not yet assigned the necessary numbers for the Heartbeat protocol and the Hello extensions. Best regards Robin This patch adds TLS/DTLS Heartbeats, as described intools.ietf.org/html/draft-ietf-tls-dtls-heartbeatHeartbeats can be sent any time when no handshake is in progress to check the availability of the peer. The retransmission feature of DTLS is used to repeat lost Heartbeats. If no response is received, the peer is considered unavailable and an SSL timeout error occurs. Heartbeats can be sent withSSL_heartbeat() andSSL_heartbeat_pending() can be used to check if one is still in flight. The optionSSL_OP_NO_HB_REQUEST can be set to not allow the peer to send HeartbeatRequests, which is useful for devices powered with a battery.This is a preliminary version, because the IANA has not yet assigned the necessary numbers for the Heartbeat protocol and the Hello extensions. Best regardsRobin dtls-tls-heartbeats-1.0.1.patch Description: Binary data
[openssl.org #2628] [PATCH] ServerKeyExchange signature broken if ECC key is used with DTLS
The signature in the ServerKeyExchange is created with wrong parameters with ECC keys, because the TLS header length is used instead of the DTLS header length. Thanks to Erwin Himawan for providing hints! Best regards Robin --- ssl/d1_srvr.c 5 Sep 2011 10:25:21 - 1.20.2.21 +++ ssl/d1_srvr.c 20 Oct 2011 09:20:35 - @@ -1271,7 +1271,7 @@ EVP_SignInit_ex(md_ctx,EVP_ecdsa(), NULL); EVP_SignUpdate(md_ctx,(s-s3-client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(md_ctx,(s-s3-server_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(md_ctx,(d[4]),n); + EVP_SignUpdate(md_ctx,(d[DTLS1_HM_HEADER_LENGTH]),n); if (!EVP_SignFinal(md_ctx,(p[2]), (unsigned int *)i,pkey)) { dtls-ecc-key-bug-1.0.0.patch Description: Binary data dtls-ecc-key-bug-1.0.1.patch Description: Binary data
[openssl.org #2625] [PATCH] Incorrect fragments cause DTLS to exit the program
The reception of incomplete or incorrectly formatted DTLS fragments is handled with an OPENSSL_assert(), causing the program to exit rather then just terminating the connection. This patch exchanges the asserts with unexpected message and illegal parameter alerts. Thanks to Zhu Qun-Ying for finding this bug! Best regards Robin --- ssl/d1_both.c 23 Sep 2011 13:35:19 - 1.14.2.25 +++ ssl/d1_both.c 18 Oct 2011 13:16:22 - @@ -793,7 +793,13 @@ *ok = 0; return i; } - OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH); + /* Handshake fails if message header is incomplete */ + if (i != DTLS1_HM_HEADER_LENGTH) + { + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } /* parse the message fragment header */ dtls1_get_message_header(wire, msg_hdr); @@ -865,7 +871,12 @@ /* XDTLS: an incorrectly formatted fragment should cause the * handshake to fail */ - OPENSSL_assert(i == (int)frag_len); + if (i != (int)frag_len) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL3_AD_ILLEGAL_PARAMETER); + goto f_err; + } *ok = 1; dtls-fragment-assert-bug-0.9.8.patch Description: Binary data dtls-fragment-assert-bug-1.0.0.patch Description: Binary data dtls-fragment-assert-bug-1.0.1.patch Description: Binary data
[openssl.org #2602] [PATCH] DTLS bug prevents manual MTU setting
Since patch #2506 the MTU stored in DTLS1_STATE is cleared with every initial handshake. This prevents setting an MTU manually when SSL_OP_NO_QUERY_MTU is set and causes OpenSSL to crash because an MTU of 0 is used therefore an memcpy with a negative length in the following. This patch prevents the MTU from being overwritten if SSL_OP_NO_QUERY_MTU is set, adds an assert to prevent invalid MTU values from being used and doesn't allow to manually set too low MTU values. Thanks to Paul Witty for reporting this bug! Best regards Robin --- ssl/d1_both.c 3 Apr 2011 17:15:08 - 1.14.2.24 +++ ssl/d1_both.c 13 Sep 2011 14:51:21 - @@ -158,7 +158,6 @@ /* XDTLS: figure out the right values */ static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; -static unsigned int dtls1_min_mtu(void); static unsigned int dtls1_guess_mtu(unsigned int curr_mtu); static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len); @@ -264,11 +263,10 @@ return ret; mtu = s-d1-mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); } - - OPENSSL_assert(mtu 0); /* should have something reasonable now */ - #endif + OPENSSL_assert(s-d1-mtu = dtls1_min_mtu()); /* should have something reasonable now */ + if ( s-init_off == 0 type == SSL3_RT_HANDSHAKE) OPENSSL_assert(s-init_num == (int)s-d1-w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); @@ -1367,7 +1365,7 @@ return p; } -static unsigned int +unsigned int dtls1_min_mtu(void) { return (g_probable_mtu[(sizeof(g_probable_mtu) / --- ssl/d1_lib.c22 Jun 2011 15:29:55 - 1.8.2.17 +++ ssl/d1_lib.c13 Sep 2011 14:51:21 - @@ -204,7 +204,8 @@ pqueue buffered_messages; pqueue sent_messages; pqueue buffered_app_data; - + unsigned int mtu; + if (s-d1) { unprocessed_rcds = s-d1-unprocessed_rcds.q; @@ -212,6 +213,7 @@ buffered_messages = s-d1-buffered_messages; sent_messages = s-d1-sent_messages; buffered_app_data = s-d1-buffered_app_data.q; + mtu = s-d1-mtu; dtls1_clear_queues(s); @@ -222,6 +224,11 @@ s-d1-cookie_len = sizeof(s-d1-cookie); } + if (SSL_get_options(s) SSL_OP_NO_QUERY_MTU) + { + s-d1-mtu = mtu; + } + s-d1-unprocessed_rcds.q = unprocessed_rcds; s-d1-processed_rcds.q = processed_rcds; s-d1-buffered_messages = buffered_messages; --- ssl/ssl_lib.c 14 Aug 2011 13:48:42 - 1.176.2.20 +++ ssl/ssl_lib.c 13 Sep 2011 14:51:21 - @@ -1054,6 +1054,9 @@ s-max_cert_list=larg; return(l); case SSL_CTRL_SET_MTU: + if (larg dtls1_min_mtu()) + return 0; + if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) { --- ssl/ssl_locl.h 8 Dec 2009 11:38:18 - 1.100.2.10 +++ ssl/ssl_locl.h 13 Sep 2011 14:51:21 - @@ -950,6 +950,7 @@ int dtls1_is_timer_expired(SSL *s); void dtls1_double_timeout(SSL *s); int dtls1_send_newsession_ticket(SSL *s); +unsigned int dtls1_min_mtu(void); /* some client-only functions */ int ssl3_client_hello(SSL *s); dtls-mtu-bug-1.0.1.patch Description: Binary data dtls-mtu-bug-1.0.0.patch Description: Binary data dtls-mtu-bug-0.9.8.patch Description: Binary data
[openssl.org #2573] [PATCH] DTLS buffering and decryption bug
DTLS buffers records of the next epoch while listening, although it's not supposed to change its state. Additionally, when the decryption of buffered records fails, the connection is dropped with a BadRecord alert, instead of just silently discarding the message. With this patch nothing is buffered while listening and messages that cannot be decrypted will be ignored. Thanks to Yogesh Chopra for providing hints! Best regards Robin --- ssl/d1_pkt.c4 Jan 2011 19:33:22 - 1.27.2.26 +++ ssl/d1_pkt.c28 Jul 2011 10:48:48 - @@ -409,13 +409,13 @@ enc_err = s-method-ssl3_enc-enc(s,0); if (enc_err = 0) { - if (enc_err == 0) - /* SSLerr() and ssl3_send_alert() have been called */ - goto err; - - /* otherwise enc_err == -1 */ - al=SSL_AD_BAD_RECORD_MAC; - goto f_err; + /* decryption failed, silently discard message */ + if (enc_err 0) + { + rr-length = 0; + s-packet_length = 0; + } + goto err; } #ifdef TLS_DEBUG @@ -658,10 +658,12 @@ /* If this record is from the next epoch (either HM or ALERT), * and a handshake is currently in progress, buffer it since it -* cannot be processed at this time. */ +* cannot be processed at this time. However, do not buffer +* anything while listening. +*/ if (is_next_epoch) { - if (SSL_in_init(s) || s-in_handshake) + if ((SSL_in_init(s) || s-in_handshake) !s-d1-listen) { dtls1_buffer_record(s, (s-d1-unprocessed_rcds), rr-seq_num); } dtls-decryption-buffer-bug-0.9.8.patch Description: Binary data dtls-decryption-buffer-bug-1.0.0.patch Description: Binary data dtls-decryption-buffer-bug-1.0.1.patch Description: Binary data
[openssl.org #2559] [PATCH] DTLS socket error bug
The socket timeout is adjusted before reading and reset afterwards, in case a handshake is in progress to handle handshake timeouts properly. The reset, however, is done before the socket error handling. The new system call overwrites the error code when using Windows and breaks the error handling. Doing the error handling first fixes this issue. Thanks to Nilesh Vaghela for providing hints! Best regards Robin --- crypto/bio/bss_dgram.c 3 Jan 2011 01:07:03 - 1.7.2.24 +++ crypto/bio/bss_dgram.c 12 Jul 2011 11:20:23 - @@ -308,7 +308,6 @@ OPENSSL_assert(sa.len.s=sizeof(sa.peer)); sa.len.i = (int)sa.len.s; } - dgram_reset_rcv_timeout(b); if ( ! data-connected ret = 0) BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, sa.peer); @@ -322,6 +321,8 @@ data-_errno = get_last_socket_error(); } } + + dgram_reset_rcv_timeout(b); } return(ret); } @@ -745,9 +746,13 @@ { err=get_last_socket_error(); -#if defined(OPENSSL_SYS_WINDOWS) 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */ - if ((i == -1) (err == 0)) - return(1); +#if defined(OPENSSL_SYS_WINDOWS) + /* If the socket return value (i) is -1 +* and err is unexpectedly 0 at this point, +* the error code was overwritten by +* another system call before this error +* handling is called. +*/ #endif return(BIO_dgram_non_fatal_error(err)); dtls-socket-error-bug-0.9.8.patch Description: Binary data dtls-socket-error-bug-1.0.0.patch Description: Binary data dtls-socket-error-bug-1.0.1.patch Description: Binary data
[openssl.org #2550] [PATCH] DTLS HelloVerifyRequest Timer bug
The server starts a timer when sending a HelloVerifyRequest, although its state should remain unchanged. Thanks to Yogesh Chopra for finding this bug! Best regards Robin --- ssl/d1_srvr.c 25 May 2011 14:29:55 - 1.20.2.18 +++ ssl/d1_srvr.c 27 Jun 2011 10:02:10 - @@ -295,7 +295,6 @@ case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: - dtls1_start_timer(s); ret = dtls1_send_hello_verify_request(s); if ( ret = 0) goto end; s-state=SSL3_ST_SW_FLUSH; dtls-helloverify-timer-bug-1.0.0.patch Description: Binary data dtls-helloverify-timer-bug-1.0.1.patch Description: Binary data dtls-helloverify-timer-bug-0.9.8.patch Description: Binary data
[openssl.org #2543] [PATCH] DTLS handle timeout error handling
As mentioned by Nilesh Vaghela, DTLSv1_handle_timeout() does not handle errors because of too many retransmissions correctly. The return value should be -1 instead of 0, so the application can detect the error. Best regards Robin --- ssl/d1_lib.c25 May 2011 14:30:05 - 1.8.2.13.2.3 +++ ssl/d1_lib.c22 Jun 2011 08:11:35 - @@ -398,7 +398,7 @@ { /* fail the connection, enough alerts have been sent */ SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED); - return 0; + return -1; } state-timeout.read_timeouts++; dtls-handle-timeout-bug-0.9.8.patch Description: Binary data dtls-handle-timeout-bug-1.0.0.patch Description: Binary data dtls-handle-timeout-bug-1.0.1.patch Description: Binary data
[openssl.org #2533] [PATCH] Setting SSL_MODE_RELEASE_BUFFERS crashes with DTLS
Setting SSL_MODE_RELEASE_BUFFERS should be ignored for DTLS, but instead causes the program to crash. This is due to missing version checks and is fixed with this patch. Best regards Robin --- ssl/s3_pkt.c11 May 2011 13:37:52 - 1.72.2.7.2.7 +++ ssl/s3_pkt.c25 May 2011 11:13:58 - @@ -247,7 +247,8 @@ if (i = 0) { rb-left = left; - if (s-mode SSL_MODE_RELEASE_BUFFERS) + if (s-mode SSL_MODE_RELEASE_BUFFERS + SSL_version(s) != DTLS1_VERSION SSL_version(s) != DTLS1_BAD_VER) if (len+left == 0) ssl3_release_read_buffer(s); return(i); @@ -866,7 +867,8 @@ { wb-left=0; wb-offset+=i; - if (s-mode SSL_MODE_RELEASE_BUFFERS) + if (s-mode SSL_MODE_RELEASE_BUFFERS + SSL_version(s) != DTLS1_VERSION SSL_version(s) != DTLS1_BAD_VER) ssl3_release_write_buffer(s); s-rwstate=SSL_NOTHING; return(s-s3-wpend_ret); dtls-release-buffers-bug-1.0.1.patch Description: Binary data dtls-release-buffers-bug-1.0.0.patch Description: Binary data
Re: [openssl.org #2506] [PATCH] SSL_clear not fully implemented for DTLS
Here is an updated version of the patch, also addressing the memory leak reported in #1714. Best regards Robin --- ssl/d1_lib.c3 Apr 2011 17:14:48 - 1.8.2.13.2.1 +++ ssl/d1_lib.c6 May 2011 12:40:39 - @@ -129,26 +129,33 @@ return(1); } -void dtls1_free(SSL *s) +static void dtls1_clear_queues(SSL *s) { pitem *item = NULL; hm_fragment *frag = NULL; - - ssl3_free(s); + DTLS1_RECORD_DATA *rdata; while( (item = pqueue_pop(s-d1-unprocessed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *) item-data; + if (rdata-rbuf.buf) + { + OPENSSL_free(rdata-rbuf.buf); + } OPENSSL_free(item-data); pitem_free(item); } -pqueue_free(s-d1-unprocessed_rcds.q); while( (item = pqueue_pop(s-d1-processed_rcds.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *) item-data; + if (rdata-rbuf.buf) + { + OPENSSL_free(rdata-rbuf.buf); + } OPENSSL_free(item-data); pitem_free(item); } -pqueue_free(s-d1-processed_rcds.q); while( (item = pqueue_pop(s-d1-buffered_messages)) != NULL) { @@ -157,7 +164,6 @@ OPENSSL_free(frag); pitem_free(item); } -pqueue_free(s-d1-buffered_messages); while ( (item = pqueue_pop(s-d1-sent_messages)) != NULL) { @@ -166,7 +172,6 @@ OPENSSL_free(frag); pitem_free(item); } - pqueue_free(s-d1-sent_messages); while ( (item = pqueue_pop(s-d1-buffered_app_data.q)) != NULL) { @@ -175,6 +180,18 @@ OPENSSL_free(frag); pitem_free(item); } + } + +void dtls1_free(SSL *s) + { + ssl3_free(s); + + dtls1_clear_queues(s); + +pqueue_free(s-d1-unprocessed_rcds.q); +pqueue_free(s-d1-processed_rcds.q); +pqueue_free(s-d1-buffered_messages); + pqueue_free(s-d1-sent_messages); pqueue_free(s-d1-buffered_app_data.q); OPENSSL_free(s-d1); @@ -182,6 +199,36 @@ void dtls1_clear(SSL *s) { +pqueue unprocessed_rcds; +pqueue processed_rcds; +pqueue buffered_messages; + pqueue sent_messages; + pqueue buffered_app_data; + + if (s-d1) + { + unprocessed_rcds = s-d1-unprocessed_rcds.q; + processed_rcds = s-d1-processed_rcds.q; + buffered_messages = s-d1-buffered_messages; + sent_messages = s-d1-sent_messages; + buffered_app_data = s-d1-buffered_app_data.q; + + dtls1_clear_queues(s); + + memset(s-d1, 0, sizeof(*(s-d1))); + + if (s-server) + { + s-d1-cookie_len = sizeof(s-d1-cookie); + } + + s-d1-unprocessed_rcds.q = unprocessed_rcds; + s-d1-processed_rcds.q = processed_rcds; + s-d1-buffered_messages = buffered_messages; + s-d1-sent_messages = sent_messages; + s-d1-buffered_app_data.q = buffered_app_data; + } + ssl3_clear(s); if (s-options SSL_OP_CISCO_ANYCONNECT) s-version=DTLS1_BAD_VER; dtls-clear-0.9.8.patch Description: Binary data dtls-clear-1.0.0.patch Description: Binary data dtls-clear-1.0.1.patch Description: Binary data
[openssl.org #2505] [PATCH] DTLS Session Resumption Timer Bug
The client always starts timer for the retransmission of the ChangeCipherSpec and Finished, although that is only correct when performing a full handshake. With the abbreviated session resumption handshake, these messages are not followed by a response of the server, so the timer is never stopped and causes retransmissions until the connection is dropped. This patch adds the distinction between full and abbreviated handshakes and prevents the timer from being started in the latter case. Best regards Robin --- ssl/d1_clnt.c 27 Aug 2010 12:10:11 - 1.16.2.15.2.3 +++ ssl/d1_clnt.c 27 Apr 2011 12:27:50 - @@ -407,7 +407,8 @@ case SSL3_ST_CW_CHANGE_A: case SSL3_ST_CW_CHANGE_B: - dtls1_start_timer(s); + if (!s-hit) + dtls1_start_timer(s); ret=dtls1_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B); if (ret = 0) goto end; @@ -442,7 +443,8 @@ case SSL3_ST_CW_FINISHED_A: case SSL3_ST_CW_FINISHED_B: - dtls1_start_timer(s); + if (!s-hit) + dtls1_start_timer(s); ret=dtls1_send_finished(s, SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B, s-method-ssl3_enc-client_finished_label, dtls-session-resumption-timer-bug-0.9.8.patch Description: Binary data dtls-session-resumption-timer-bug-1.0.0.patch Description: Binary data dtls-session-resumption-timer-bug-1.0.1.patch Description: Binary data
[openssl.org #2506] [PATCH] SSL_clear not fully implemented for DTLS
The implementation of dtls1_clear(), called by SSL_clear(), is not handling the DTLS1_STATE struct at s-d1. Hence, calling SSL_clear() does not reset any value stored in this struct, which includes epochs, sequence numbers, replay check bitmask, buffered messages, etc. This also prevents the -reconnect option for s_client from working, because the state is not fully cleared and thus the next connection attempt starts with an initial ClientHello with epoch 1, which is invalid and ignored by the server. This patch adds clearing all values and emptying all queues in s-d1 when calling SSL_clear(). Best regards Robin --- ssl/d1_lib.c3 Apr 2011 17:14:48 - 1.8.2.13.2.1 +++ ssl/d1_lib.c27 Apr 2011 12:25:10 - @@ -129,26 +129,22 @@ return(1); } -void dtls1_free(SSL *s) +static void dtls1_clear_queues(SSL *s) { pitem *item = NULL; hm_fragment *frag = NULL; - - ssl3_free(s); - + while( (item = pqueue_pop(s-d1-unprocessed_rcds.q)) != NULL) { OPENSSL_free(item-data); pitem_free(item); } -pqueue_free(s-d1-unprocessed_rcds.q); while( (item = pqueue_pop(s-d1-processed_rcds.q)) != NULL) { OPENSSL_free(item-data); pitem_free(item); } -pqueue_free(s-d1-processed_rcds.q); while( (item = pqueue_pop(s-d1-buffered_messages)) != NULL) { @@ -157,7 +153,6 @@ OPENSSL_free(frag); pitem_free(item); } -pqueue_free(s-d1-buffered_messages); while ( (item = pqueue_pop(s-d1-sent_messages)) != NULL) { @@ -166,7 +161,6 @@ OPENSSL_free(frag); pitem_free(item); } - pqueue_free(s-d1-sent_messages); while ( (item = pqueue_pop(s-d1-buffered_app_data.q)) != NULL) { @@ -175,6 +169,18 @@ OPENSSL_free(frag); pitem_free(item); } + } + +void dtls1_free(SSL *s) + { + ssl3_free(s); + + dtls1_clear_queues(s); + +pqueue_free(s-d1-unprocessed_rcds.q); +pqueue_free(s-d1-processed_rcds.q); +pqueue_free(s-d1-buffered_messages); + pqueue_free(s-d1-sent_messages); pqueue_free(s-d1-buffered_app_data.q); OPENSSL_free(s-d1); @@ -182,6 +188,36 @@ void dtls1_clear(SSL *s) { +pqueue unprocessed_rcds; +pqueue processed_rcds; +pqueue buffered_messages; + pqueue sent_messages; + pqueue buffered_app_data; + + if (s-d1) + { + unprocessed_rcds = s-d1-unprocessed_rcds.q; + processed_rcds = s-d1-processed_rcds.q; + buffered_messages = s-d1-buffered_messages; + sent_messages = s-d1-sent_messages; + buffered_app_data = s-d1-buffered_app_data.q; + + dtls1_clear_queues(s); + + memset(s-d1, 0, sizeof(*(s-d1))); + + if (s-server) + { + s-d1-cookie_len = sizeof(s-d1-cookie); + } + + s-d1-unprocessed_rcds.q = unprocessed_rcds; + s-d1-processed_rcds.q = processed_rcds; + s-d1-buffered_messages = buffered_messages; + s-d1-sent_messages = sent_messages; + s-d1-buffered_app_data.q = buffered_app_data; + } + ssl3_clear(s); if (s-options SSL_OP_CISCO_ANYCONNECT) s-version=DTLS1_BAD_VER; dtls-clear-1.0.1.patch Description: Binary data dtls-clear-1.0.0.patch Description: Binary data dtls-clear-0.9.8.patch Description: Binary data
Re: [openssl.org #2484] [PATCH] DTLS: wrong fragment reassembly
Hi, On Apr 1, 2011, at 9:28 AM, via RT wrote: I’ve tested DTLS implementation and know that several fixes has been applied for issues related to fragment. Thanks for testing! There is a known issue with the bitmask, the patch #2457 addresses that, but has not been applied to the official source yet. But, it still has a problem to reassemble fragments. Please, check the attached patch. Patch #2457 corrects the first value in bitmask_end_values[] to 0xff. Your patch is basically doing the same, but you also shift the entire array, which requires adjusting the index when accessing it by subtracting one. Please have a look at http://sctp.fh-muenster.de for the latest DTLS patches. It would be great if you could confirm that #2457 fixes the problems you encountered. Best regards Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #2462] [PATCH] DTLS Retransmission Buffer Bug
DTLS clears the handshake retransmission buffer every time a message has been received, assuming no retransmissions are necessary anymore. This fails when the last flight of the server was lost twice. The first time DTLS bundles the SessionTicket, ChangeCipherSpec and Finished messages into one packet. If this gets lost, the client repeats its last flight. The server will then retransmit the mentioned messages each in a single packet. If any of them is lost again, the flight is not complete but the client clears its retransmission buffer as soon as the first message of the flight arrives. The server assumes that the handshake has been completed but the client still awaits a retransmission of the last flight. The client retransmits its empty buffer, that is nothing, and will give up when it reached its max number of timeouts. This can be solved easily by clearing the buffer when the retransmission timer is stopped. That happens when nothing has to be retransmitted anymore whic h is exactly when the buffer is supposed to be cleared. Thanks to Robert Story for providing hints! -Robin --- ssl/d1_both.c 3 May 2010 13:01:50 - 1.14.2.21 +++ ssl/d1_both.c 28 Feb 2011 15:12:07 - @@ -465,19 +465,6 @@ memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); s-d1-handshake_read_seq++; - /* we just read a handshake message from the other side: -* this means that we don't need to retransmit of the -* buffered messages. -* XDTLS: may be able clear out this -* buffer a little sooner (i.e if an out-of-order -* handshake message/record is received at the record -* layer. -* XDTLS: exception is that the server needs to -* know that change cipher spec and finished messages -* have been received by the client before clearing this -* buffer. this can simply be done by waiting for the -* first data segment, but is there a better way? */ - dtls1_clear_record_buffer(s); s-init_msg = s-init_buf-data + DTLS1_HM_HEADER_LENGTH; return s-init_num; --- ssl/d1_lib.c6 Apr 2010 12:29:21 - 1.8.2.13 +++ ssl/d1_lib.c28 Feb 2011 15:12:07 - @@ -330,6 +330,8 @@ memset((s-d1-next_timeout), 0, sizeof(struct timeval)); s-d1-timeout_duration = 1; BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, (s-d1-next_timeout)); + /* Clear retransmission buffer */ + dtls1_clear_record_buffer(s); } int dtls1_handle_timeout(SSL *s) dtls-rtx-buffer-bug-0.9.8.patch Description: Binary data dtls-rtx-buffer-bug-1.0.0.patch Description: Binary data dtls-rtx-buffer-bug-1.0.1.patch Description: Binary data
[openssl.org #2457] [PATCH] DTLS Reassembly Bitmask
With patch #2230 a DTLS reassembly bitmask array should have been changed. Unfortunately this change was lost, so there is still a bug. Fragmented messages with lengths of multiples of 8 may not be handled correctly, because the highest byte of the bitmask will be compared to 0x00 instead of 0xff. -Robin --- ssl/d1_both.c 3 May 2010 13:01:50 - 1.14.2.21 +++ ssl/d1_both.c 23 Feb 2011 12:56:15 - @@ -153,7 +153,7 @@ #endif static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; -static unsigned char bitmask_end_values[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; +static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; /* XDTLS: figure out the right values */ static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; dtls-rsmbly-bitmask-bug-0.9.8.patch Description: Binary data dtls-rsmbly-bitmask-bug-1.0.0.patch Description: Binary data dtls-rsmbly-bitmask-bug-1.0.1.patch Description: Binary data
[openssl.org #2458] [PATCH] DTLS state changed while listening may cause infinite loop
While listening for incoming connections, DTLS should answer every ClientHello with a HelloVerifyRequest without changing its state. However, this is not the case since the handshake sequence numbers are still incremented with every incoming message. After receiving an initial ClientHello (seq 0), seq 1 is expected (ClientHello with cookie) and every other initial ClientHello will be dropped until seq 1 has been received. This may even result in an infinite loop when the expected sequence number becomes 1 due to a race condition with many simultaneously connecting clients, because the expected number will never appear while in listening state. The changes of the attached patch prevent the increase of the sequence numbers while listening, so only sequence number 0 (initial ClientHello) will be expected and accepted. An exception exists for sequence number 1 (ClientHello with cookie), which has to be allowed as well. After a valid ClientHello with cookie has been received, the sequence numbers are set to the expected values to continue the handshake. Additionally, HelloVerifyRequest messages aren't buffered and retransmitted anymore, since this would also change the state of the listening server according to RFC 4347. Thanks to Neeraj Rajgure for providing hints! -Robin --- ssl/d1_both.c 3 May 2010 13:01:50 - 1.14.2.21 +++ ssl/d1_both.c 23 Feb 2011 13:25:54 - @@ -464,7 +464,10 @@ memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); - s-d1-handshake_read_seq++; + /* Don't change sequence numbers while listening */ + if (!s-d1-listen) + s-d1-handshake_read_seq++; + /* we just read a handshake message from the other side: * this means that we don't need to retransmit of the * buffered messages. @@ -813,9 +816,11 @@ /* * if this is a future (or stale) message it gets buffered -* (or dropped)--no further processing at this time +* (or dropped)--no further processing at this time +* While listening, we accept seq 1 (ClientHello with cookie) +* although we're still expecting seq 0 (ClientHello) */ - if ( msg_hdr.seq != s-d1-handshake_read_seq) + if (msg_hdr.seq != s-d1-handshake_read_seq !(s-d1-listen msg_hdr.seq == 1)) return dtls1_process_out_of_seq_message(s, msg_hdr, ok); len = msg_hdr.msg_len; @@ -1322,7 +1327,8 @@ dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, unsigned long len, unsigned long frag_off, unsigned long frag_len) { - if ( frag_off == 0) + /* Don't change sequence numbers while listening */ + if (frag_off == 0 !s-d1-listen) { s-d1-handshake_write_seq = s-d1-next_handshake_write_seq; s-d1-next_handshake_write_seq++; --- ssl/d1_srvr.c 27 Aug 2010 12:10:11 - 1.20.2.16.2.3 +++ ssl/d1_srvr.c 23 Feb 2011 13:25:54 - @@ -278,6 +278,12 @@ { ret = 2; s-d1-listen = 0; + /* Set expected sequence numbers +* to continue the handshake. +*/ + s-d1-handshake_read_seq = 2; + s-d1-handshake_write_seq = 1; + s-d1-next_handshake_write_seq = 1; goto end; } @@ -737,9 +743,6 @@ /* number of bytes to write */ s-init_num=p-buf; s-init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); } /* s-state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ dtls-listen-state-bugs-0.9.8.patch Description: Binary data dtls-listen-state-bugs-1.0.0.patch Description: Binary data dtls-listen-state-bugs-1.0.1.patch Description: Binary data
Re: [openssl.org #1833] [PATCH] Abbreviated Renegotiations
On 05.09.2010, at 02:08, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Mon Aug 30 16:26:24 2010]: On Aug 27, 2010, at 2:32 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Fri Aug 27 11:34:17 2010]: Unfortunately, there was newer code which was not yet covered by the patch. This caused an abbreviated handshake to fail. Applied now, thanks. Note that since we need to retain binary compatibility between 1.0.0 and 1.0.1 we will need to either avoid having to add a new field to ssl.h or move it to the end of the structure. As things are any application accessing a field after the new member would misbehave. Do you need a patch which moves the int renegotiate; to the end of the struct for 1.0.1? No, I was just wondering if it was possible to achieve the same functionality without adding any new fields to the SSL structure? For example by adding flags or new values to the existing new_session field? The latest patch was modified to maintain the previous values of new_session for legacy applications. We can either break compatibility of a few applications, if any, by adding a new field or by adding new values. I don't see any possibility to avoid this at all. -Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1833] [PATCH] Abbreviated Renegotiations
On Aug 27, 2010, at 2:32 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Fri Aug 27 11:34:17 2010]: Unfortunately, there was newer code which was not yet covered by the patch. This caused an abbreviated handshake to fail. Applied now, thanks. Note that since we need to retain binary compatibility between 1.0.0 and 1.0.1 we will need to either avoid having to add a new field to ssl.h or move it to the end of the structure. As things are any application accessing a field after the new member would misbehave. Do you need a patch which moves the int renegotiate; to the end of the struct for 1.0.1? -Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1833] [PATCH] Abbreviated Renegotiations
Updated version. The variable new_session is now set during a full handshake as before, to avoid breaking applications which access it directly instead using SSL_renegotiate_pending() to determine whether a handshake is in progress. --- ssl/d1_clnt.c 26 Jan 2010 19:46:29 - 1.16.2.15 +++ ssl/d1_clnt.c 26 Aug 2010 13:04:39 - @@ -171,7 +171,7 @@ switch(s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; s-state=SSL_ST_CONNECT; s-ctx-stats.sess_connect_renegotiate++; /* break */ @@ -539,6 +539,7 @@ /* else do it later in ssl3_write */ s-init_num=0; + s-renegotiate=0; s-new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); --- ssl/d1_pkt.c15 Jun 2010 17:25:13 - 1.27.2.25 +++ ssl/d1_pkt.c26 Aug 2010 13:04:39 - @@ -957,6 +957,7 @@ !(s-s3-flags SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) !s-s3-renegotiate) { + s-new_session = 1; ssl3_renegotiate(s); if (ssl3_renegotiate_check(s)) { @@ -1163,6 +1164,7 @@ #else s-state = s-server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; #endif + s-renegotiate=1; s-new_session=1; } i=s-handshake_func(s); --- ssl/d1_srvr.c 1 Feb 2010 16:49:42 - 1.20.2.16 +++ ssl/d1_srvr.c 26 Aug 2010 13:04:39 - @@ -177,7 +177,7 @@ switch (s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; /* s-state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: @@ -299,7 +299,7 @@ case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: - s-new_session = 2; + s-renegotiate = 2; dtls1_start_timer(s); ret=dtls1_send_server_hello(s); if (ret = 0) goto end; @@ -620,11 +620,12 @@ s-init_num=0; - if (s-new_session == 2) /* skipped if we just sent a HelloRequest */ + if (s-renegotiate == 2) /* skipped if we just sent a HelloRequest */ { /* actually not necessarily a 'new' session unless * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ + s-renegotiate=0; s-new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); --- ssl/s3_clnt.c 28 Feb 2010 00:24:24 - 1.129.2.15 +++ ssl/s3_clnt.c 26 Aug 2010 13:04:39 - @@ -207,7 +207,7 @@ switch(s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; s-state=SSL_ST_CONNECT; s-ctx-stats.sess_connect_renegotiate++; /* break */ @@ -546,6 +546,7 @@ /* else do it later in ssl3_write */ s-init_num=0; + s-renegotiate=0; s-new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); --- ssl/s3_lib.c16 Oct 2009 15:24:19 - 1.126.2.4 +++ ssl/s3_lib.c26 Aug 2010 13:04:39 - @@ -2226,6 +2226,7 @@ s-packet_length=0; s-s3-renegotiate=0; + s-s3-new_session=0; s-s3-total_renegotiations=0; s-s3-num_renegotiations=0; s-s3-in_read_app_data=0; --- ssl/s3_pkt.c27 Jun 2010 14:22:10 - 1.72.2.7.2.1 +++ ssl/s3_pkt.c26 Aug 2010 13:04:39 - @@ -1280,6 +1280,7 @@ #else s-state = s-server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; #endif + s-renegotiate=1; s-new_session=1; } i=s-handshake_func(s); --- ssl/s3_srvr.c 27 Feb 2010 23:04:10 - 1.171.2.21 +++ ssl/s3_srvr.c 26 Aug 2010 13:04:39 - @@ -218,7 +218,7 @@ switch (s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; /*
[openssl.org #2319] [BUG] Compile error on Mac OS X
OpenSSL does not compile anymore as a shared library with Mac OS X since check-ins #19768 - #19771 by appro. It always fails with the following error: making all in engines... /bin/sh: -c: line 0: unexpected EOF while looking for matching ``' /bin/sh: -c: line 1: syntax error: unexpected end of file make[2]: *** [link_o.darwin] Error 2 make[1]: *** [lib] Error 2 make: *** [build_engines] Error 1 -Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1830] [PATCH] TLS Key Material Extractor
Here is an up to date version of the patch for OpenSSL 1.0.1, adding the TLS Key Exporter, as described in RFC 5705. --- ssl/ssl.h 6 Jan 2010 17:37:38 - 1.221.2.24 +++ ssl/ssl.h 17 Jun 2010 12:25:35 - @@ -1806,6 +1806,10 @@ /* Pre-shared secret session resumption functions */ int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); +void SSL_tls1_key_exporter(SSL *s, unsigned char *label, int label_len, + unsigned char *context, int context_len, + unsigned char *out, int olen); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. --- ssl/t1_enc.c15 Jun 2010 17:25:15 - 1.57.2.3 +++ ssl/t1_enc.c17 Jun 2010 12:25:35 - @@ -1043,3 +1043,17 @@ } } +void SSL_tls1_key_exporter(SSL *s, unsigned char *label, int label_len, + unsigned char *context, int context_len, + unsigned char *out, int olen) + { + unsigned char tmp[olen]; + + tls1_PRF(s-s3-tmp.new_cipher-algorithm2, +label, label_len, +s-s3-client_random,SSL3_RANDOM_SIZE, +s-s3-server_random,SSL3_RANDOM_SIZE, +context, context_len, NULL, 0, +s-session-master_key, s-session-master_key_length, +out, tmp, olen); + } tls-exporter.patch Description: Binary data
Re: [openssl.org #1833] [PATCH] Abbreviated Renegotiations
Here is an up to date version of the patch for OpenSSL 1.0.1. This patch adds the new variable 'renegotiate' to the SSL struct. Until now the variable 'new_session' is used to indicate if a renegotiation is in progress AND if a new session has to be created, i.e. a full handshake has to be performed. This has the severe disadvantage that it is not possible to perform an abbreviated handshake and keep the current session. With this patch the new variable 'renegotiate' is used to determine whether a renegotiation is in progress and 'new_session' is set whether a new session should be negotiated or not. This allows to perform abbreviated handshakes and to do so, the function SSL_renegotiate_abbreviated(SSL *s) is added, while SSL_renegotiate(SSL *s) remains unchanged and still performs full handshakes. --- ssl/d1_clnt.c 26 Jan 2010 19:46:29 - 1.16.2.15 +++ ssl/d1_clnt.c 17 Jun 2010 12:47:40 - @@ -171,7 +171,7 @@ switch(s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; s-state=SSL_ST_CONNECT; s-ctx-stats.sess_connect_renegotiate++; /* break */ @@ -539,7 +539,7 @@ /* else do it later in ssl3_write */ s-init_num=0; - s-new_session=0; + s-renegotiate=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); if (s-hit) s-ctx-stats.sess_hit++; --- ssl/d1_pkt.c15 Jun 2010 17:25:13 - 1.27.2.25 +++ ssl/d1_pkt.c17 Jun 2010 12:47:40 - @@ -957,6 +957,7 @@ !(s-s3-flags SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) !s-s3-renegotiate) { + s-new_session = 1; ssl3_renegotiate(s); if (ssl3_renegotiate_check(s)) { @@ -1163,7 +1164,7 @@ #else s-state = s-server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; #endif - s-new_session=1; + s-renegotiate=1; } i=s-handshake_func(s); if (i 0) return(i); --- ssl/d1_srvr.c 1 Feb 2010 16:49:42 - 1.20.2.16 +++ ssl/d1_srvr.c 17 Jun 2010 12:47:40 - @@ -177,7 +177,7 @@ switch (s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; /* s-state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: @@ -299,7 +299,7 @@ case SSL3_ST_SW_SRVR_HELLO_A: case SSL3_ST_SW_SRVR_HELLO_B: - s-new_session = 2; + s-renegotiate = 2; dtls1_start_timer(s); ret=dtls1_send_server_hello(s); if (ret = 0) goto end; @@ -620,12 +620,12 @@ s-init_num=0; - if (s-new_session == 2) /* skipped if we just sent a HelloRequest */ + if (s-renegotiate == 2) /* skipped if we just sent a HelloRequest */ { /* actually not necessarily a 'new' session unless * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ - s-new_session=0; + s-renegotiate=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); --- ssl/s3_clnt.c 28 Feb 2010 00:24:24 - 1.129.2.15 +++ ssl/s3_clnt.c 17 Jun 2010 12:47:40 - @@ -207,7 +207,7 @@ switch(s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; s-state=SSL_ST_CONNECT; s-ctx-stats.sess_connect_renegotiate++; /* break */ @@ -546,7 +546,7 @@ /* else do it later in ssl3_write */ s-init_num=0; - s-new_session=0; + s-renegotiate=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); if (s-hit) s-ctx-stats.sess_hit++; --- ssl/s3_pkt.c25 Mar 2010 11:22:42 - 1.72.2.7 +++ ssl/s3_pkt.c17 Jun 2010 12:47:41 - @@ -1261,7 +1261,7 @@ #else s-state = s-server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; #endif - s-new_session=1; +
Re: [openssl.org #2230] [PATCH] DTLS reassembly
On Apr 26, 2010, at 12:44 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Mon Apr 26 11:04:29 2010]: You're right. The loop was written in the assumption that the control variable in the for loop can become -1. Since the variable type was changed to unsigned long, that didn't work anymore and my fix also didn't correct that. Here's an updated version. The initial patch was changed because it didn't compile without warnings with the stricter developer compiler options and my fix unfortunately broke it. Can you check there aren't any warnings with the revised patch? On OpenSSL 1.0.0 you can use the --strict-warnings option to Configure. After modifying several other files which threw warnings, I was able to compile it with the strict option. There is still a warning which can be fixed by adding casts the code in dtls1_reassemble() in line 662 to 666: RSMBLY_BITMASK_MARK(frag-reassembly, (long) msg_hdr-frag_off, (long) (msg_hdr-frag_off + frag_len)); RSMBLY_BITMASK_IS_COMPLETE(frag-reassembly, (long) msg_hdr-msg_len, is_complete); Regards, Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #2230] Resolved: [PATCH] DTLS reassembly
There is still a bug in the bitmask macros, reported by Daniel Mentz. While checking if the message is complete a read might occur beyond the bitmask array. This is fixed with this patch and the check is now also done backwards which should be faster usually. Regards, Robin --- ssl/d1_both.c 14 Apr 2010 00:41:01 - 1.14.2.20 +++ ssl/d1_both.c 21 Apr 2010 13:32:23 - @@ -132,15 +132,16 @@ } else { \ unsigned long ii; \ bitmask[((start) 3)] |= bitmask_start_values[((start) 7)]; \ - for (ii = (((start) 3) + 1); ii ((end) 3); ii++) bitmask[ii] = 0xff; \ - bitmask[((end) 3)] |= bitmask_end_values[((end) 7)]; \ + for (ii = (((start) 3) + 1); ii (((end - 1)) 3); ii++) bitmask[ii] = 0xff; \ + bitmask[(((end) - 1) 3)] |= bitmask_end_values[((end) 7)]; \ } } #define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ unsigned long ii; \ + OPENSSL_assert((msg_len) 0); \ is_complete = 1; \ - if (bitmask[((msg_len) 3)] != bitmask_end_values[((msg_len) 7)]) is_complete = 0; \ - if (is_complete) for (ii = 0; ii ((msg_len) 3); ii++) \ + if (bitmask[(((msg_len) - 1) 3)] != bitmask_end_values[((msg_len) 7)]) is_complete = 0; \ + if (is_complete) for (ii = (((msg_len) - 1) 3) - 1; ii 0 ; ii--) \ if (bitmask[ii] != 0xff) { is_complete = 0; break; } } #if 0 @@ -152,7 +153,7 @@ #endif static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; -static unsigned char bitmask_end_values[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; +static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; /* XDTLS: figure out the right values */ static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; dtls-bitmask.patch Description: Binary data
Re: [openssl.org #2233] [BUG] Checkin #19560 causes an DTLS bug
In my opinion the patch is also not necessary, because dtls1_buffer_message() requires a pointer to some 64 bit data to be used as the priority for the queue. However, s-s3-rrec.seq_num already is a pointer, since it is an array. Using (s-s3-rrec.seq_num) usually returns the same value, i.e. the pointer to the first value of the array, but I'm not sure if that's always the case. Regards, Robin On Apr 14, 2010, at 2:20 AM, Stephen Henson via RT wrote: Patch has already been reverted. Presumably the 0.9.8 one (Checkin #19561) is OK? Steve. -- Dr Stephen N. Henson. OpenSSL project core developer. Commercial tech support now available see: http://www.openssl.org __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #2230] [PATCH] DTLS reassembly
On Apr 14, 2010, at 2:20 PM, Stephen Henson via RT wrote: This patch appears to be broken on OpenSSL 0.9.8 it gives warnings: d1_both.c: In function ‘dtls1_reassemble_fragment’: d1_both.c:623: error: passing argument 2 of ‘pqueue_find’ makes integer from pointer without a cast ../include/openssl/pqueue.h:89: note: expected ‘long unsigned int’ but argument is of type ‘unsigned char *’ d1_both.c:679: error: passing argument 1 of ‘pitem_new’ makes integer from pointer without a cast ../include/openssl/pqueue.h:80: note: expected ‘long unsigned int’ but argument is of Sorry, my bad. I forgot the different pqueue priorities in 0.9.8... Here is a patch to fix that. Regards, Robin --- ssl/d1_both.c 14 Apr 2010 00:41:25 - 1.4.2.27 +++ ssl/d1_both.c 14 Apr 2010 12:48:59 - @@ -599,7 +599,7 @@ hm_fragment *frag = NULL; pitem *item = NULL; int i = -1, is_complete; - unsigned char seq64be[8]; + PQ_64BIT seq64; unsigned long frag_len = msg_hdr-frag_len, max_len; if ((msg_hdr-frag_off+frag_len) msg_hdr-msg_len) @@ -617,10 +617,10 @@ goto err; /* Try to find item in queue */ - memset(seq64be,0,sizeof(seq64be)); - seq64be[6] = (unsigned char) (msg_hdr-seq8); - seq64be[7] = (unsigned char) msg_hdr-seq; - item = pqueue_find(s-d1-buffered_messages, seq64be); + pq_64bit_init(seq64); + pq_64bit_assign_word(seq64, msg_hdr-seq); + item = pqueue_find(s-d1-buffered_messages, seq64); + pq_64bit_free(seq64); if (item == NULL) { @@ -672,11 +672,11 @@ if (item == NULL) { - memset(seq64be,0,sizeof(seq64be)); - seq64be[6] = (unsigned char)(msg_hdr-seq8); - seq64be[7] = (unsigned char)(msg_hdr-seq); + pq_64bit_init(seq64); + pq_64bit_assign_word(seq64, msg_hdr-seq); + item = pitem_new(seq64, frag); + pq_64bit_free(seq64); - item = pitem_new(seq64be, frag); if (item == NULL) { goto err; dtls-reassembly-bug-bug-0.9.8.patch Description: Binary data
Re: [openssl.org #2233] [BUG] Checkin #19560 causes an DTLS bug
On 14.04.2010, at 15:35, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Wed Apr 14 12:08:30 2010]: In my opinion the patch is also not necessary, because dtls1_buffer_message() requires a pointer to some 64 bit data to be used as the priority for the queue. However, s-s3-rrec.seq_num already is a pointer, since it is an array. Using (s-s3- rrec.seq_num) usually returns the same value, i.e. the pointer to the first value of the array, but I'm not sure if that's always the case. Err it is of type PQ_64BIT in 0.9.8 and not an array. Yes, but the dtls1_buffer_message() function uses a PQ_64BIT pointer to pass a PQ_64BIT struct, which is accessed directly. However, passed is just the pointer to the array which holds the sequence number. This is not very elegant but seems to work. The patch recently submitted only changed s-s3-rrec.seq_num to (s-s3-rrec.seq_num) when passing it to the buffering function. Since seq_num is an array and therefore interpreted as a pointer to the first element this was ok. It was simply used as if it were a pointer to an PQ_64BIT struct. Changing it to (s-s3-rrec.seq_num) only results in passing the very same pointer to the buffering function. This is because the compiler also interprets this as a pointer to the first element of the array. However, I don't know if this is the case with every compiler because we didn't find this construct in the C specification, i.e. referencing an array pointer. I expected it to be the pointer to the pointer to the first element of the a rray, which it is not for some reason. So I still recommend not to change it and revert the patch for 0.9.8 as well to be sure it keeps working or change it to create a real PQ_64BIT struct which is then passed to the buffering function. Regards, Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #2233] [BUG] Checkin #19560 causes an DTLS bug
The recent checkin #19560 causes a bug by changing the third parameter from rr-seq_num to rr-seq_num in dtls_buffer_record() calls in d1_pkt.c. However, this is not correct because rr-seq_num is an array, see ssl3.h: unsigned char seq_num[8]; So it was referenced correctly, the change was not necessary and has to be reverted. Regards, Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #2227] [PATCH] Define OPENSSL_SYS_BSD
This patch adds an OPENSSL_SYS_BSD define, to consider BSD platforms when implementing platform-dependent functionality. This is necessary for future DTLS features. --- Configure 19 Jan 2010 21:40:54 - 1.621.2.34 +++ Configure 8 Apr 2010 10:39:52 - @@ -381,19 +382,19 @@ linux-alpha+bwx-ccc,ccc:-fast -readonly_strings -DL_ENDIAN -DTERMIO::-D_REENTRANT:::SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL:${alpha_asm}, *BSD [do see comment about ${BSDthreads} above!] -BSD-generic32,gcc:-DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -BSD-x86, gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -BSD-x86-elf, gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -debug-BSD-x86-elf, gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall -g::${BSDthreads}:::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -BSD-sparcv8, gcc:-DB_ENDIAN -DTERMIOS -O3 -mv8 -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${sparcv8_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-generic32,gcc:-DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:BSD::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-x86, gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:BSD::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_asm}:a.out:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-x86-elf, gcc:-DL_ENDIAN -DTERMIOS -O3 -fomit-frame-pointer -Wall::${BSDthreads}:BSD::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +debug-BSD-x86-elf, gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall -g::${BSDthreads}:BSD::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-sparcv8, gcc:-DB_ENDIAN -DTERMIOS -O3 -mv8 -Wall::${BSDthreads}:BSD::BN_LLONG RC2_CHAR RC4_INDEX DES_INT DES_UNROLL:${sparcv8_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -BSD-generic64,gcc:-DTERMIOS -O3 -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-generic64,gcc:-DTERMIOS -O3 -Wall::${BSDthreads}:BSD::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${no_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), # -DMD32_REG_T=int doesn't actually belong in sparc64 target, it # simply *happens* to work around a compiler bug in gcc 3.3.3, # triggered by RIPEMD160 code. -BSD-sparc64, gcc:-DB_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::BN_LLONG RC2_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC2 BF_PTR:${sparcv9_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -BSD-ia64,gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), -BSD-x86_64, gcc:-DL_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-sparc64, gcc:-DB_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:BSD::BN_LLONG RC2_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC2 BF_PTR:${sparcv9_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-ia64,gcc:-DL_ENDIAN -DTERMIOS -O3 -Wall::${BSDthreads}:BSD::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_UNROLL DES_INT:${ia64_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), +BSD-x86_64, gcc:-DL_ENDIAN -DTERMIOS -O3 -DMD32_REG_T=int -Wall::${BSDthreads}:BSD::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), bsdi-elf-gcc, gcc:-DPERL5 -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall::(unknown)::-ldl:BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}:dlfcn:bsd-gcc-shared:-fPIC::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR), Index: e_os2.h === RCS file: /v/openssl/cvs/openssl/e_os2.h,v retrieving revision 1.33.2.1 diff -u -r1.33.2.1 e_os2.h --- e_os2.h 16 Apr 2009 17:22:46 - 1.33.2.1 +++ e_os2.h 8 Apr 2010 10:39:52 - @@ -162,6 +162,9 @@ # if defined(linux) || defined(__linux__) || defined(OPENSSL_SYSNAME_LINUX) # define
[openssl.org #2228] [PATCH] DTLS MAC validation fails for buffered messages
Whenever handshake messages are buffered because they arrived reordered and already belong to the next epoch, the MAC validation fails when the messages are finally processed because the sequence number is not restored and instead 0 is always used. This is fixed with setting the s-s3-read_sequence variable when retrieving buffered messages. --- ssl/d1_pkt.c6 Apr 2010 12:44:55 - 1.27.2.20 +++ ssl/d1_pkt.c8 Apr 2010 10:43:29 - @@ -196,6 +196,9 @@ s-packet_length = rdata-packet_length; memcpy((s-s3-rbuf), (rdata-rbuf), sizeof(SSL3_BUFFER)); memcpy((s-s3-rrec), (rdata-rrec), sizeof(SSL3_RECORD)); + + /* Set proper sequence number for mac calculation */ + memcpy((s-s3-read_sequence[2]), (rdata-packet[5]), 6); return(1); } dtls-badmac-bug-0.9.8.patch Description: Binary data dtls-badmac-bug-1.0.0.patch Description: Binary data
[openssl.org #2229] [PATCH] DTLS drops connection after MAC validation or decryption failed
DTLS drops the connection with a BAD_RECORD alert whenever validation of the MAC or decryption failed. This is ok with the specification as an optional behavior but is also an easy target for a potential attack to drop the connection. An attacker only has to send random data to cause the decryption to fail and the connection is closed. So DTLS should rather silently discard those messages and continue the connection. --- ssl/d1_pkt.c6 Apr 2010 12:44:55 - 1.27.2.20 +++ ssl/d1_pkt.c8 Apr 2010 10:44:09 - @@ -414,7 +425,7 @@ goto err; /* otherwise enc_err == -1 */ - goto decryption_failed_or_bad_record_mac; + goto err; } #ifdef TLS_DEBUG @@ -444,7 +455,7 @@ SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); goto f_err; #else - goto decryption_failed_or_bad_record_mac; + goto err; #endif } /* check the MAC for rr-input (it's in mac_size bytes at the tail) */ @@ -455,14 +466,14 @@ SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT); goto f_err; #else - goto decryption_failed_or_bad_record_mac; + goto err; #endif } rr-length-=mac_size; i=s-method-ssl3_enc-mac(s,md,0); if (i 0 || memcmp(md,(rr-data[rr-length]),mac_size) != 0) { - goto decryption_failed_or_bad_record_mac; + goto err; } } @@ -504,14 +515,6 @@ dtls1_record_bitmap_update(s, (s-d1-bitmap));/* Mark receipt of record. */ return(1); -decryption_failed_or_bad_record_mac: - /* Separate 'decryption_failed' alert was introduced with TLS 1.0, -* SSL 3.0 only has 'bad_record_mac'. But unless a decryption -* failure is directly visible from the ciphertext anyway, -* we should not reveal which kind of error occured -- this -* might become visible to an attacker (e.g. via logfile) */ - al=SSL_AD_BAD_RECORD_MAC; - SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: @@ -544,8 +547,7 @@ /* The epoch may have changed. If so, process all the * pending records. This is a non-blocking operation. */ - if ( ! dtls1_process_buffered_records(s)) -return 0; + dtls1_process_buffered_records(s); /* if we're renegotiating, then there may be buffered records */ if (dtls1_get_processed_record(s)) @@ -680,8 +690,12 @@ goto again; } - if ( ! dtls1_process_record(s)) - return(0); + if (!dtls1_process_record(s)) + { + rr-length = 0; + s-packet_length = 0; /* dump this record */ + goto again; /* get another record */ + } dtls1_clear_timeouts(s); /* done waiting */ return(1); dtls-badmsg-alert-bug-0.9.8.patch Description: Binary data dtls-badmsg-alert-bug-1.0.0.patch Description: Binary data
[openssl.org #2230] [PATCH] DTLS reassembly
The reassembly for fragmented DTLS handshake messages only works if the fragments don't overlap, aren't reordered and haven't been retransmitted. This patch fixes this and allows the reassembly of messages regardless of retransmissions, losses, reordering or even the mixture of fragments of different messages. Incomplete messages now have a bitmask to keep track of the fragments and are buffered until completed. This allows the reassembly of fragments in random order and from multiple messages at a time, instead of reassembling only the message currently being processed and dropping everything but the expected fragment. Also fixed is the issue mentioned in #2221 that zero length fragments aren't buffered. --- ssl/d1_both.c 24 Mar 2010 23:16:49 - 1.14.2.18 +++ ssl/d1_both.c 8 Apr 2010 10:44:42 - @@ -123,6 +123,36 @@ #include openssl/evp.h #include openssl/x509.h +#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) + +#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ + if ((end) - (start) = 8) { \ + int ii; \ + for (ii = (start); ii (end); ii++) bitmask[((ii) 3)] |= (1 ((ii) 7)); \ + } else { \ + int ii; \ + bitmask[((start) 3)] |= bitmask_start_values[((start) 7)]; \ + for (ii = (((start) 3) + 1); ii ((end) 3); ii++) bitmask[ii] = 0xff; \ + bitmask[((end) 3)] |= bitmask_end_values[((end) 7)]; \ + } } + +#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ + int ii; \ + is_complete = 1; \ + if (bitmask[((msg_len) 3)] != bitmask_end_values[((msg_len) 7)]) is_complete = 0; \ + if (is_complete) for (ii = 0; ii ((msg_len) 3); ii++) \ + if (bitmask[ii] != 0xff) { is_complete = 0; break; } } + +#if 0 +#define RSMBLY_BITMASK_PRINT(bitmask, msg_len) { \ + int ii; \ + printf(bitmask: ); for (ii = 0; ii (msg_len); ii++) \ + printf(%d , (bitmask[ii 3] (1 (ii 7))) (ii 7)); \ + printf(\n); } +#endif + +static unsigned char bitmask_start_values[] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; +static unsigned char bitmask_end_values[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}; /* XDTLS: figure out the right values */ static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; @@ -140,10 +170,11 @@ long max, int *ok); static hm_fragment * -dtls1_hm_fragment_new(unsigned long frag_len) +dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) { hm_fragment *frag = NULL; unsigned char *buf = NULL; + unsigned char *bitmask = NULL; frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment)); if ( frag == NULL) @@ -162,6 +193,21 @@ /* zero length fragment gets zero frag-fragment */ frag-fragment = buf; + /* Initialize reassembly bitmask if necessary */ + if (reassembly) + { + bitmask = (unsigned char *)OPENSSL_malloc(RSMBLY_BITMASK_SIZE(frag_len)); + if (bitmask == NULL) + { + if (buf != NULL) OPENSSL_free(buf); + OPENSSL_free(frag); + return NULL; + } + memset(bitmask, 0, RSMBLY_BITMASK_SIZE(frag_len)); + } + + frag-reassembly = bitmask; + return frag; } @@ -169,6 +215,7 @@ dtls1_hm_fragment_free(hm_fragment *frag) { if (frag-fragment) OPENSSL_free(frag-fragment); + if (frag-reassembly) OPENSSL_free(frag-reassembly); OPENSSL_free(frag); } @@ -363,6 +410,8 @@ { int i, al; struct hm_header_st *msg_hdr; + unsigned char *p; + unsigned long msg_len; /* s3-tmp is used to store messages that are unexpected, caused * by the absence of an optional handshake message */ @@ -382,77 +431,55 @@ } msg_hdr = s-d1-r_msg_hdr; - do - { - if ( msg_hdr-frag_off == 0) - { - /* s-d1-r_message_header.msg_len = 0; */ - memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); - } + memset(msg_hdr, 0x00, sizeof(struct hm_header_st)); - i = dtls1_get_message_fragment(s, st1, stn, max, ok); - if ( i == DTLS1_HM_BAD_FRAGMENT || - i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ - continue; - else if ( i = 0 !*ok) - return i; +again: +
[openssl.org #2223] [PATCH] DTLS timeout bug
To handle handshake message timeouts properly, DTLS sets the socket timeouts according to the currently remaining time until the next timeout occurs. However, in some cases this doesn't work because the operating system returns the socket call a few milliseconds before the DTLS timer expires. To solve this, the remaining time until timeout is set to 0 if it is less than 15 ms. Index: ssl/d1_lib.c === RCS file: /v/openssl/cvs/openssl/ssl/d1_lib.c,v retrieving revision 1.8.2.12 diff -u -r1.8.2.12 d1_lib.c --- ssl/d1_lib.c8 Dec 2009 11:38:17 - 1.8.2.12 +++ ssl/d1_lib.c6 Apr 2010 07:43:33 - @@ -283,6 +283,16 @@ timeleft-tv_usec += 100; } + /* If remaining time is less than 15 ms, set it to 0 +* to prevent issues because of small devergences with +* socket timeouts. +*/ + if (timeleft-tv_sec == 0 timeleft-tv_usec 15) + { + memset(timeleft, 0, sizeof(struct timeval)); + } + + return timeleft; } dtls-timeout-bug-1.0.0.patch Description: Binary data dtls-timeout-bug-0.9.8.patch Description: Binary data
Re: [openssl.org #2223] [PATCH] DTLS timeout bug
On Apr 6, 2010, at 10:56 AM, Daniel Mentz wrote: Robin Seggelmann via RT wrote: To handle handshake message timeouts properly, DTLS sets the socket timeouts according to the currently remaining time until the next timeout occurs. However, in some cases this doesn't work because the operating system returns the socket call a few milliseconds before the DTLS timer expires. To solve this, the remaining time until timeout is set to 0 if it is less than 15 ms. +if (timeleft-tv_sec == 0 timeleft-tv_usec 15) tv_usec stores microseconds not milliseconds. So I suggest to use if (timeleft-tv_sec == 0 timeleft-tv_usec 15000) Yes, I obviously confused that...it's 15000 of course. __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #2219] [PATCH] DTLS buffering bug causing crash
Application data arriving between ChangeCipherSpec and Finished is buffered and processed after the handshake has been completed. While calling dtls1_buffer_record() a NULL-pointer was passed as priority. This causes a crash when multiple messages have to be buffered. With this patch the sequence number of the corresponding record is used as the priority as intended. Thanks to Daniel Mentz for finding this bug. --- ssl/d1_pkt.c4 Oct 2009 16:52:35 - 1.27.2.18 +++ ssl/d1_pkt.c3 Apr 2010 10:49:07 - @@ -809,7 +809,7 @@ * buffer the application data for later processing rather * than dropping the connection. */ - dtls1_buffer_record(s, (s-d1-buffered_app_data), 0); + dtls1_buffer_record(s, (s-d1-buffered_app_data), rr-seq_num); rr-length = 0; goto start; } dtls-buffer-bug-1.0.0.patch Description: Binary data dtls-buffer-bug-0.9.8.patch Description: Binary data
Re: [openssl.org #2218] [Bug report] DTLS: dtls1_get_record() uses unauthenticated sequence number
This patch addresses this issue. --- ssl/d1_pkt.c4 Oct 2009 16:52:35 - 1.27.2.18 +++ ssl/d1_pkt.c4 Apr 2010 09:10:09 - @@ -667,14 +667,14 @@ if (rr-length == 0) goto again; /* If this record is from the next epoch (either HM or ALERT), -* buffer it since it cannot be processed at this time. Records -* from the next epoch are marked as received even though they -* are not processed, so as to prevent any potential resource -* DoS attack */ +* and a handshake is currently in progress, buffer it since it +* cannot be processed at this time. */ if (is_next_epoch) { - dtls1_record_bitmap_update(s, bitmap); - dtls1_buffer_record(s, (s-d1-unprocessed_rcds), rr-seq_num); + if (SSL_in_init(s) || s-in_handshake) + { + dtls1_buffer_record(s, (s-d1-unprocessed_rcds), rr-seq_num); + } rr-length = 0; s-packet_length = 0; goto again; Regards, Robin On Apr 3, 2010, at 2:19 PM, Daniel Mentz via RT wrote: d1_pkt.c:dtls1_get_record() processes DTLS records which it gets from the wire. At the same time, this function performs replay protection: It memorizes the (explicit) sequence numbers of the records and drops records that have already been processed. The sequence numbers of the processed records are saved in a sliding bitmap window. The corresponding bit in the window is set to 1, if a specific sequence number is processed. The key point is that the MAC of the record is usually verified *before* the bitmap of sequence numbers is updated. This requires the receiving end to be in possession of the symmetric key used for integrity control. With every renegotiation, the keys are renewed and a new epoch begins. Due to reordering on the network, it may happen that a record from a future epoch arrives during renegotiation. Because the keying material is not yet available, the integrity of these records can not be verified. The aspect I'm complaining about is that OpenSSL updates the record bitmap *without* prior verification of the integrity of the record *iff* the record is from a future epoch. Here's the code: /* If this record is from the next epoch (either HM or ALERT), * buffer it since it cannot be processed at this time. Records * from the next epoch are marked as received even though they * are not processed, so as to prevent any potential resource * DoS attack */ if (is_next_epoch) { dtls1_record_bitmap_update(s, bitmap); dtls1_buffer_record(s, (s-d1-unprocessed_rcds), rr-seq_num); rr-length = 0; s-packet_length = 0; goto again; } In my opinion, there's no potential for resource DoS attacks because dtls1_buffer_record() limits the number of buffered records to 100. However, as the code stands today, there is a potential for a DoS attack. An attacker might guess the source and destination UDP port as well as the number of the next epoch. They then send a faked DTLS record with a high sequence number, say n. As a result, OpenSSL moves forward the bitmap window and will drop any future record carrying a sequence number that is smaller than (n-64) i.e. which lies outside the window. I suggest to improve on that situation by doing the following: - Do *not* update the record bitmap if the record belongs to the next epoch. As a result, two records carrying the same sequence number may be buffered at the same time. However, one of these records might be invalid or faked. - Buffer records from the next epoch only if a re-handshake is currently in progress. Does that make sense? Please let me know your opinions. -Daniel __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org dtls-replay-bug-1.0.0.patch Description: Binary data dtls-replay-bug-0.9.8.patch Description: Binary data
[openssl.org #2159] [PATCH] Fix for #1949 broke DTLS
In the fix for #1949 was a typo which breaks DTLS and results in an infinite loop. The state SSL3_ST_CW_FLUSH is for the client and the server needs SSL3_ST_SW_FLUSH. Here's a patch to fix that: --- ssl/d1_srvr.c 26 Jan 2010 19:40:36 - 1.2.2.27 +++ ssl/d1_srvr.c 31 Jan 2010 18:50:09 - @@ -440,7 +440,7 @@ s-init_num=0; break; - case SSL3_ST_CW_FLUSH: + case SSL3_ST_SW_FLUSH: s-rwstate=SSL_WRITING; if (BIO_flush(s-wbio) = 0) { Regards, Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #2160] [PATCH] DTLS Sessionticket extension bugs
The Sessionticket extension doesn't work with DTLS. The NewSessionTicket message of the server is truncated because of a wrong calculation of the length and the server is also unable to parse the ticket attached to a ClientHello because DTLS is considered as an unknown protocol version. Regards, Robin Index: ssl/d1_srvr.c === RCS file: /v/openssl/cvs/openssl/ssl/d1_srvr.c,v retrieving revision 1.20.2.14 diff -u -r1.20.2.14 d1_srvr.c --- ssl/d1_srvr.c 26 Jan 2010 19:46:29 - 1.20.2.14 +++ ssl/d1_srvr.c 31 Jan 2010 18:09:17 - @@ -1525,9 +1667,10 @@ p += hlen; /* Now write out lengths: p points to end of data written */ /* Total length */ - len = p - (unsigned char *)(s-init_buf-data[DTLS1_HM_HEADER_LENGTH]); + len = p - (unsigned char *)(s-init_buf-data); + /* Ticket length */ p=(unsigned char *)(s-init_buf-data[DTLS1_HM_HEADER_LENGTH]) + 4; - s2n(len - 18, p); /* Ticket length */ + s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p); /* number of bytes to write */ s-init_num= len; Index: ssl/ssl_asn1.c === RCS file: /v/openssl/cvs/openssl/ssl/ssl_asn1.c,v retrieving revision 1.36.2.5 diff -u -r1.36.2.5 ssl_asn1.c --- ssl/ssl_asn1.c 30 Oct 2009 14:06:18 - 1.36.2.5 +++ ssl/ssl_asn1.c 31 Jan 2010 18:09:20 - @@ -394,7 +394,7 @@ ((unsigned long)os.data[1] 8L)| (unsigned long)os.data[2]; } - else if ((ssl_version8) == SSL3_VERSION_MAJOR) + else if ((ssl_version8) = SSL3_VERSION_MAJOR) { if (os.length != 2) { Index: ssl/ssl_sess.c === RCS file: /v/openssl/cvs/openssl/ssl/ssl_sess.c,v retrieving revision 1.74.2.1 diff -u -r1.74.2.1 ssl_sess.c --- ssl/ssl_sess.c 19 Apr 2009 18:03:13 - 1.74.2.1 +++ ssl/ssl_sess.c 31 Jan 2010 18:09:22 - @@ -538,7 +538,7 @@ p=buf; l=ret-cipher_id; l2n(l,p); - if ((ret-ssl_version8) == SSL3_VERSION_MAJOR) + if ((ret-ssl_version8) = SSL3_VERSION_MAJOR) ret-cipher=ssl_get_cipher_by_char(s,(buf[2])); else ret-cipher=ssl_get_cipher_by_char(s,(buf[1])); dtls-sessionticket-bug-1.0.0.patch Description: Binary data dtls-sessionticket-bug-0.9.8.patch Description: Binary data
[openssl.org #2114] [PATCH] DTLS BIO write fails with Invalid Argument with IPv4
Since IPv6 support was added, in dgram_write() the size of data-peer cannot be used for sendto() anymore. The union has the size of sockaddr_in6 when IPv6 is enabled and therefore sendto() always fails with Invalid Argument when only IPv4 is used. It should be either the size of sockaddr_in or sockaddr_in6, depending on the protocol. Regards, Robin Index: crypto/bio/bss_dgram.c === RCS file: /v/openssl/cvs/openssl/crypto/bio/bss_dgram.c,v retrieving revision 1.7.2.21 diff -u -r1.7.2.21 bss_dgram.c --- crypto/bio/bss_dgram.c 26 Nov 2009 20:56:05 - 1.7.2.21 +++ crypto/bio/bss_dgram.c 27 Nov 2009 14:29:03 - @@ -329,16 +329,22 @@ static int dgram_write(BIO *b, const char *in, int inl) { int ret; + socklen_t peerlen; bio_dgram_data *data = (bio_dgram_data *)b-ptr; clear_socket_error(); + if (data-peer.sa.sa_family == AF_INET6) + peerlen = sizeof(data-peer.sa_in6); + else + peerlen = sizeof(data-peer.sa_in); + if ( data-connected ) ret=writesocket(b-num,in,inl); else #if defined(NETWARE_CLIB) defined(NETWARE_BSDSOCK) - ret=sendto(b-num, (char *)in, inl, 0, data-peer.sa, sizeof(data-peer)); + ret=sendto(b-num, (char *)in, inl, 0, data-peer.sa, peerlen); #else - ret=sendto(b-num, in, inl, 0, data-peer.sa, sizeof(data-peer)); + ret=sendto(b-num, in, inl, 0, data-peer.sa, peerlen); #endif BIO_clear_retry_flags(b); peerlen.patch Description: Binary data
[openssl.org #2115] [PATCH] Regenegotiaton extension for DTLS
This patch adds the renegotiaton extension for DTLS and also fixes a segmentation fault occuring on server-side when the ClientHello could not be processed and therefore no cipher is set. Regards, Robin --- ssl/d1_both.c 2 Nov 2009 13:37:17 - 1.14.2.16 +++ ssl/d1_both.c 27 Nov 2009 12:54:08 - @@ -764,6 +764,24 @@ p+=i; l=i; + /* Copy the finished so we can use it for +* renegotiation checks +*/ + if(s-type == SSL_ST_CONNECT) + { + OPENSSL_assert(i = EVP_MAX_MD_SIZE); + memcpy(s-s3-previous_client_finished, + s-s3-tmp.finish_md, i); + s-s3-previous_client_finished_len=i; + } + else + { + OPENSSL_assert(i = EVP_MAX_MD_SIZE); + memcpy(s-s3-previous_server_finished, + s-s3-tmp.finish_md, i); + s-s3-previous_server_finished_len=i; + } + #ifdef OPENSSL_SYS_WIN16 /* MSVC 1.5 does not clear the top bytes of the word unless * I do this. --- ssl/d1_clnt.c 24 Jul 2009 11:52:32 - 1.16.2.11 +++ ssl/d1_clnt.c 27 Nov 2009 12:54:08 - @@ -635,7 +635,15 @@ *(p++)=comp-id; } *(p++)=0; /* Add the NULL method */ - + +#ifndef OPENSSL_NO_TLSEXT + if ((p = ssl_add_clienthello_dtlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); + goto err; + } +#endif + l=(p-d); d=buf; --- ssl/d1_lib.c9 Sep 2009 17:05:42 - 1.8.2.10 +++ ssl/d1_lib.c27 Nov 2009 12:54:08 - @@ -382,3 +382,194 @@ (void) BIO_dgram_get_peer(SSL_get_rbio(s), client); return 1; } + +#ifndef OPENSSL_NO_TLSEXT +unsigned char *ssl_add_clienthello_dtlsext(SSL *s, unsigned char *p, unsigned char *limit) + { + int extdatalen = 0; + unsigned char *ret = p; + int el; + + ret+=2; + + if (ret=limit) return NULL; /* this really never occurs, but ... */ + + /* Renegotiate extension */ + if(!ssl_add_clienthello_renegotiate_ext(s, 0, el, 0)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + if((limit - p - 4 - el) 0) return NULL; + + s2n(TLSEXT_TYPE_renegotiate,ret); + s2n(el,ret); + + if(!ssl_add_clienthello_renegotiate_ext(s, ret, el, el)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + + if ((extdatalen = ret-p-2)== 0) + return p; + + s2n(extdatalen,p); + + return ret; + } + +int ssl_parse_clienthello_dtlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) + { + unsigned short type; + unsigned short size; + unsigned short len; + unsigned char *data = *p; + int renegotiate_seen = 0; + + if (data = (d+n-2)) + { + if (s-new_session +!(s-ctx-options SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + /* We should always see one extension: the renegotiate extension */ + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + return 0; + } + return 1; + } + n2s(data,len); + + if (data (d+n-len)) + return 1; + + while (data = (d+n-4)) + { + n2s(data,type); + n2s(data,size); + + if (data+size (d+n)) + return 1; + + if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } + + data+=size; + } + + if (s-new_session !renegotiate_seen +!(s-ctx-options SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) + { + *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */ + SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } + + *p = data; + return 1; + } + +unsigned
[openssl.org #2110] [PATCH] Changed behavior of BIO_CTRL_DGRAM_GET_PEER breaks DTLS apps
The latest changes of bss_dgram.c affected the behavior of BIO_CTRL_DGRAM_GET_PEER, which now requires to preset the expected IP type before requesting the current peer. This was done to prevent that the user always has to use sockaddr_storage, even if he doesn't use IPv6 at all. The default is to return the length of a sockaddr structure which is always wrong, therefore existing DTLS applications which rely on this function for cookie generation, such as s_server/s_client, don't work anymore. Additionally, this requires that the user has to guess which IP type the peer has. This can be difficult, e.g. if the client uses IPv4 to connect to an IPv6 socket and a system returns AF_INET then. A better solution is to use the num parameter of BIO_ctrl() to limit the length if desired. When num is 0, the function returns either sockaddr_in or sockaddr_in6, depending on what's necessary, so the user should use sockaddr_storage. If the user knows that he only uses IPv4 and doesn't want to use sockaddr_storage, he can limit the copied length by setting the num parameter to sizeof(struct sockaddr_in). He can then check if the family variable of the passed structure is really AF_INET and try again with sockaddr_storage or handle it as an error in case it's not. Index: crypto/bio/bss_dgram.c === RCS file: /v/openssl/cvs/openssl/crypto/bio/bss_dgram.c,v retrieving revision 1.7.2.20 diff -u -r1.7.2.20 bss_dgram.c --- crypto/bio/bss_dgram.c 22 Nov 2009 12:24:43 - 1.7.2.20 +++ crypto/bio/bss_dgram.c 26 Nov 2009 10:20:24 - @@ -566,18 +970,24 @@ break; case BIO_CTRL_DGRAM_GET_PEER: to = (struct sockaddr *) ptr; - switch (to-sa_family) + switch (data-peer.sa.sa_family) { case AF_INET: - memcpy(to,data-peer,(ret=sizeof(data-peer.sa_in))); + if (num == 0 || num sizeof(data-peer.sa_in)) + num = sizeof(data-peer.sa_in); + memcpy(to,data-peer,(ret=num)); break; #if OPENSSL_USE_IPV6 case AF_INET6: - memcpy(to,data-peer,(ret=sizeof(data-peer.sa_in6))); + if (num == 0 || num sizeof(data-peer.sa_in6)) + num = sizeof(data-peer.sa_in6); + memcpy(to,data-peer,(ret=num)); break; #endif default: - memcpy(to,data-peer,(ret=sizeof(data-peer.sa))); + if (num == 0 || num sizeof(data-peer.sa)) + num = sizeof(data-peer.sa); + memcpy(to,data-peer,(ret=num)); break; } break; get_peer.patch Description: Binary data
[openssl.org #2109] Typo in x86_64-xlate.pl since check-in 18896
In check-in 18896 for openssl/crypto/perlasm/x86_64-xlate.pl in branch OpenSSL_1_0_0-stable was a typo: - # in $self-{label} - $self-{label} =~ s/(?![0-9a-f])(0[x0-9a-f]+)/oct($1)/egi; + # in $self-{label}, new gas requires sign extentions... + user integer; + $self-{label} =~ s/(?![0-9a-f])(0[x0-9a-f]+)/oct($1)3232/egi; It has to be use integer, otherwise the compiler nags. Regards, Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #2089] [PATCH] DTLS Fragment size bug
DTLS fragmentation doesn't consider the additional data required with using encryption, so the packet size then exceeds the MTU when fragmentation is performed. This patch subtracts the size of the mac and the additional encryption bytes of the maximum possible length for a fragment, if necessary. Thanks to Daniel Mentz for finding this bug. Regards, Robin --- ssl/d1_both.c 1 Oct 2009 00:03:50 - 1.14.2.15 +++ ssl/d1_both.c 30 Oct 2009 15:16:40 - @@ -177,7 +177,7 @@ { int ret; int curr_mtu; - unsigned int len, frag_off; + unsigned int len, frag_off, mac_size, blocksize; /* AHA! Figure out the MTU, and stick to the right size */ if ( ! (SSL_get_options(s) SSL_OP_NO_QUERY_MTU)) @@ -225,11 +225,22 @@ OPENSSL_assert(s-init_num == (int)s-d1-w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); + if (s-write_hash) + mac_size = EVP_MD_CTX_size(s-write_hash); + else + mac_size = 0; + + if (s-enc_write_ctx + (EVP_CIPHER_mode( s-enc_write_ctx-cipher) EVP_CIPH_CBC_MODE)) + blocksize = 2 * EVP_CIPHER_block_size(s-enc_write_ctx-cipher); + else + blocksize = 0; + frag_off = 0; while( s-init_num) { curr_mtu = s-d1-mtu - BIO_wpending(SSL_get_wbio(s)) - - DTLS1_RT_HEADER_LENGTH; + DTLS1_RT_HEADER_LENGTH - mac_size - blocksize; if ( curr_mtu = DTLS1_HM_HEADER_LENGTH) { @@ -237,7 +248,8 @@ ret = BIO_flush(SSL_get_wbio(s)); if ( ret = 0) return ret; - curr_mtu = s-d1-mtu - DTLS1_RT_HEADER_LENGTH; + curr_mtu = s-d1-mtu - DTLS1_RT_HEADER_LENGTH - + mac_size - blocksize; } if ( s-init_num curr_mtu) dtls-mtu-fragment-bug.patch Description: Binary data
Re: [openssl.org #2033] [PATCH] DTLS Listen
On Sep 8, 2009, at 8:26 PM, Robin Seggelmann via RT wrote: Am 08.09.2009 um 19:59 schrieb Stephen Henson via RT: [seggelm...@fh-muenster.de - Tue Sep 08 18:31:29 2009]: That's just a simple example. If you use blocking sockets, it doesn't return until a ClientHello with a valid cookie has been received (returns 1) or an error occurred (returns 0). If you use non- blocking sockets, it always returns 0 on EAGAIN, so you can use select() to only call it when there's data to process and it will return as soon as there is nothing left. Is there some reason you only return 0, 1 from the ctrl? I'm wondering why you can't just return the return value of SSL_accept() (is = 0) for consistency with similar calls. Well, I was thinking of just making a difference between valid ClientHello received and everything else. Just returning the return value of SSL_accept() would be ok in case it's = 0. Otherwise it returns 2 to differentiate the premature handshake routine exit because of listen from the regular handshake ending. So, also for consitency, the listen call should not return 2 but 1 then. However, when using listen the handhsake routine should never exit with 1, indicating a successful handshake. I'll submit an updated version of the patch tomorrow. Here's an updated version of the patch: --- ssl/d1_lib.c12 Aug 2009 17:30:36 - 1.16 +++ ssl/d1_lib.c3 Sep 2009 09:59:22 - @@ -203,6 +203,9 @@ case DTLS_CTRL_HANDLE_TIMEOUT: ret = dtls1_handle_timeout(s); break; + case DTLS_CTRL_LISTEN: + ret = dtls1_listen(s, parg); + break; default: ret = ssl3_ctrl(s, cmd, larg, parg); @@ -364,3 +367,17 @@ gettimeofday(t, NULL); #endif } + +int dtls1_listen(SSL *s, struct sockaddr *client) + { + int ret; + + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); + s-d1-listen = 1; + + ret = SSL_accept(s); + if (ret = 0) return ret; + + BIO_dgram_get_peer(SSL_get_rbio(s), client); + return 1; + } --- ssl/d1_srvr.c 5 Jun 2009 14:59:26 - 1.25 +++ ssl/d1_srvr.c 3 Sep 2009 09:59:22 - @@ -279,6 +279,15 @@ s-state = SSL3_ST_SW_SRVR_HELLO_A; s-init_num=0; + + /* If we're just listening, stop here */ + if (s-d1-listen s-state == SSL3_ST_SW_SRVR_HELLO_A) + { + ret = 2; + s-d1-listen = 0; + goto end; + } + break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: --- ssl/dtls1.h 17 Jun 2009 11:37:44 - 1.21 +++ ssl/dtls1.h 3 Sep 2009 09:59:22 - @@ -212,6 +212,9 @@ */ record_pqueue buffered_app_data; + /* Is set when listening for new connections with dtls1_listen() */ + unsigned int listen; + unsigned int mtu; /* max DTLS packet size */ struct hm_header_st w_msg_hdr; --- ssl/ssl.h 26 Aug 2009 11:51:57 - 1.231 +++ ssl/ssl.h 3 Sep 2009 09:59:22 - @@ -1398,11 +1398,14 @@ #define DTLS_CTRL_GET_TIMEOUT 73 #define DTLS_CTRL_HANDLE_TIMEOUT 74 +#define DTLS_CTRL_LISTEN 75 #define DTLSv1_get_timeout(ssl, arg) \ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) #define DTLSv1_handle_timeout(ssl) \ SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +#define DTLSv1_listen(ssl, peer) \ + SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer) #define SSL_session_reused(ssl) \ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) dtls-listen.patch Description: Binary data
Re: [openssl.org #2033] [PATCH] DTLS Listen
On Sep 9, 2009, at 2:23 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Wed Sep 09 08:49:17 2009]: On Sep 8, 2009, at 8:26 PM, Robin Seggelmann via RT wrote: Here's an updated version of the patch: [snipped] This doesn't compile cleanly, patches should compile without any warnings. In this case there are warnings about an implicit declaration of dtls1_listen(). Just adding a prototype ssl_locl.h is not sufficient because it needs the definition of struct sockaddr too. Sorry, I only compiled it on Mac OS X and it works there. Compiling on FreeBSD 8.0 helped to reproduce the warnings, so here is a new version. Actually, dtls1_listen() doesn't need to be defined in ssl_locl.h because it's only used inside d1_lib.c and nowhere else. It was implicit because its declaration was after it is called in dtls1_ctrl(), so adding a declaration at the top of the file solves the problem and there are no warnings left. If you still get warnings for a missing declaration of struct sockaddr, please try to add include sys/socket.h. - Robin --- ssl/d1_lib.c12 Aug 2009 17:30:36 - 1.16 +++ ssl/d1_lib.c3 Sep 2009 09:59:22 - @@ -68,6 +68,7 @@ static void get_current_time(struct timeval *t); const char dtls1_version_str[]=DTLSv1 OPENSSL_VERSION_PTEXT; +int dtls1_listen(SSL *s, struct sockaddr *client); SSL3_ENC_METHOD DTLSv1_enc_data={ dtls1_enc, @@ -203,6 +203,9 @@ case DTLS_CTRL_HANDLE_TIMEOUT: ret = dtls1_handle_timeout(s); break; + case DTLS_CTRL_LISTEN: + ret = dtls1_listen(s, parg); + break; default: ret = ssl3_ctrl(s, cmd, larg, parg); @@ -364,3 +367,17 @@ gettimeofday(t, NULL); #endif } + +int dtls1_listen(SSL *s, struct sockaddr *client) + { + int ret; + + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); + s-d1-listen = 1; + + ret = SSL_accept(s); + if (ret = 0) return ret; + + (void) BIO_dgram_get_peer(SSL_get_rbio(s), client); + return 1; + } --- ssl/d1_srvr.c 5 Jun 2009 14:59:26 - 1.25 +++ ssl/d1_srvr.c 3 Sep 2009 09:59:22 - @@ -279,6 +279,15 @@ s-state = SSL3_ST_SW_SRVR_HELLO_A; s-init_num=0; + + /* If we're just listening, stop here */ + if (s-d1-listen s-state == SSL3_ST_SW_SRVR_HELLO_A) + { + ret = 2; + s-d1-listen = 0; + goto end; + } + break; case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: --- ssl/dtls1.h 17 Jun 2009 11:37:44 - 1.21 +++ ssl/dtls1.h 3 Sep 2009 09:59:22 - @@ -212,6 +212,9 @@ */ record_pqueue buffered_app_data; + /* Is set when listening for new connections with dtls1_listen() */ + unsigned int listen; + unsigned int mtu; /* max DTLS packet size */ struct hm_header_st w_msg_hdr; --- ssl/ssl.h 26 Aug 2009 11:51:57 - 1.231 +++ ssl/ssl.h 3 Sep 2009 09:59:22 - @@ -1398,11 +1398,14 @@ #define DTLS_CTRL_GET_TIMEOUT 73 #define DTLS_CTRL_HANDLE_TIMEOUT 74 +#define DTLS_CTRL_LISTEN 75 #define DTLSv1_get_timeout(ssl, arg) \ SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) #define DTLSv1_handle_timeout(ssl) \ SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +#define DTLSv1_listen(ssl, peer) \ + SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer) #define SSL_session_reused(ssl) \ SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) dtls-listen.patch Description: Binary data
Re: [openssl.org #2033] [PATCH] DTLS Listen
Am 08.09.2009 um 18:15 schrieb Stephen Henson via RT: [seggelm...@fh-muenster.de - Thu Sep 03 18:09:34 2009]: This patch adds the function dtls1_listen(SSL *s, struct sockaddr *client), as well as the user accessible macro DTLSv1_listen(). It is intended to be called with an SSL object with a listening socket. [snip to example] /* Wait for ClientHello with valid cookie (blocking) */ while (!DTLSv1_listen(ssl, client_addr)); Is the above just an example or would it always block, possibly indefinitely? If so is there some way this could work with non- blocking I/O? That's just a simple example. If you use blocking sockets, it doesn't return until a ClientHello with a valid cookie has been received (returns 1) or an error occurred (returns 0). If you use non-blocking sockets, it always returns 0 on EAGAIN, so you can use select() to only call it when there's data to process and it will return as soon as there is nothing left. - Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #2033] [PATCH] DTLS Listen
Am 08.09.2009 um 19:59 schrieb Stephen Henson via RT: [seggelm...@fh-muenster.de - Tue Sep 08 18:31:29 2009]: That's just a simple example. If you use blocking sockets, it doesn't return until a ClientHello with a valid cookie has been received (returns 1) or an error occurred (returns 0). If you use non-blocking sockets, it always returns 0 on EAGAIN, so you can use select() to only call it when there's data to process and it will return as soon as there is nothing left. Is there some reason you only return 0, 1 from the ctrl? I'm wondering why you can't just return the return value of SSL_accept() (is = 0) for consistency with similar calls. Well, I was thinking of just making a difference between valid ClientHello received and everything else. Just returning the return value of SSL_accept() would be ok in case it's = 0. Otherwise it returns 2 to differentiate the premature handshake routine exit because of listen from the regular handshake ending. So, also for consitency, the listen call should not return 2 but 1 then. However, when using listen the handhsake routine should never exit with 1, indicating a successful handshake. I'll submit an updated version of the patch tomorrow. - Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #2033] [PATCH] DTLS Listen
Am 08.09.2009 um 18:31 schrieb Robin Seggelmann via RT: Am 08.09.2009 um 18:15 schrieb Stephen Henson via RT: [seggelm...@fh-muenster.de - Thu Sep 03 18:09:34 2009]: This patch adds the function dtls1_listen(SSL *s, struct sockaddr *client), as well as the user accessible macro DTLSv1_listen(). It is intended to be called with an SSL object with a listening socket. [snip to example] /* Wait for ClientHello with valid cookie (blocking) */ while (!DTLSv1_listen(ssl, client_addr)); Is the above just an example or would it always block, possibly indefinitely? If so is there some way this could work with non- blocking I/O? That's just a simple example. If you use blocking sockets, it doesn't return until a ClientHello with a valid cookie has been received (returns 1) or an error occurred (returns 0). If you use non-blocking sockets, it always returns 0 on EAGAIN, so you can use select() to only call it when there's data to process and it will return as soon as there is nothing left. I forgot to mention that in the example above I have socket timeouts set. That's the reason why the listen call is in a loop to try again as soon as it returned because of EAGAIN. - Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #2028] [PATCH] DTLS cookie management bugs
On Sep 4, 2009, at 1:21 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Fri Sep 04 09:39:52 2009]: Still wrong castsI hope that's it now A fair number of the casts seem to be unnecessary for example in RAND_bytes(), OPENSSL_malloc() and HMAC(). Do you get warnings on your system without them? I used the same example in a server/client testprogram and compiled it with the g++ compiler to be very pedantic. The regular gcc doesn't complain if there are none at all, but the g++ is nagging about missing casts. - Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #2022] [PATCH] DTLS record header length bug
On Sep 2, 2009, at 2:55 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Wed Aug 26 19:49:38 2009]: This patch fixes the size of the read and write buffers which are 8 bytes too small for DTLS. The function ssl3_setup_buffers() is called to allocate the necessary memory for the read and write buffers. This is done in two subfunctions, ssl3_setup_read_buffer() and ssl3_setup_write_buffer(). Unfortuanately there is no difference between TLS and DTLS, although both use different record headers with different lengths. Patch applied to OpenSSL 1.0 and HEAD, patch doesn't apply cleanly to 0.9.8. Here is a modified version for 0.9.8: --- ssl/s3_both.c 6 Aug 2009 16:23:17 - 1.43.2.2 +++ ssl/s3_both.c 3 Sep 2009 05:50:32 - @@ -587,9 +587,14 @@ int ssl3_setup_buffers(SSL *s) { unsigned char *p; - unsigned int extra; + unsigned int extra,headerlen; size_t len; + if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) + headerlen = DTLS1_RT_HEADER_LENGTH; + else + headerlen = SSL3_RT_HEADER_LENGTH; + if (s-s3-rbuf.buf == NULL) { if (s-options SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) @@ -606,7 +611,7 @@ if (s-s3-wbuf.buf == NULL) { len = SSL3_RT_MAX_PACKET_SIZE; - len += SSL3_RT_HEADER_LENGTH + 256; /* extra space for empty fragment */ + len += headerlen + 256; /* extra space for empty fragment */ if ((p=OPENSSL_malloc(len)) == NULL) goto err; s-s3-wbuf.buf = p; dtls-recordheaderlength-bug-0.9.8.patch Description: Binary data
[openssl.org #2033] [PATCH] DTLS Listen
This patch adds the function dtls1_listen(SSL *s, struct sockaddr *client), as well as the user accessible macro DTLSv1_listen(). It is intended to be called with an SSL object with a listening socket. Every ClientHello arriving will be answered with a HelloVerifyRequest without allocating any memory. When a ClientHello is repeated with a valid cookie attached, dtls1_listen() returns after entering the peer's address into the given sockaddr structure. The application can then create an UDP socket connected to that peer, assign it to the SSL object and continue the connection (with a SSL_accept() to complete the handshake, since the dtls1_listen returns before sending the ServerHello) in a new thread. Then a new SSL object has to be created and the listening socket has to be assigned to it, so that following connections can be handled. Here's an example how the server can look like: - /* Create listening socket */ fd = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) on, (socklen_t) sizeof(on)); setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) on, (socklen_t) sizeof(on)); bind(fd, (const struct sockaddr *) server_addr, sizeof(server_addr)); while (1) { memset(client_addr, 0, sizeof(struct sockaddr)); /* Create new BIO with the listening socket and new SSL object */ bio = BIO_new_dgram(fd, BIO_NOCLOSE); ssl = SSL_new(ctx); /* Assign BIO and activate cookie exchange */ SSL_set_bio(ssl, bio, bio); SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE); /* Wait for ClientHello with valid cookie (blocking) */ while (!DTLSv1_listen(ssl, client_addr)); /* Pass SSL object and peer info to a new thread */ info = (struct pass_info*) malloc (sizeof(struct pass_info)); memcpy(info-server_addr, server_addr, sizeof(struct sockaddr)); memcpy(info-client_addr, client_addr, sizeof(struct sockaddr)); info-ssl = ssl; pthread_create( tid, NULL, connection_thread, info); } - The new thread can then create a connected socket with the passed information and assign the new socket to the existing SSL object to continue with a one-to-one connection. - fd = socket(AF_INET, SOCK_DGRAM, 0); setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) on, (socklen_t) sizeof(on)); setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) on, (socklen_t) sizeof(on)); bind(fd, (const struct sockaddr *) server_addr, sizeof(struct sockaddr)); connect(fd, (struct sockaddr *) client_addr, sizeof(struct sockaddr)); /* Set new fd and set BIO to connected */ BIO_set_fd(SSL_get_rbio(ssl), fd, BIO_NOCLOSE); BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_CONNECTED, 0, client_addr); /* Finish handshake */ SSL_accept(ssl); - This allows clean multi-threaded applications with UDP, since accept() can't be used and a continuous listening socket is necessary to avoid the loss of messages until a new listening socket has been created after connecting the previous one. It also allows to use the HelloVerifyRequest functionallity to avoid denial of service attacks, because otherwise resources (connected socket, thread) have to be allocated for every new connection to perform a handshake, maybe just to await the timeout because the peer doesn't answer. --- ssl/d1_lib.c12 Aug 2009 17:30:36 - 1.16 +++ ssl/d1_lib.c3 Sep 2009 09:59:22 - @@ -203,6 +203,9 @@ case DTLS_CTRL_HANDLE_TIMEOUT: ret = dtls1_handle_timeout(s); break; + case DTLS_CTRL_LISTEN: + ret = dtls1_listen(s, parg); + break; default: ret = ssl3_ctrl(s, cmd, larg, parg); @@ -364,3 +367,17 @@ gettimeofday(t, NULL); #endif } + +int dtls1_listen(SSL *s, struct sockaddr *client) + { + int ret; + + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); + s-d1-listen = 1; + + ret = SSL_accept(s); + if (ret = 0) return 0; + + BIO_dgram_get_peer(SSL_get_rbio(s), client); + return 1; + } --- ssl/d1_srvr.c 5 Jun 2009 14:59:26 - 1.25 +++ ssl/d1_srvr.c 3 Sep 2009 09:59:22 - @@ -279,6 +279,15 @@ s-state = SSL3_ST_SW_SRVR_HELLO_A; s-init_num=0; + + /* If we're just listening, stop here */ + if (s-d1-listen s-state == SSL3_ST_SW_SRVR_HELLO_A) + { + ret = 2; + s-d1-listen = 0; + goto end; + } + break;
[openssl.org #2028] [PATCH] DTLS cookie management bugs
This patch fixes several issues with DTLS cookies. At first the maximum cookie length was defined as 32 bytes, while the specification states 256 bytes. Then there was code in the wrong order which prevented the use of cookies larger than 0 bytes in ssl3_get_client_hello(), it was tried to process extensions before the cookie. The present implementation always expects a ClientHello, sends a HelloVerifyRequest and then expects a ClientHello with a cookie attached. Everything else is considered as an error, which is not correct because the first ClientHello could be repeated. Now every ClientHello is answered with a HelloVerifyRequest until a ClientHello with cookie appears. Then the cookie is verified and an error returned if the verification failed. If SSL_OP_COOKIE_EXCHANGE is set, in dtls1_send_hello_verify_request() the cookie is sent. It was assumed that the cookie was specified somehow else if the user did not register a callback function for cookie generation. This doesn't make any sense because if the user doesn't use the designated function to generate cookies, how else should they be generated? The result is a cookie with length 0, which is almost as bad as no HelloVerifyRequest at all. Now an internal error occurs if the user requests cookie exchange but did not register the required callback functions. The application s_server activated cookies but didn't supply any generation or verification functions. They are added now and use a 16 byte random number as a secret to calculate an HMAC over the peer's address and port as suggested in the DTLS specification. --- apps/s_apps.h 22 Dec 2008 14:05:42 - 1.21 +++ apps/s_apps.h 31 Aug 2009 13:24:35 - @@ -171,3 +171,6 @@ unsigned char *data, int len, void *arg); #endif + +int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len); +int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie, unsigned int cookie_len); --- apps/s_cb.c 24 Jul 2009 11:17:10 - 1.28 +++ apps/s_cb.c 31 Aug 2009 13:24:35 - @@ -121,9 +121,13 @@ #include openssl/ssl.h #include s_apps.h +#defineCOOKIE_SECRET_LENGTH16 + int verify_depth=0; int verify_error=X509_V_OK; int verify_return_error=0; +unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; +int cookie_initialized=0; int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) { @@ -668,3 +690,93 @@ BIO_dump(bio, (char *)data, len); (void)BIO_flush(bio); } + +int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) + { + unsigned char *buffer, result[EVP_MAX_MD_SIZE]; + unsigned int length, resultlength; + struct sockaddr_in peer; + + /* Initialize a random secret */ + if (!cookie_initialized) + { + if (!RAND_bytes((unsigned char*) cookie_secret, COOKIE_SECRET_LENGTH)) + { + BIO_printf(bio_err,error setting random cookie secret\n); + return 0; + } + cookie_initialized = 1; + } + + /* Read peer information */ + BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); + + /* Create buffer with peer's address and port */ + length = sizeof(peer.sin_addr); + length += sizeof(peer.sin_port); + buffer = OPENSSL_malloc(length); + + if (buffer == NULL) + { + BIO_printf(bio_err,out of memory\n); + return 0; + } + + memcpy(buffer, peer.sin_addr, sizeof(peer.sin_addr)); + memcpy(buffer + sizeof(peer.sin_addr), peer.sin_port, sizeof(peer.sin_port)); + + /* Calculate HMAC of buffer using the secret */ + HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, buffer, +length, (unsigned char*) result, resultlength); + OPENSSL_free(buffer); + + memcpy(cookie, result, resultlength); + *cookie_len = resultlength; + + return 1; + } + +int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie, unsigned int cookie_len) + { + unsigned char *buffer, result[EVP_MAX_MD_SIZE]; + unsigned int length, resultlength; + struct sockaddr_in peer; + + /* Initialize a random secret */ + if (!cookie_initialized) + { + if (!RAND_bytes((unsigned char*) cookie_secret, COOKIE_SECRET_LENGTH)) + { + BIO_printf(bio_err,error setting random cookie secret\n); + return 0; + } + cookie_initialized = 1; + } + + /* Read peer information */ + BIO_dgram_get_peer(SSL_get_rbio(ssl), peer); + + /*
[openssl.org #2022] [PATCH] DTLS record header length bug
This patch fixes the size of the read and write buffers which are 8 bytes too small for DTLS. The function ssl3_setup_buffers() is called to allocate the necessary memory for the read and write buffers. This is done in two subfunctions, ssl3_setup_read_buffer() and ssl3_setup_write_buffer(). Unfortuanately there is no difference between TLS and DTLS, although both use different record headers with different lengths. --- ssl/s3_both.c 15 Jul 2009 11:32:57 - 1.49.2.2 +++ ssl/s3_both.c 26 Aug 2009 11:30:45 - @@ -666,7 +666,12 @@ int ssl3_setup_read_buffer(SSL *s) { unsigned char *p; - size_t len,align=0; + size_t len,align=0,headerlen; + + if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) + headerlen = DTLS1_RT_HEADER_LENGTH; + else + headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH)(SSL3_ALIGN_PAYLOAD-1); @@ -676,7 +681,7 @@ { len = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD - + SSL3_RT_HEADER_LENGTH + align; + + headerlen + align; if (s-options SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { s-s3-init_extra = 1; @@ -703,7 +708,12 @@ int ssl3_setup_write_buffer(SSL *s) { unsigned char *p; - size_t len,align=0; + size_t len,align=0,headerlen; + + if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) + headerlen = DTLS1_RT_HEADER_LENGTH + 1; + else + headerlen = SSL3_RT_HEADER_LENGTH; #if defined(SSL3_ALIGN_PAYLOAD) SSL3_ALIGN_PAYLOAD!=0 align = (-SSL3_RT_HEADER_LENGTH)(SSL3_ALIGN_PAYLOAD-1); @@ -713,13 +723,13 @@ { len = s-max_send_fragment + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD - + SSL3_RT_HEADER_LENGTH + align; + + headerlen + align; #ifndef OPENSSL_NO_COMP if (!(s-options SSL_OP_NO_COMPRESSION)) len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif if (!(s-options SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) - len += SSL3_RT_HEADER_LENGTH + align + len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; if ((p=freelist_extract(s-ctx, 0, len)) == NULL) dtls-recordheaderlength-bug.patch Description: Binary data
[openssl.org #2015] OpenSSL doesn't install with shared libs config
When configuring OpenSSL with ./config shared --prefix=$HOME/install on Mac OS X 10.5.8, it compiles cleanly but doesn't install. Apparently some Makefiles seem to be messed up: making install in crypto... ... making install in ssl... making install in engines... installing 4758cca cp: /Users/robinseggelmann/install//engines/lib4758cca.so.new: No such file or directory installing aep cp: /Users/robinseggelmann/install//engines/libaep.so.new: No such file or directory installing atalla cp: /Users/robinseggelmann/install//engines/libatalla.so.new: No such file or directory installing cswift cp: /Users/robinseggelmann/install//engines/libcswift.so.new: No such file or directory installing gmp cp: /Users/robinseggelmann/install//engines/libgmp.so.new: No such file or directory installing chil cp: /Users/robinseggelmann/install//engines/libchil.so.new: No such file or directory installing nuron cp: /Users/robinseggelmann/install//engines/libnuron.so.new: No such file or directory installing sureware cp: /Users/robinseggelmann/install//engines/libsureware.so.new: No such file or directory installing ubsec cp: /Users/robinseggelmann/install//engines/libubsec.so.new: No such file or directory installing padlock cp: /Users/robinseggelmann/install//engines/libpadlock.so.new: No such file or directory installing capi cp: /Users/robinseggelmann/install//engines/libcapi.so.new: No such file or directory make[1]: *** [install] Error 1 make: *** [install_sw] Error 1 The problem occurs since request #2003, check-in #18488. When I return engines/Makefile to a version before that patch (1.25), it installs cleanly. However, then the binaries in apps can't find the libraries because they got the wrong directory for the shared libs: openssl: /Users/robinseggelmann/install//libssl.1.1.0.dylib (compatibility version 1.1.0, current version 1.1.0) /Users/robinseggelmann/install//libcrypto.1.1.0.dylib (compatibility version 1.1.0, current version 1.1.0) /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4) The lib is missing there. It doesn't matter whether the new libdir parameter is used or not. Unfortunatley I'm not familiar with the Makefiles, so I can't provide a patch. I'd appreciate if this is fixed soon because I have to use links now, so the binaries can find the libs. That in turn has the disadvantage, that the binaries don't notice changes and I have to rebuild everything every time, which is very annoying. - Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1997] [PATCH] DTLS timeout handling bug
On Aug 12, 2009, at 3:23 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Wed Aug 12 08:34:27 2009]: Ok, here's an updated version. Internally is dtls1_get_timeout() and dtls1_handle_timeout() used. They can be called externally using SSL_ctrl() with DTLS_CTRL_GET_TIMEOUT and DTLS_CTRL_HANDLE_TIMEOUT or with the corresponding macros DTLSv1_get_timeout() and DTLSv1_handle_timeout() for simplicity. OK, I've applied a slightly modified version to 1.0 and HEAD (to avoid a shadow warning on the timeout variable). Patch doesn't apply cleanly to 0.9.8, please include a version for that and I'll apply it. Steve. Here is a version for 0.9.8. --- apps/s_client.c 17 May 2009 16:48:19 - 1.76.2.25 +++ apps/s_client.c 13 Aug 2009 09:13:38 - @@ -318,6 +318,7 @@ BIO *sbio; char *inrand=NULL; int mbuf_len=0; + struct timeval timeout, *timeoutp; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; char *ssl_client_engine_id=NULL; @@ -819,7 +820,6 @@ if ( SSL_version(con) == DTLS1_VERSION) { - struct timeval timeout; sbio=BIO_new_dgram(s,BIO_NOCLOSE); if (getsockname(s, peer, (void *)peerlen) 0) @@ -1036,6 +1036,12 @@ FD_ZERO(readfds); FD_ZERO(writefds); + if ((SSL_version(con) == DTLS1_VERSION) + DTLSv1_get_timeout(con, timeout)) + timeoutp = timeout; + else + timeoutp = NULL; + if (SSL_in_init(con) !SSL_total_renegotiations(con)) { in_init=1; @@ -1132,7 +1138,7 @@ if(!i (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || ! read_tty) ) continue; #endif } else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { @@ -1142,11 +1148,11 @@ i=select(width,(void *)readfds,(void *)writefds, NULL,tv); } else i=select(width,(void *)readfds,(void *)writefds, - NULL,NULL); + NULL,timeoutp); } #else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); #endif if ( i 0) { @@ -1157,6 +1163,11 @@ } } + if ((SSL_version(con) == DTLS1_VERSION) DTLSv1_handle_timeout(con) 0) + { + BIO_printf(bio_err,TIMEOUT occured\n); + } + if (!ssl_pending FD_ISSET(SSL_get_fd(con),writefds)) { k=SSL_write(con,(cbuf[cbuf_off]), --- apps/s_server.c 5 Jun 2009 15:05:08 - 1.97.2.16 +++ apps/s_server.c 13 Aug 2009 09:13:38 - @@ -1590,6 +1590,7 @@ unsigned long l; SSL *con=NULL; BIO *sbio; + struct timeval timeout, *timeoutp; #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) struct timeval tv; #endif @@ -1643,7 +1644,6 @@ if (SSL_version(con) == DTLS1_VERSION) { - struct timeval timeout; sbio=BIO_new_dgram(s,BIO_NOCLOSE); @@ -1744,7 +1744,19 @@ if(_kbhit()) read_from_terminal = 1; #else - i=select(width,(void *)readfds,NULL,NULL,NULL); + if ((SSL_version(con) == DTLS1_VERSION) + DTLSv1_get_timeout(con, timeout)) + timeoutp = timeout; + else + timeoutp = NULL; + + i=select(width,(void *)readfds,NULL,NULL,timeoutp); + + if ((SSL_version(con) == DTLS1_VERSION) DTLSv1_handle_timeout(con) 0) + { + BIO_printf(bio_err,TIMEOUT occured\n); + } + if (i = 0) continue; if (FD_ISSET(fileno(stdin),readfds)) read_from_terminal = 1; --- ssl/d1_both.c 6 Aug 2009 16:23:17 - 1.4.2.18 +++ ssl/d1_both.c 13 Aug 2009 09:13:38 - @@ -892,9 +892,6 @@ int dtls1_read_failed(SSL *s, int
Re: [openssl.org #1997] [PATCH] DTLS timeout handling bug
On Aug 11, 2009, at 7:40 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Mon Jul 27 17:03:25 2009]: This patch fixes the timeout handling. The method dtls1_get_timeout() was intended to determine the next handshake message timeout when using select() calls, to set their timeout. This method is renamed to DTLSv1_get_timeout(), to fit the common naming scheme and the declaration is moved. It was declared in the wrong file, so the user was unable to use it. Additionally, the timeout handling is moved to the method DTLSv1_handle_timeout(), which can be called by the user when a select() timer expires. Until now expired timers were handled not until a SSL_read() is called. This is a problem when using select() on the reading socket, because no call of SSL_read() is done before data from the peer arrived. Actually now I think of it perhaps the ctrl() mechanism would be a better way to implement this. Steve. Ok, here's an updated version. Internally is dtls1_get_timeout() and dtls1_handle_timeout() used. They can be called externally using SSL_ctrl() with DTLS_CTRL_GET_TIMEOUT and DTLS_CTRL_HANDLE_TIMEOUT or with the corresponding macros DTLSv1_get_timeout() and DTLSv1_handle_timeout() for simplicity. --- apps/s_client.c 30 Jun 2009 16:10:24 - 1.123.2.2 +++ apps/s_client.c 12 Aug 2009 06:20:30 - @@ -411,6 +411,7 @@ BIO *sbio; char *inrand=NULL; int mbuf_len=0; + struct timeval timeout, *timeoutp; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; char *ssl_client_engine_id=NULL; @@ -1196,6 +1197,12 @@ FD_ZERO(readfds); FD_ZERO(writefds); + if ((SSL_version(con) == DTLS1_VERSION) + DTLSv1_get_timeout(con, timeout)) + timeoutp = timeout; + else + timeoutp = NULL; + if (SSL_in_init(con) !SSL_total_renegotiations(con)) { in_init=1; @@ -1300,7 +1307,7 @@ if(!i (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || ! read_tty) ) continue; #endif } else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { @@ -1310,7 +1317,7 @@ i=select(width,(void *)readfds,(void *)writefds, NULL,tv); } else i=select(width,(void *)readfds,(void *)writefds, - NULL,NULL); + NULL,timeoutp); } #elif defined(OPENSSL_SYS_BEOS_R5) /* Under BeOS-R5 the situation is similar to DOS */ @@ -1328,12 +1335,12 @@ if (!i (stdin_set != 1 || !read_tty)) continue; } else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); } (void)fcntl(fileno(stdin), F_SETFL, 0); #else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); #endif if ( i 0) { @@ -1344,6 +1351,11 @@ } } + if ((SSL_version(con) == DTLS1_VERSION) DTLSv1_handle_timeout(con) 0) + { + BIO_printf(bio_err,TIMEOUT occured\n); + } + if (!ssl_pending FD_ISSET(SSL_get_fd(con),writefds)) { k=SSL_write(con,(cbuf[cbuf_off]), --- apps/s_server.c 27 Jul 2009 21:08:46 - 1.136.2.5 +++ apps/s_server.c 12 Aug 2009 06:20:30 - @@ -1750,6 +1750,7 @@ unsigned long l; SSL *con=NULL; BIO *sbio; + struct timeval timeout, *timeoutp; #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) struct timeval tv; #endif @@ -1919,7 +1920,19 @@ read_from_terminal = 1; (void)fcntl(fileno(stdin), F_SETFL, 0); #else - i=select(width,(void *)readfds,NULL,NULL,NULL); + if ((SSL_version(con) == DTLS1_VERSION) + DTLSv1_get_timeout(con, timeout)) +
[openssl.org #1997] [PATCH] DTLS timeout handling bug
This patch fixes the timeout handling. The method dtls1_get_timeout() was intended to determine the next handshake message timeout when using select() calls, to set their timeout. This method is renamed to DTLSv1_get_timeout(), to fit the common naming scheme and the declaration is moved. It was declared in the wrong file, so the user was unable to use it. Additionally, the timeout handling is moved to the method DTLSv1_handle_timeout(), which can be called by the user when a select() timer expires. Until now expired timers were handled not until a SSL_read() is called. This is a problem when using select() on the reading socket, because no call of SSL_read() is done before data from the peer arrived. The test programs s_server and s_client are also modified to make use of the new timeout handling to fully support timeouts. --- apps/s_client.c 30 Jun 2009 15:56:35 - 1.125 +++ apps/s_client.c 27 Jul 2009 12:28:55 - @@ -411,6 +411,7 @@ BIO *sbio; char *inrand=NULL; int mbuf_len=0; + struct timeval timeout, *timeoutp; #ifndef OPENSSL_NO_ENGINE char *engine_id=NULL; char *ssl_client_engine_id=NULL; @@ -1196,6 +1197,12 @@ FD_ZERO(readfds); FD_ZERO(writefds); + if ((SSL_version(con) == DTLS1_VERSION) + (DTLSv1_get_timeout(con, timeout) != NULL)) + timeoutp = timeout; + else + timeoutp = NULL; + if (SSL_in_init(con) !SSL_total_renegotiations(con)) { in_init=1; @@ -1300,7 +1307,7 @@ if(!i (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || ! read_tty) ) continue; #endif } else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); } #elif defined(OPENSSL_SYS_NETWARE) if(!write_tty) { @@ -1310,7 +1317,7 @@ i=select(width,(void *)readfds,(void *)writefds, NULL,tv); } else i=select(width,(void *)readfds,(void *)writefds, - NULL,NULL); + NULL,timeoutp); } #elif defined(OPENSSL_SYS_BEOS_R5) /* Under BeOS-R5 the situation is similar to DOS */ @@ -1328,12 +1335,12 @@ if (!i (stdin_set != 1 || !read_tty)) continue; } else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); } (void)fcntl(fileno(stdin), F_SETFL, 0); #else i=select(width,(void *)readfds,(void *)writefds, -NULL,NULL); +NULL,timeoutp); #endif if ( i 0) { @@ -1344,6 +1351,11 @@ } } + if ((SSL_version(con) == DTLS1_VERSION) DTLSv1_handle_timeout(con) 0) + { + BIO_printf(bio_err,TIMEOUT occured\n); + } + if (!ssl_pending FD_ISSET(SSL_get_fd(con),writefds)) { k=SSL_write(con,(cbuf[cbuf_off]), --- apps/s_server.c 30 Jun 2009 15:56:35 - 1.140 +++ apps/s_server.c 27 Jul 2009 12:28:55 - @@ -1750,6 +1750,7 @@ unsigned long l; SSL *con=NULL; BIO *sbio; + struct timeval timeout, *timeoutp; #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5) struct timeval tv; #endif @@ -1919,7 +1920,19 @@ read_from_terminal = 1; (void)fcntl(fileno(stdin), F_SETFL, 0); #else - i=select(width,(void *)readfds,NULL,NULL,NULL); + if ((SSL_version(con) == DTLS1_VERSION) + (DTLSv1_get_timeout(con, timeout) != NULL)) + timeoutp = timeout; + else + timeoutp = NULL; + + i=select(width,(void *)readfds,NULL,NULL,timeoutp); + + if ((SSL_version(con) == DTLS1_VERSION) DTLSv1_handle_timeout(con) 0) + { +
[openssl.org #1993] [PATCH] DTLS Cookie Resumption bug
In d1_clnt.c the variables s-d1-send_cookie and s-hit aren't reset when initiating a new renegotiation handshake. This is ok if a new session is created, that is everything will be reset anyway, but with an abbreviated handshake without a new session this causes the handshake to fail. Additionally a typo in d1_pkt.c in OpenSSL 1.0.0 is fixed. --- ssl/d1_clnt.c 2009-07-15 13:32:57.0 +0200 +++ ssl/d1_clnt.c 2009-07-23 12:48:29.0 +0200 @@ -223,6 +223,8 @@ s-init_num=0; /* mark client_random uninitialized */ memset(s-s3-client_random,0,sizeof(s-s3-client_random)); + s-d1-send_cookie = 0; + s-hit = 0; break; case SSL3_ST_CW_CLNT_HELLO_A: --- ssl/d1_pkt.c2009-07-13 13:44:04.0 +0200 +++ ssl/d1_pkt.c2009-07-23 12:47:41.0 +0200 @@ -775,7 +775,7 @@ /* Check for timeout */ if (dtls1_is_timer_expired(s)) { - if (dtls1_read_failed(s, -1) 0); + if (dtls1_read_failed(s, -1) 0) goto start; } dtls-cookie-resumption-bug-1.0.0.patch Description: Binary data
[openssl.org #1990] [PATCH] DTLS socket timeout bug
When the socket timeout has to be adjusted because of a handshake timeout expiring earlier, the user set value is saved and reset afterwards. This patch adds a missing if-clause in dgram_reset_rcv_timeout() to prevent the reset of the socket timeout when no timer is active. Since no adjustment has been done then, no previous socket timeout has been saved and the socket timeout will be always set to 0. --- crypto/bio/bss_dgram.c 5 Jun 2009 14:46:48 - 1.7.2.14 +++ crypto/bio/bss_dgram.c 22 Jul 2009 10:56:00 - @@ -250,17 +380,22 @@ { #if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b-ptr; + + /* Is a timer active? */ + if (data-next_timeout.tv_sec 0 || data-next_timeout.tv_usec 0) + { #ifdef OPENSSL_SYS_WINDOWS - int timeout = data-socket_timeout.tv_sec * 1000 + - data-socket_timeout.tv_usec / 1000; - if (setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, - (void*)timeout, sizeof(timeout)) 0) - { perror(setsockopt); } -#else - if ( setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, (data- socket_timeout), - sizeof(struct timeval)) 0) - { perror(setsockopt); } + int timeout = data-socket_timeout.tv_sec * 1000 + + data-socket_timeout.tv_usec / 1000; + if (setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, + (void*)timeout, sizeof(timeout)) 0) + { perror(setsockopt); } +#else + if ( setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, (data- socket_timeout), + sizeof(struct timeval)) 0) + { perror(setsockopt); } #endif + } #endif } dtls-socket-timeout-bug.patch Description: Binary data
[openssl.org #1981] [PATCH] DTLS Record Header
This patch changes the behavior of DTLS regarding erroneous record headers. The current implementation reports an error if the version or length entries of the record layer are unexpected and closes the connection. This is probably takes over from TLS but doesn't make sense with DTLS, since an attacker can easily send random data to close the connection. In fact every packet not containing the correct version and length terminates the connection. With this patch such packets are just silently discarded to keep the connection alive. --- ssl/d1_pkt.c1 Jul 2009 11:29:01 - 1.27.2.10 +++ ssl/d1_pkt.c3 Jul 2009 13:43:18 - @@ -586,26 +594,27 @@ { if (version != s-version) { - SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); - /* Send back error using their -* version number :-) */ - s-version=version; - al=SSL_AD_PROTOCOL_VERSION; - goto f_err; + /* unexpected version, silently discard */ + rr-length = 0; + s-packet_length = 0; + goto again; } } if ((version 0xff00) != (s-version 0xff00)) { - SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER); - goto err; + /* wrong version, silently discard record */ + rr-length = 0; + s-packet_length = 0; + goto again; } if (rr-length SSL3_RT_MAX_ENCRYPTED_LENGTH) { - al=SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; + /* record too long, silently discard it */ + rr-length = 0; + s-packet_length = 0; + goto again; } /* now s-rstate == SSL_ST_READ_BODY */ dtls-record.patch Description: Binary data
Re: [openssl.org #1953] Bug: DTLS never sends Finish and leaks that message
Hi Michael, this bug has already been described in bug report #1828 and has been fixed in OpenSSL 1.0.0 beta 2 as well as in the current version of the 0.9.8 stable development branch. To solve this issue you can either use OpenSSL 1.0.0 beta 2 or use the patches for 0.9.8k provided on sctp.fh-muenster.de. You may also notice that there are numeroxus other bugs that have been fixed already. Except for the latest ECDH patch, all of them are applied to both the 0.9.8 and 1.0.0 branches available via CVS and will be included in the next releases. Regards, Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1952] [PATCH] ECDH renegotiaton bug
The variable s-s3-tmp.ecdh is set in ssl3_send_server_key_exchange() or dtls1_send_server_key_exchange(), after it is checked if it points to NULL. Later it is read only once in ssl3_get_client_key_exchange(), but then not freed and set to NULL again. When a renegotiation with a full handshake is performed, to compute new key material, the procedure is the same and s-s3-tmp.ecdh should be set in the send_server_key_exchange() functions. This fails because is has not been set to NULL in advance, so no renegotiation is possible, even worse, it causes to connection to fail. This patch adds two lines to free the variable right after it has been used, to allow it to be set again during following renegotiations. --- ssl/s3_srvr.c 22 Apr 2009 15:40:54 - 1.171.2.3 +++ ssl/s3_srvr.c 10 Jun 2009 08:30:11 - @@ -2388,6 +2399,8 @@ EC_POINT_free(clnt_ecpoint); EC_KEY_free(srvr_ecdh); BN_CTX_free(bn_ctx); + EC_KEY_free(s-s3-tmp.ecdh); + s-s3-tmp.ecdh = NULL; /* Compute the master secret */ s-session-master_key_length = s-method-ssl3_enc- \ ecdh-bug.patch Description: Binary data
Re: [openssl.org #1950] [PATCH] DTLS fragment retransmission bug
Here is an updated version, the last didn't cover every variation of the handshake message flow because the CertificateVerify state is entered every time, not only when a CertificateVerify message is really expected. --- crypto/bio/bss_dgram.c 5 Jun 2009 08:35:54 - 1.7.2.13 +++ crypto/bio/bss_dgram.c 5 Jun 2009 12:05:47 - @@ -220,9 +220,10 @@ /* Adjust socket timeout if next handhake message timer * will expire earlier. */ - if (data-socket_timeout.tv_sec timeleft.tv_sec || + if ((data-socket_timeout.tv_sec == 0 data- socket_timeout.tv_usec == 0) || + (data-socket_timeout.tv_sec timeleft.tv_sec) || (data-socket_timeout.tv_sec == timeleft.tv_sec -data-socket_timeout.tv_usec = timeleft.tv_usec)) +data-socket_timeout.tv_usec = timeleft.tv_usec)) { #ifdef OPENSSL_SYS_WINDOWS timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; --- ssl/d1_both.c 16 May 2009 16:22:11 - 1.14.2.9 +++ ssl/d1_both.c 5 Jun 2009 12:05:47 - @@ -569,9 +569,13 @@ item = pqueue_find(s-d1-buffered_messages, seq64be); /* Discard the message if sequence number was already there, is -* too far in the future or the fragment is already in the queue */ +* too far in the future, already in the queue or if we received +* a FINISHED before the SERVER_HELLO, which then must be a stale +* retransmit. +*/ if (msg_hdr-seq = s-d1-handshake_read_seq || - msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL) + msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL || + s-d1-handshake_read_seq == 0 msg_hdr-type == SSL3_MT_FINISHED) { unsigned char devnull [256]; --- ssl/d1_clnt.c 31 May 2009 17:11:24 - 1.16.2.8 +++ ssl/d1_clnt.c 5 Jun 2009 12:05:47 - @@ -442,7 +442,7 @@ case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - + s-d1-change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret = 0) goto end; --- ssl/d1_pkt.c16 May 2009 16:17:46 - 1.27.2.8 +++ ssl/d1_pkt.c5 Jun 2009 12:05:47 - @@ -1102,6 +1102,16 @@ s-msg_callback(0, s-version, SSL3_RT_CHANGE_CIPHER_SPEC, rr-data, 1, s, s-msg_callback_arg); + /* We can't process a CCS now, because previous handshake +* messages are still missing, so just drop it. +*/ + if (!s-d1-change_cipher_spec_ok) + { + goto start; + } + + s-d1-change_cipher_spec_ok = 0; + s-s3-change_cipher_spec=1; if (!ssl3_do_change_cipher_spec(s)) goto err; --- ssl/d1_srvr.c 31 May 2009 17:11:24 - 1.20.2.5 +++ ssl/d1_srvr.c 5 Jun 2009 12:05:47 - @@ -497,6 +497,7 @@ case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: + s-d1-change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret = 0) goto end; @@ -508,6 +509,7 @@ case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: + s-d1-change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret = 0) goto end; --- ssl/dtls1.h 2 Jun 2009 11:23:30 - 1.12.2.9 +++ ssl/dtls1.h 5 Jun 2009 12:05:47 - @@ -231,6 +231,7 @@ unsigned int handshake_fragment_len; unsigned int retransmitting; + unsigned int change_cipher_spec_ok; } DTLS1_STATE; dtls-fragment-retransmission-bug-1.0.0.patch Description: Binary data dtls-fragment-retransmission-bug-0.9.8.patch Description: Binary data
Re: [openssl.org #1950] [PATCH] DTLS fragment retransmission bug
I just found another timing bug... --- crypto/bio/bss_dgram.c 5 Jun 2009 08:35:54 - 1.7.2.13 +++ crypto/bio/bss_dgram.c 5 Jun 2009 14:00:26 - @@ -217,12 +217,19 @@ timeleft.tv_usec += 100; } + if (timeleft.tv_sec 0) + { + timeleft.tv_sec = 0; + timeleft.tv_usec = 1; + } + /* Adjust socket timeout if next handhake message timer * will expire earlier. */ - if (data-socket_timeout.tv_sec timeleft.tv_sec || + if ((data-socket_timeout.tv_sec == 0 data- socket_timeout.tv_usec == 0) || + (data-socket_timeout.tv_sec timeleft.tv_sec) || (data-socket_timeout.tv_sec == timeleft.tv_sec -data-socket_timeout.tv_usec = timeleft.tv_usec)) +data-socket_timeout.tv_usec = timeleft.tv_usec)) { #ifdef OPENSSL_SYS_WINDOWS timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; --- ssl/d1_both.c 16 May 2009 16:22:11 - 1.14.2.9 +++ ssl/d1_both.c 5 Jun 2009 14:00:31 - @@ -569,9 +569,13 @@ item = pqueue_find(s-d1-buffered_messages, seq64be); /* Discard the message if sequence number was already there, is -* too far in the future or the fragment is already in the queue */ +* too far in the future, already in the queue or if we received +* a FINISHED before the SERVER_HELLO, which then must be a stale +* retransmit. +*/ if (msg_hdr-seq = s-d1-handshake_read_seq || - msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL) + msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL || + s-d1-handshake_read_seq == 0 msg_hdr-type == SSL3_MT_FINISHED) { unsigned char devnull [256]; --- ssl/d1_clnt.c 31 May 2009 17:11:24 - 1.16.2.8 +++ ssl/d1_clnt.c 5 Jun 2009 14:00:31 - @@ -442,7 +442,7 @@ case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - + s-d1-change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret = 0) goto end; --- ssl/d1_pkt.c16 May 2009 16:17:46 - 1.27.2.8 +++ ssl/d1_pkt.c5 Jun 2009 14:00:31 - @@ -1102,6 +1102,16 @@ s-msg_callback(0, s-version, SSL3_RT_CHANGE_CIPHER_SPEC, rr-data, 1, s, s-msg_callback_arg); + /* We can't process a CCS now, because previous handshake +* messages are still missing, so just drop it. +*/ + if (!s-d1-change_cipher_spec_ok) + { + goto start; + } + + s-d1-change_cipher_spec_ok = 0; + s-s3-change_cipher_spec=1; if (!ssl3_do_change_cipher_spec(s)) goto err; --- ssl/d1_srvr.c 31 May 2009 17:11:24 - 1.20.2.5 +++ ssl/d1_srvr.c 5 Jun 2009 14:00:31 - @@ -497,6 +497,7 @@ case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: + s-d1-change_cipher_spec_ok = 1; /* we should decide if we expected this one */ ret=ssl3_get_cert_verify(s); if (ret = 0) goto end; @@ -508,6 +509,7 @@ case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: + s-d1-change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret = 0) goto end; --- ssl/dtls1.h 2 Jun 2009 11:23:30 - 1.12.2.9 +++ ssl/dtls1.h 5 Jun 2009 14:00:31 - @@ -231,6 +231,7 @@ unsigned int handshake_fragment_len; unsigned int retransmitting; + unsigned int change_cipher_spec_ok; } DTLS1_STATE; dtls-fragment-retransmission-bug-1.0.0.patch Description: Binary data dtls-fragment-retransmission-bug-0.9.8.patch Description: Binary data
[openssl.org #1950] [PATCH] DTLS fragment retransmission bug
When handshake messages can't be reassembled because a fragment got lost, the ChangeCipherSpec included in the same flight was still processed. The new mastersecret has not been calculated yet, so random memory is used causing the connection to fail. This patch drops every ChangeCipherSpec which arrives before all previous messages are processed. It doesn't have to be buffered because always the entire flight is repeated, so it will be sent again anyway. This patch also fixes wrong socket timing causing retransmissions to be sent later than necessary. Finally this patch also fixes a problem with stale retransmits of Finished messages of a previous handshake when a new one is initiated. It will be dropped instead of buffered and processed after the ChangeCipherSpec, if it arrives before the ServerHello, when it obviously can't belong to the current handshake. Otherwise the connection fails with unexpected message. Thanks to Daniel Mentz for providing hints! --- crypto/bio/bss_dgram.c 18 May 2009 16:11:58 - 1.7.2.12 +++ crypto/bio/bss_dgram.c 4 Jun 2009 19:59:10 - @@ -220,9 +220,10 @@ /* Adjust socket timeout if next handhake message timer * will expire earlier. */ - if (data-socket_timeout.tv_sec timeleft.tv_sec || + if ((data-socket_timeout.tv_sec == 0 data- socket_timeout.tv_usec == 0) || + (data-socket_timeout.tv_sec timeleft.tv_sec) || (data-socket_timeout.tv_sec == timeleft.tv_sec -data-socket_timeout.tv_usec = timeleft.tv_usec)) +data-socket_timeout.tv_usec = timeleft.tv_usec)) { #ifdef OPENSSL_SYS_WINDOWS timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; --- ssl/d1_both.c 16 May 2009 16:22:11 - 1.14.2.9 +++ ssl/d1_both.c 4 Jun 2009 19:59:11 - @@ -569,9 +569,13 @@ item = pqueue_find(s-d1-buffered_messages, seq64be); /* Discard the message if sequence number was already there, is -* too far in the future or the fragment is already in the queue */ +* too far in the future, already in the queue or if we received +* a FINISHED before the SERVER_HELLO, which then must be a stale +* retransmit. +*/ if (msg_hdr-seq = s-d1-handshake_read_seq || - msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL) + msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL || + s-d1-handshake_read_seq == 0 msg_hdr-type == SSL3_MT_FINISHED) { unsigned char devnull [256]; --- ssl/d1_clnt.c 31 May 2009 17:11:24 - 1.16.2.8 +++ ssl/d1_clnt.c 4 Jun 2009 19:59:12 - @@ -442,7 +442,7 @@ case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - + s-d1-change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret = 0) goto end; --- ssl/d1_pkt.c16 May 2009 16:17:46 - 1.27.2.8 +++ ssl/d1_pkt.c4 Jun 2009 19:59:12 - @@ -1102,6 +1102,16 @@ s-msg_callback(0, s-version, SSL3_RT_CHANGE_CIPHER_SPEC, rr-data, 1, s, s-msg_callback_arg); + /* We can't process a CCS now, because previous handshake +* messages are still missing, so just drop it. +*/ + if (!s-d1-change_cipher_spec_ok) + { + goto start; + } + + s-d1-change_cipher_spec_ok = 0; + s-s3-change_cipher_spec=1; if (!ssl3_do_change_cipher_spec(s)) goto err; --- ssl/d1_srvr.c 31 May 2009 17:11:24 - 1.20.2.5 +++ ssl/d1_srvr.c 4 Jun 2009 19:59:13 - @@ -501,6 +501,7 @@ ret=ssl3_get_cert_verify(s); if (ret = 0) goto end; dtls1_stop_timer(s); + s-d1-change_cipher_spec_ok = 1; s-state=SSL3_ST_SR_FINISHED_A; s-init_num=0; @@ -508,6 +509,7 @@ case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: + s-d1-change_cipher_spec_ok = 1; ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); if (ret = 0) goto end; --- ssl/dtls1.h 2 Jun 2009 11:23:30 - 1.12.2.9 +++ ssl/dtls1.h 4 Jun 2009 19:59:13 - @@ -231,6 +231,7 @@ unsigned int handshake_fragment_len; unsigned int retransmitting; + unsigned int
Re: [openssl.org #1922] [PATCH] DTLS Timer Bug
On May 16, 2009, at 2:08 PM, Stephen Henson via RT wrote: [seggelm...@fh-muenster.de - Sat May 16 12:13:35 2009]: Patch applied to 1.0.0 and HEAD. Should this go into 0.9.8 too? Thanks for applying. Yes, this is important for 0.9.8, too. Every patch for DTLS I submitted concerns both branches, there are no differences so far. The patch doesn't apply cleanly to 0.9.8 but a minor manual change fixes that. However I've noticed the patch break compilation in 1.0.0 with a compilation failure in bss_dgram.c: bss_dgram.c:292: structure has no member named `hstimeout' I've commented out the errant line for now. Please check if this is the right thing to do. You can safely delete this line, the patch should have removed it anyway. Seems that this didn't work for some reason. Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1931] [PATCH] DTLS fragment handling memory leak
On May 17, 2009, at 6:46 PM, Stephen Henson via RT wrote: [steve - Sat May 16 18:28:06 2009]: Patch applied to 1.0, HEAD and 0.9.8. Thanks for the report. Patch reverted on 0.9.8, it breaks compilation. Please supply a version for 0.9.8. The 0.9.8 version: --- ssl/d1_both.c 2009-05-18 09:57:08.0 +0200 +++ ssl/d1_both.c 2009-05-18 10:08:51.0 +0200 @@ -561,7 +561,16 @@ if ((msg_hdr-frag_off+frag_len) msg_hdr-msg_len) goto err; - if (msg_hdr-seq = s-d1-handshake_read_seq) + /* Try to find item in queue, to prevent duplicate entries */ + pq_64bit_init(seq64); + pq_64bit_assign_word(seq64, msg_hdr-seq); + item = pqueue_find(s-d1-buffered_messages, seq64); + pq_64bit_free(seq64); + + /* Discard the message if sequence number was already there, is +* too far in the future or the fragment is already in the queue */ + if (msg_hdr-seq = s-d1-handshake_read_seq || + msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL) { unsigned char devnull [256]; dtls-fragment-memleak-bug.patch Description: Binary data
Re: [openssl.org #1929] DTLS MTU bug
On May 17, 2009, at 6:44 PM, Stephen Henson via RT wrote: Ooops, missed the attachment. Patch now applied to 1.0.0-beta and HEAD. A modified version was applied to 0.9.8, please check that is OK. The only problem I found was a variable name in apps/s_server.c and apps/s_client.c, that is 'mtu' in 0.9.8 and 'socket_mtu in 1.0.0. You apparently solved it by renaming the variable in 0.9.8 which should be ok. Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1922] [PATCH] DTLS Timer Bug
Patch applied to 1.0.0 and HEAD. Should this go into 0.9.8 too? Thanks for applying. Yes, this is important for 0.9.8, too. Every patch for DTLS I submitted concerns both branches, there are no differences so far. Robin __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1930] [PATCH] DTLS record buffer limitation bug
Records are buffered if they arrive with a future epoch to be processed after finishing the corresponding handshake. There is currently no limitation to this buffer allowing an attacker to perform a DOS attack with sending records with future epochs until there is no memory left. This patch adds the pqueue_size() function to detemine the size of a buffer and limits the record buffer to 100 entries. Thanks to Daniel Mentz for finding this bug! --- crypto/pqueue/pqueue.c 2005-12-20 08:03:10.0 +0100 +++ crypto/pqueue/pqueue.c 2009-05-15 16:07:33.0 +0200 @@ -237,3 +237,17 @@ return ret; } + +int +pqueue_size(pqueue_s *pq) +{ + pitem *item = pq-items; + int count = 0; + + while(item != NULL) + { + count++; + item = item-next; + } + return count; +} --- crypto/pqueue/pqueue.h 2005-06-08 00:21:14.0 +0200 +++ crypto/pqueue/pqueue.h 2009-05-15 16:07:03.0 +0200 @@ -89,5 +89,6 @@ pitem *pqueue_next(piterator *iter); void pqueue_print(pqueue pq); +int pqueue_size(pqueue pq); #endif /* ! HEADER_PQUEUE_H */ --- ssl/d1_pkt.c2009-04-23 18:32:40.0 +0200 +++ ssl/d1_pkt.c2009-05-15 16:06:23.0 +0200 @@ -207,6 +207,10 @@ DTLS1_RECORD_DATA *rdata; pitem *item; + /* Limit the size of the queue to prevent DOS attacks */ + if (pqueue_size(queue-q) = 100) + return 0; + rdata = OPENSSL_malloc(sizeof(DTLS1_RECORD_DATA)); item = pitem_new(priority, rdata); if (rdata == NULL || item == NULL) dtls-record-buffer-bug-1.0.0.patch Description: Binary data
[openssl.org #1931] [PATCH] DTLS fragment handling memory leak
In dtls1_process_out_of_seq_message() the check if the current message is already buffered was missing. For every new message was memory allocated, allowing an attacker to perform an denial of service attack with sending out of seq handshake messages until there is no memory left. Additionally every future messege was buffered, even if the sequence number made no sense and would be part of another handshake. So only messages with sequence numbers less than 10 in advance will be buffered. Thanks to Daniel Mentz for finding this bug! --- ssl/d1_both.c 2009-04-19 20:03:11.0 +0200 +++ ssl/d1_both.c 2009-05-12 10:15:35.0 +0200 @@ -561,7 +561,16 @@ if ((msg_hdr-frag_off+frag_len) msg_hdr-msg_len) goto err; - if (msg_hdr-seq = s-d1-handshake_read_seq) + /* Try to find item in queue, to prevent duplicate entries */ + memset(seq64be,0,sizeof(seq64be)); + seq64be[6] = (unsigned char) (msg_hdr-seq8); + seq64be[7] = (unsigned char) msg_hdr-seq; + item = pqueue_find(s-d1-buffered_messages, seq64be); + + /* Discard the message if sequence number was already there, is +* too far in the future or the fragment is already in the queue */ + if (msg_hdr-seq = s-d1-handshake_read_seq || + msg_hdr-seq s-d1-handshake_read_seq + 10 || item != NULL) { unsigned char devnull [256]; __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
Re: [openssl.org #1922] [PATCH] DTLS Timer Bug
I have just found the new get_current_time() function in bss_dgram.c and modified the patch so that it will be used. Additionally I have copied this function to d1_lib.c and made the timer functions there use it to avoid redundant code. dtls-timer-bug-1.0.0.patch Description: Binary data
[openssl.org #1922] [PATCH] DTLS Timer Bug
This patch is broken due to line wrap issues. Try a plain text attachment or if that fails a gziped one. Ok, let's try a plain text attachment... Some of the changes break source compatibility with previous versions of the patch. That's ok for now but once this stuff appears in a released version no such changes are permissible as they would break applications. I don't know what exactly you mean. There are no changes to the api or any behavior noticable by the user. Actually, I mostly just moved code and renamed some internal functions that weren't accessible to or intended for the user anyway. dtls-timer-bug-1.0.0.patch Description: Binary data
Re: [openssl.org #1922] [PATCH] DTLS Timer Bug
OK that's better but the patch doesn't apply cleanly to 1.0.0-stable: getting rejects in bss_dgram.c Oh, I was still using beta 2 to create the patches and haven't noticed the changes you made in the meantime. Here is a new version attached. It was the change of the name of BIO_CTRL_DGRAM_SET_TIMEOUT in a public header. Ok. The name change was not really necessary, I just wanted to have similar names for the timer related variables and constants. This option is not intended to be used by the user anyway, that's the reason why I didn't consider a change to cause any problems. Robin dtls-timer-bug-1.0.0.patch Description: Binary data
[openssl.org #1923] dtls1_retrieve_buffered_fragment: Read from freed data structure
This suggested patch is not conform to ANSI C. The declaration of variables always has to be done at the beginning of their scope: --- ssl/d1_both.c 2009-04-19 20:03:11.0 +0200 +++ ssl/d1_both.c 2009-05-12 09:23:30.0 +0200 @@ -519,6 +519,8 @@ if ( s-d1-handshake_read_seq == frag-msg_header.seq) { + unsigned long frag_len = frag-msg_header.frag_len; + pqueue_pop(s-d1-buffered_messages); al=dtls1_preprocess_fragment(s,frag-msg_header,max); @@ -536,7 +538,7 @@ if (al==0) { *ok = 1; - return frag-msg_header.frag_len; + return frag_len; } ssl3_send_alert(s,SSL3_AL_FATAL,al); __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1922] [PATCH] DTLS Timer Bug
I have updated the last patch, considering the suggestions of Daniel Mentz. The previous solutions were done in the BIO object, which was not a good choice. Additionally they didn't allow non-blocking sockets to be used. This approach doesn't rely on socket errors anymore. The timer stuff is completely rewritten and now part of the DTLS implementation, where it belongs to. If a timer is started, it also tells the BIO object when it will expire, so that the BIO object is able to adjust its sockets timeouts if necessary. This prevents needless waiting time during handshakes if the socket timeouts are set too generous by the user or the socket timer starts just before the message timer is about to expire. With every retransmission the duration of the timer is doubled up to 60 seconds unless the expected message arrived. Non- Blocking sockets shouldn't be problem anymore, too. --- crypto/bio/bio.h2009-04-14 16:33:12.0 +0200 +++ crypto/bio/bio.h2009-05-12 10:20:24.0 +0200 @@ -159,7 +159,8 @@ #define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */ -#define BIO_CTRL_DGRAM_SET_TIMEOUT45 +#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to + * adjust socket timeouts */ /* modifiers */ #define BIO_FP_READ 0x02 --- crypto/bio/bss_dgram.c 2009-04-14 17:13:35.0 +0200 +++ crypto/bio/bss_dgram.c 2009-05-12 11:08:04.0 +0200 @@ -108,8 +108,8 @@ unsigned int connected; unsigned int _errno; unsigned int mtu; - struct timeval hstimeoutdiff; - struct timeval hstimeout; + struct timeval next_timeout; + struct timeval socket_timeout; } bio_dgram_data; BIO_METHOD *BIO_s_datagram(void) @@ -171,7 +171,95 @@ } return(1); } - + +static void dgram_adjust_rcv_timeout(BIO *b) + { +#if defined(SO_RCVTIMEO) + bio_dgram_data *data = (bio_dgram_data *)b-ptr; + int sz = sizeof(int); + + /* Is a timer active? */ + if (data-next_timeout.tv_sec 0 || data-next_timeout.tv_usec 0) + { + struct timeval timenow, timeleft; + + /* Read current socket timeout */ +#ifdef OPENSSL_SYS_WINDOWS + struct _timeb tb; + int timeout; + if (getsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, + (void*)timeout, sz) 0) + { perror(getsockopt); } + else + { + data-socket_timeout.tv_sec = timeout / 1000; + data-socket_timeout.tv_usec = (timeout % 1000) * 1000; + } +#else + if ( getsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, + (data-socket_timeout), (void *)sz) 0) + { perror(getsockopt); } +#endif + + /* Get current time */ +#ifdef OPENSSL_SYS_WIN32 + _ftime(tb); + timenow.tv_sec = (long) tb.time; + timenow.tv_usec = (long) tb.millitm * 1000; +#else + gettimeofday(timenow, NULL); +#endif + + /* Calculate time left until timer expires */ + memcpy(timeleft, (data-next_timeout), sizeof(struct timeval)); + timeleft.tv_sec -= timenow.tv_sec; + timeleft.tv_usec -= timenow.tv_usec; + if (timeleft.tv_usec 0) + { + timeleft.tv_sec--; + timeleft.tv_usec += 100; + } + + /* Adjust socket timeout if next handhake message timer +* will expire earlier. +*/ + if (data-socket_timeout.tv_sec timeleft.tv_sec || + (data-socket_timeout.tv_sec == timeleft.tv_sec +data-socket_timeout.tv_usec = timeleft.tv_usec)) + { +#ifdef OPENSSL_SYS_WINDOWS + timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; + if (setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, + (void*)timeout, sizeof(timeout)) 0) + { perror(setsockopt); } +#else + if ( setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, timeleft, + sizeof(struct timeval)) 0) + { perror(setsockopt); } +#endif + } + } +#endif + } + +static void dgram_reset_rcv_timeout(BIO *b) + { +#if defined(SO_RCVTIMEO) + bio_dgram_data *data = (bio_dgram_data *)b-ptr; +#ifdef OPENSSL_SYS_WINDOWS + int timeout = data-socket_timeout.tv_sec * 1000 + +
[openssl.org #1922] [PATCH] DTLS Timer Bug
This patch fixes a bug when checking if the additional timer for handshake messages is expired. The timeval structs were not compared in the right way. According to the RFC 4347, timers should be initialized with 1 second and doubled after each timeout up to 60 seconds. This behavior is also added, instead of always using the same value. After receiving or sending sucessfully, the corresponding timer is set to its initial value. Timers are always used and the default initial values are 1 second, so the user doesn't have to activate the timers manually. However, he is able to use the known BIO_cntl options to modify the initial values. In the end, the receiving socket timeout is adjusted if the timer for an expected handshake message will expire earlier. --- crypto/bio/bss_dgram.c 2009-04-14 17:13:35.0 +0200 +++ crypto/bio/bss_dgram.c 2009-05-08 11:50:11.0 +0200 @@ -108,8 +108,11 @@ unsigned int connected; unsigned int _errno; unsigned int mtu; - struct timeval hstimeoutdiff; - struct timeval hstimeout; + struct timeval initialtrcvtimeout; + struct timeval initialtsndtimeout; + struct timeval rcvtimeout; + struct timeval sndtimeout; + struct timeval nextrcvtimeout; } bio_dgram_data; BIO_METHOD *BIO_s_datagram(void) @@ -137,9 +140,19 @@ if (data == NULL) return 0; memset(data, 0x00, sizeof(bio_dgram_data)); -bi-ptr = data; - + bi-ptr = data; bi-flags=0; + + /* initialize timeouts */ + memset((data-initialtrcvtimeout), 0, sizeof(struct timeval)); + data-initialtrcvtimeout.tv_sec = 1; + memset((data-initialtsndtimeout), 0, sizeof(struct timeval)); + data-initialtsndtimeout.tv_sec = 1; + memset((data-rcvtimeout), 0, sizeof(struct timeval)); + data-rcvtimeout.tv_sec = 1; + memset((data-sndtimeout), 0, sizeof(struct timeval)); + data-sndtimeout.tv_sec = 1; + return(1); } @@ -174,7 +187,8 @@ static int dgram_read(BIO *b, char *out, int outl) { - int ret=0; + int ret=0, timeout = 0; + struct timeval settimeout; bio_dgram_data *data = (bio_dgram_data *)b-ptr; struct sockaddr peer; @@ -184,6 +198,62 @@ { clear_socket_error(); memset(peer, 0x00, peerlen); + + /* Set timeout */ + memcpy(settimeout, (data-rcvtimeout), sizeof(struct timeval)); + + /* If the time left for a handshake message is smaller than the +* socket timeout, set the socket timeout to the remaining time. +*/ + if (data-nextrcvtimeout.tv_sec 0 || data-nextrcvtimeout.tv_usec 0) + { + struct timeval curtime, cmptime; +#ifdef OPENSSL_SYS_WIN32 + struct _timeb tb; + _ftime(tb); + curtime.tv_sec = (long)tb.time; + curtime.tv_usec = (long)tb.millitm * 1000; +#else + gettimeofday(curtime, NULL); +#endif + memcpy(cmptime, (data-nextrcvtimeout), sizeof(struct timeval)); + cmptime.tv_sec = cmptime.tv_sec - curtime.tv_sec; + cmptime.tv_usec = cmptime.tv_usec - curtime.tv_usec; + if (cmptime.tv_usec 0) + { + cmptime.tv_sec--; + cmptime.tv_usec += 100; + } + if (cmptime.tv_sec 0) + { + cmptime.tv_sec = 0; + cmptime.tv_usec = 1; + } + + if (cmptime.tv_sec settimeout.tv_sec || + (cmptime.tv_sec == settimeout.tv_sec +cmptime.tv_usec = settimeout.tv_usec)) + { + memcpy(settimeout, cmptime, sizeof(struct timeval)); + } + + } + +#if defined(SO_RCVTIMEO) +#ifdef OPENSSL_SYS_WINDOWS + { + timeout = settimeout.tv_sec * 1000 + settimeout.tv_usec/1000; + if (setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, + (void*)timeout, sizeof(timeout)) 0) + { perror(setsockopt); ret = -1; } + } +#else + if ( setsockopt(b-num, SOL_SOCKET, SO_RCVTIMEO, settimeout, + sizeof(struct timeval)) 0) + { perror(setsockopt); ret = -1; } +#endif +#endif +
[openssl.org #1830] [PATCH] TLS Key Material Extractor
The compatibility with 1.0.0beta1 required more changes than I thought...the function tls1_PRF was modified significantly. So here's a working version of the patch: --- ssl/ssl.h 2008-12-27 03:09:23.0 +0100 +++ ssl/ssl.h 2009-04-17 11:03:58.0 +0200 @@ -1770,6 +1770,10 @@ /* Pre-shared secret session resumption functions */ int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); +void SSL_tls1_key_extractor(SSL *s, unsigned char *label, int label_len, + unsigned char *context, int context_len, + unsigned char *out, int olen); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. --- ssl/t1_enc.c2009-01-11 21:34:23.0 +0100 +++ ssl/t1_enc.c2009-04-17 11:06:30.0 +0200 @@ -1006,3 +1006,17 @@ } } +void SSL_tls1_key_extractor(SSL *s, unsigned char *label, int label_len, + unsigned char *context, int context_len, + unsigned char *out, int olen) + { + unsigned char tmp[olen]; + + tls1_PRF(s-s3-tmp.new_cipher-algorithm2, +label, label_len, +s-s3-client_random,SSL3_RANDOM_SIZE, +s-s3-server_random,SSL3_RANDOM_SIZE, +context, context_len, NULL, 0, +s-session-master_key, s-session-master_key_length, +out, tmp, olen); + } __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1830] [PATCH] TLS Key Material Extractor
Updated version for compatibility with 1.0.0beta1: --- ssl/ssl.h 2008-12-27 03:09:23.0 +0100 +++ ssl/ssl.h 2009-04-16 10:14:12.0 +0200 @@ -1770,6 +1770,10 @@ /* Pre-shared secret session resumption functions */ int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); +void SSL_tls1_key_extractor(SSL *s, unsigned char *label, int label_len, + unsigned char *context, int context_len, + unsigned char *out, int olen); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. --- ssl/t1_enc.c2009-01-11 21:34:23.0 +0100 +++ ssl/t1_enc.c2009-04-16 10:14:12.0 +0200 @@ -1006,3 +1006,24 @@ } } +void SSL_tls1_key_extractor(SSL *s, unsigned char *label, int label_len, + unsigned char *context, int context_len, + unsigned char *out, int olen) + { + unsigned char buf[label_len + 2 * SSL3_RANDOM_SIZE + context_len]; + unsigned char tmp[olen], *p; + + p = buf; + memcpy(p, label, label_len); + p += label_len; + memcpy(p, s-s3-client_random, SSL3_RANDOM_SIZE); + p += SSL3_RANDOM_SIZE; + memcpy(p, s-s3-server_random, SSL3_RANDOM_SIZE); + p += SSL3_RANDOM_SIZE; + memcpy(p, context, context_len); + + tls1_PRF(s-ctx-md5,s-ctx-sha1,buf,sizeof(buf), +s-session-master_key,s-session-master_key_length, +out, tmp,olen); + } + __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1833] [PATCH] Abbreviated Renegotiations
Updated version for compatibility with 1.0.0beta1: --- ssl/d1_clnt.c 2008-06-02 00:33:24.0 +0200 +++ ssl/d1_clnt.c 2009-04-16 09:41:59.0 +0200 @@ -169,7 +169,7 @@ switch(s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; s-state=SSL_ST_CONNECT; s-ctx-stats.sess_connect_renegotiate++; /* break */ @@ -476,7 +476,7 @@ /* else do it later in ssl3_write */ s-init_num=0; - s-new_session=0; + s-renegotiate=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); if (s-hit) s-ctx-stats.sess_hit++; --- ssl/d1_pkt.c2008-12-29 17:11:57.0 +0100 +++ ssl/d1_pkt.c2009-04-16 09:41:59.0 +0200 @@ -1086,7 +1086,7 @@ #else s-state = s-server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; #endif - s-new_session=1; + s-renegotiate=1; } i=s-handshake_func(s); if (i 0) return(i); --- ssl/d1_srvr.c 2008-09-14 16:02:07.0 +0200 +++ ssl/d1_srvr.c 2009-04-16 09:41:59.0 +0200 @@ -178,7 +178,7 @@ switch (s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; /* s-state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: @@ -269,7 +269,7 @@ s-shutdown=0; ret=ssl3_get_client_hello(s); if (ret = 0) goto end; - s-new_session = 2; + s-renegotiate = 2; if (s-d1-send_cookie) s-state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; @@ -533,12 +533,12 @@ s-init_num=0; - if (s-new_session == 2) /* skipped if we just sent a HelloRequest */ + if (s-renegotiate == 2) /* skipped if we just sent a HelloRequest */ { /* actually not necessarily a 'new' session unless * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ - s-new_session=0; + s-renegotiate=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); --- ssl/s3_clnt.c 2009-02-14 22:49:38.0 +0100 +++ ssl/s3_clnt.c 2009-04-16 09:41:59.0 +0200 @@ -211,7 +211,7 @@ switch(s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; s-state=SSL_ST_CONNECT; s-ctx-stats.sess_connect_renegotiate++; /* break */ @@ -548,7 +548,7 @@ /* else do it later in ssl3_write */ s-init_num=0; - s-new_session=0; + s-renegotiate=0; ssl_update_cache(s,SSL_SESS_CACHE_CLIENT); if (s-hit) s-ctx-stats.sess_hit++; --- ssl/s3_pkt.c2009-01-28 08:09:23.0 +0100 +++ ssl/s3_pkt.c2009-04-16 09:41:59.0 +0200 @@ -1212,7 +1212,7 @@ #else s-state = s-server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; #endif - s-new_session=1; + s-renegotiate=1; } i=s-handshake_func(s); if (i 0) return(i); --- ssl/s3_srvr.c 2009-01-08 00:44:27.0 +0100 +++ ssl/s3_srvr.c 2009-04-16 09:43:34.0 +0200 @@ -219,7 +219,7 @@ switch (s-state) { case SSL_ST_RENEGOTIATE: - s-new_session=1; + s-renegotiate=1; /* s-state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: @@ -305,7 +305,7 @@ ret=ssl3_get_client_hello(s); if (ret = 0) goto end; - s-new_session = 2; + s-renegotiate = 2; s-state=SSL3_ST_SW_SRVR_HELLO_A; s-init_num=0; break; @@ -650,12 +650,12 @@ s-init_num=0; - if (s-new_session == 2) /* skipped if we just sent a HelloRequest */ + if (s-renegotiate == 2) /*
[openssl.org #1900] FreeBSD compile problem with _XOPEN_SOURCE defined
In ssl/kssl.c the constant _XOPEN_SOURCE is defined which results in using an old POSIX version and compilation problems on recent FreeBSD systems when adding SCTP support (necessary for SCTP-aware DTLS). With _XOPEN_SOURCE defined to 500, in sys/cdefs.h the constant _POSIX_C_SOURCE will get the value 199506 instead of 200112. The constant __POSIX_VISIBLE then gets the same value, so an old POSIX version will be assumed. This is not only needless, it also is a problem when including netinet/sctp.h to use SCTP. In this header file the structure sin6 is needed, which is defined in netinet/in6.h that gets included by netinet/in.h, but only when #if __POSIX_VISIBLE = 200112 is true. Hence, defining _XOPEN_SOURCE to 500 makes it impossible to use SCTP, even if the constant is undefined afterwards. A solution is to assign at least 600, then the following constants will be set correctly. This should make no difference for its original purpose, because glibc2 seems to only need _XOPEN_SOURCE defined somehow. __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1900] FreeBSD compile problem with _XOPEN_SOURCE defined
The corresponding patch for 0.9.8 and 1.0.0: --- ssl/kssl.c 2009-02-14 22:49:38.0 +0100 +++ ssl/kssl.c 2009-04-16 13:30:18.0 +0200 @@ -68,7 +68,7 @@ #include openssl/opensslconf.h -#define _XOPEN_SOURCE 500 /* glibc2 needs this to declare strptime() */ +#define _XOPEN_SOURCE 600 /* glibc2 needs this to declare strptime() */ #include time.h #if 0 /* Experimental */ #undef _XOPEN_SOURCE /* To avoid clashes with anything else... */ __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1900] FreeBSD compile problem with _XOPEN_SOURCE defined
I just had another look at the code in ssl/kssl.c and didn't find any use of strptime(). The header file time.h doesn't need to be included at all, because there is nothing (left) requiring it. So the code should be removed. --- ssl/kssl.c 2009-02-14 22:49:38.0 +0100 +++ ssl/kssl.c 2009-04-16 16:50:28.0 +0200 @@ -68,11 +68,6 @@ #include openssl/opensslconf.h -#define _XOPEN_SOURCE 500 /* glibc2 needs this to declare strptime() */ -#include time.h -#if 0 /* Experimental */ -#undef _XOPEN_SOURCE /* To avoid clashes with anything else... */ -#endif #include string.h #define KRB5_PRIVATE 1 __ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager majord...@openssl.org
[openssl.org #1828] [PATCH] DTLS Retransmission Bug
This updated version addresses (hopefully) all changes made to struct sst_st in 1.0.0beta1 to save/restore the state correctly. --- ssl/d1_both.c 2007-10-17 23:15:48.0 +0200 +++ ssl/d1_both.c 2009-04-14 11:56:36.0 +0200 @@ -136,7 +136,6 @@ static void dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, unsigned short seq_num, unsigned long frag_off, unsigned long frag_len); -static int dtls1_retransmit_buffered_messages(SSL *s); static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok); @@ -931,8 +930,21 @@ return dtls1_retransmit_buffered_messages(s) ; } +int +dtls1_get_queue_priority(unsigned short seq, int is_ccs) + { + /* The index of the retransmission queue actually is the message sequence number, +* since the queue only contains messages of a single handshake. However, the +* ChangeCipherSpec has no message sequence number and so using only the sequence +* will result in the CCS and Finished having the same index. To prevent this, +* the sequence number is multiplied by 2. In case of a CCS 1 is subtracted. +* This does not only differ CSS and Finished, it also maintains the order of the +* index (important for priority queues) and fits in the unsigned short variable. +*/ + return seq * 2 - is_ccs; + } -static int +int dtls1_retransmit_buffered_messages(SSL *s) { pqueue sent = s-d1-sent_messages; @@ -946,8 +958,9 @@ for ( item = pqueue_next(iter); item != NULL; item = pqueue_next(iter)) { frag = (hm_fragment *)item-data; - if ( dtls1_retransmit_message(s, frag-msg_header.seq, 0, found) = 0 - found) + if ( dtls1_retransmit_message(s, + dtls1_get_queue_priority(frag-msg_header.seq, frag- msg_header.is_ccs), + 0, found) = 0 found) { fprintf(stderr, dtls1_retransmit_message() failed\n); return -1; @@ -963,7 +976,6 @@ pitem *item; hm_fragment *frag; unsigned char seq64be[8]; - unsigned int epoch = s-d1-w_epoch; /* this function is called immediately after a message has * been serialized */ @@ -977,7 +989,6 @@ { OPENSSL_assert(s-d1-w_msg_hdr.msg_len + DTLS1_CCS_HEADER_LENGTH == (unsigned int)s-init_num); - epoch++; } else { @@ -992,11 +1003,18 @@ frag-msg_header.frag_len = s-d1-w_msg_hdr.msg_len; frag-msg_header.is_ccs = is_ccs; + /* save current state*/ + frag-msg_header.saved_retransmit_state.enc_write_ctx = s- enc_write_ctx; + frag-msg_header.saved_retransmit_state.write_hash = s-write_hash; + frag-msg_header.saved_retransmit_state.compress = s-compress; + frag-msg_header.saved_retransmit_state.session = s-session; + frag-msg_header.saved_retransmit_state.epoch = s-d1-w_epoch; + memset(seq64be,0,sizeof(seq64be)); - seq64be[0] = (unsigned char)(epoch8); - seq64be[1] = (unsigned char)(epoch); - seq64be[6] = (unsigned char)(frag-msg_header.seq8); - seq64be[7] = (unsigned char)(frag-msg_header.seq); + seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag- msg_header.seq, + frag-msg_header.is_ccs)8); + seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag- msg_header.seq, + frag-msg_header.is_ccs)); item = pitem_new(seq64be, frag); if ( item == NULL) @@ -1025,6 +1043,8 @@ hm_fragment *frag ; unsigned long header_length; unsigned char seq64be[8]; + struct dtls1_retransmit_state saved_state; + unsigned char save_write_sequence[8]; /* OPENSSL_assert(s-init_num == 0); @@ -1060,9 +1080,45 @@ frag-msg_header.msg_len, frag-msg_header.seq, 0, frag-msg_header.frag_len); + /* save current state */ + saved_state.enc_write_ctx = s-enc_write_ctx; + saved_state.write_hash = s-write_hash; + saved_state.compress = s-compress; + saved_state.session = s-session; + saved_state.epoch = s-d1-w_epoch; + saved_state.epoch = s-d1-w_epoch; + s-d1-retransmitting = 1; + + /* restore state in which the message was originally sent */ + s-enc_write_ctx = frag- msg_header.saved_retransmit_state.enc_write_ctx; + s-write_hash = frag-msg_header.saved_retransmit_state.write_hash; +
[openssl.org #1828] [PATCH] DTLS Retransmission Bug
This updated version includes the suggestions of Nagendra Modadugu. --- ssl/d1_both.c 2007-10-17 23:17:49.0 +0200 +++ ssl/d1_both.c 2009-03-23 19:39:10.0 +0100 @@ -136,7 +136,6 @@ static void dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, unsigned short seq_num, unsigned long frag_off, unsigned long frag_len); -static int dtls1_retransmit_buffered_messages(SSL *s); static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok); @@ -942,8 +941,21 @@ return dtls1_retransmit_buffered_messages(s) ; } +int +dtls1_get_queue_priority(unsigned short seq, int is_ccs) + { + /* The index of the retransmission queue actually is the message sequence number, +* since the queue only contains messages of a single handshake. However, the +* ChangeCipherSpec has no message sequence number and so using only the sequence +* will result in the CCS and Finished having the same index. To prevent this, +* the sequence number is multiplied by 2. In case of a CCS 1 is subtracted. +* This does not only differ CSS and Finished, it also maintains the order of the +* index (important for priority queues) and fits in the unsigned short variable. +*/ + return seq * 2 - is_ccs; + } -static int +int dtls1_retransmit_buffered_messages(SSL *s) { pqueue sent = s-d1-sent_messages; @@ -957,8 +969,9 @@ for ( item = pqueue_next(iter); item != NULL; item = pqueue_next(iter)) { frag = (hm_fragment *)item-data; - if ( dtls1_retransmit_message(s, frag-msg_header.seq, 0, found) = 0 - found) + if ( dtls1_retransmit_message(s, + dtls1_get_queue_priority(frag-msg_header.seq, frag- msg_header.is_ccs), + 0, found) = 0 found) { fprintf(stderr, dtls1_retransmit_message() failed\n); return -1; @@ -974,7 +987,6 @@ pitem *item; hm_fragment *frag; PQ_64BIT seq64; - unsigned int epoch = s-d1-w_epoch; /* this function is called immediately after a message has * been serialized */ @@ -988,7 +1000,6 @@ { OPENSSL_assert(s-d1-w_msg_hdr.msg_len + DTLS1_CCS_HEADER_LENGTH = (unsigned int)s-init_num); - epoch++; } else { @@ -1003,9 +1014,19 @@ frag-msg_header.frag_len = s-d1-w_msg_hdr.msg_len; frag-msg_header.is_ccs = is_ccs; + /* save current state*/ + frag-msg_header.saved_retransmit_state.enc_write_ctx = s- enc_write_ctx; + frag-msg_header.saved_retransmit_state.write_hash = s-write_hash; + frag-msg_header.saved_retransmit_state.compress = s-compress; + frag-msg_header.saved_retransmit_state.session = s-session; + frag-msg_header.saved_retransmit_state.epoch = s-d1-w_epoch; + pq_64bit_init(seq64); - pq_64bit_assign_word(seq64, epoch16 | frag-msg_header.seq); + pq_64bit_assign_word(seq64, + dtls1_get_queue_priority(frag-msg_header.seq, + frag-msg_header.is_ccs)); + item = pitem_new(seq64, frag); pq_64bit_free(seq64); if ( item == NULL) @@ -1034,6 +1055,8 @@ hm_fragment *frag ; unsigned long header_length; PQ_64BIT seq64; + struct dtls1_retransmit_state saved_state; + unsigned char save_write_sequence[8]; /* OPENSSL_assert(s-init_num == 0); @@ -1069,9 +1092,45 @@ frag-msg_header.msg_len, frag-msg_header.seq, 0, frag-msg_header.frag_len); + /* save current state */ + saved_state.enc_write_ctx = s-enc_write_ctx; + saved_state.write_hash = s-write_hash; + saved_state.compress = s-compress; + saved_state.session = s-session; + saved_state.epoch = s-d1-w_epoch; + saved_state.epoch = s-d1-w_epoch; + s-d1-retransmitting = 1; + + /* restore state in which the message was originally sent */ + s-enc_write_ctx = frag- msg_header.saved_retransmit_state.enc_write_ctx; + s-write_hash = frag-msg_header.saved_retransmit_state.write_hash; + s-compress = frag-msg_header.saved_retransmit_state.compress; + s-session = frag-msg_header.saved_retransmit_state.session; + s-d1-w_epoch = frag-msg_header.saved_retransmit_state.epoch; + + if (frag-msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1) + { + memcpy(save_write_sequence, s-s3-write_sequence, sizeof(s-s3-
[openssl.org #1827] [PATCH] DTLS Application Data in Handshake Bug
This updated version includes the suggestions of Nagendra Modadugu. --- ssl/d1_lib.c2008-10-13 08:43:05.0 +0200 +++ ssl/d1_lib.c2009-03-23 18:53:11.0 +0100 @@ -114,6 +114,7 @@ d1-processed_rcds.q=pqueue_new(); d1-buffered_messages = pqueue_new(); d1-sent_messages=pqueue_new(); + d1-buffered_app_data.q=pqueue_new(); if ( s-server) { @@ -121,12 +122,13 @@ } if( ! d1-unprocessed_rcds.q || ! d1-processed_rcds.q -|| ! d1-buffered_messages || ! d1-sent_messages) +|| ! d1-buffered_messages || ! d1-sent_messages || ! d1- buffered_app_data.q) { if ( d1-unprocessed_rcds.q) pqueue_free(d1- unprocessed_rcds.q); if ( d1-processed_rcds.q) pqueue_free(d1-processed_rcds.q); if ( d1-buffered_messages) pqueue_free(d1- buffered_messages); if ( d1-sent_messages) pqueue_free(d1-sent_messages); + if ( d1-buffered_app_data.q) pqueue_free(d1-buffered_app_data.q); OPENSSL_free(d1); return (0); } @@ -175,6 +177,15 @@ } pqueue_free(s-d1-sent_messages); + while ( (item = pqueue_pop(s-d1-buffered_app_data.q)) != NULL) + { + frag = (hm_fragment *)item-data; + OPENSSL_free(frag-fragment); + OPENSSL_free(frag); + pitem_free(item); + } + pqueue_free(s-d1-buffered_app_data.q); + pq_64bit_free((s-d1-bitmap.map)); pq_64bit_free((s-d1-bitmap.max_seq_num)); --- ssl/d1_pkt.c2008-10-13 08:43:06.0 +0200 +++ ssl/d1_pkt.c2009-03-23 18:53:12.0 +0100 @@ -703,6 +703,23 @@ * s-s3-rrec.length, - number of bytes. */ rr = (s-s3-rrec); + /* We are not handshaking and have no data yet, +* so process data buffered during the last handshake +* in advance, if any. +*/ + if (s-state == SSL_ST_OK rr-length == 0) + { + pitem *item; + item = pqueue_pop(s-d1-buffered_app_data.q); + if (item) + { + dtls1_copy_record(s, item); + + OPENSSL_free(item-data); + pitem_free(item); + } + } + /* get new packet if necessary */ if ((rr-length == 0) || (s-rstate == SSL_ST_READ_BODY)) { @@ -724,9 +741,14 @@ * reset by ssl3_get_finished */ (rr-type != SSL3_RT_HANDSHAKE)) { - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); - goto err; + /* We now have application data between CCS and Finished. +* Most likely the packets were reordered on their way, so +* buffer the application data for later processing rather +* than dropping the connection. +*/ + dtls1_buffer_record(s, (s-d1-buffered_app_data), 0); + rr-length = 0; + goto start; } /* If the other end has shut down, throw anything we read away @@ -796,15 +818,28 @@ dest = s-d1-alert_fragment; dest_len = s-d1-alert_fragment_len; } -/* else it's a CCS message, or it's wrong */ -else if (rr-type != SSL3_RT_CHANGE_CIPHER_SPEC) -{ - /* Not certain if this is the right error handling */ - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD); - goto f_err; -} + /* else it's a CCS message, or application data or wrong */ + else if (rr-type != SSL3_RT_CHANGE_CIPHER_SPEC) + { + /* Application data while renegotiating +* is allowed. Try again reading. +*/ + if (rr-type == SSL3_RT_APPLICATION_DATA) + { + BIO *bio; + s-s3-in_read_app_data=2; + bio=SSL_get_rbio(s); + s-rwstate=SSL_READING; + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + return(-1); + } + /* Not certain if this is the right error handling */ + al=SSL_AD_UNEXPECTED_MESSAGE; +