[prev in list] [next in list] [prev in thread] [next in thread]
List: openssl-dev
Subject: Re: [openssl.org #2535] [PATCH] Add SCTP support for DTLS (RFC 6083)
From: "Robin Seggelmann via RT" <rt () openssl ! org>
Date: 2011-05-31 14:55:19
Message-ID: rt-3.4.5-25148-1306853718-811.2535-6-0 () openssl ! org
[Download RAW message or body]
Here is an updated version of the patch, now considering new and deprecated SCTP \
socket API and adding a define necessary for Solaris.
Best regards
Robin
["dtls-sctp-1.0.1.patch" (application/octet-stream)]
--- Configure 26 May 2011 14:19:17 -0000 1.621.2.37.2.7
+++ Configure 31 May 2011 14:50:42 -0000
@@ -10,7 +10,7 @@
# see INSTALL for instructions.
-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] \
[experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] \
[[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] \
[386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] \
os/compiler[:flags]\n"; +my $usage="Usage: Configure [no-<cipher> ...] \
[enable-<cipher> ...] [experimental-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] \
[-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] \
[no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] \
[--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
# Options:
#
@@ -56,6 +56,7 @@
# [no-]zlib [don't] compile support for zlib compression.
# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared
# library and will be loaded in run-time by the OpenSSL library.
+# sctp include SCTP support
# 386 generate 80386 code
# no-sse2 disables IA-32 SSE2 code, above option implies no-sse2
# no-<cipher> build without specified algorithm (rsa, idea, rc5, ...)
@@ -640,6 +641,7 @@
my $no_asm=0;
my $no_dso=0;
my $no_gmp=0;
+my $sctp=0;
my @skip=();
my $Makefile="Makefile";
my $des_locl="crypto/des/des_locl.h";
@@ -823,6 +825,10 @@
# The check for the option is there so scripts aren't
# broken
}
+ elsif (/^sctp$/)
+ {
+ $sctp = 1;
+ }
elsif (/^[-+]/)
{
if (/^-[lL](.*)$/ or /^-Wl,/)
@@ -1341,6 +1347,27 @@
}
}
+if ($sctp)
+ {
+ $openssl_other_defines .= "#define OPENSSL_SCTP\n";
+
+ if ($target =~ /^darwin/ || $target =~ /^debug-darwin/)
+ {
+ $lflags = "$lflags -lsctp";
+ }
+
+ if ($target =~ /^linux/)
+ {
+ $lflags = "$lflags -lsctp";
+ }
+
+ if ($target =~ /^solaris/)
+ {
+ $cflags = "$cflags -D_XPG4_2";
+ $lflags = "$lflags -lsctp";
+ }
+ }
+
$cpuid_obj.=" uplink.o uplink-cof.o" if ($cflags =~ /\-DOPENSSL_USE_APPLINK/);
#
@@ -1826,6 +1853,7 @@
print "RC2 uses u$type[$rc2_int]\n" if $rc2_int != $def_int;
print "BF_PTR used\n" if $bf_ptr == 1;
print "BF_PTR2 used\n" if $bf_ptr == 2;
+print "SCTP used\n" if $sctp;
if($IsMK1MF) {
open (OUT,">crypto/buildinf.h") || die "Can't open buildinf.h";
--- crypto/bio/bio.h 4 Sep 2009 17:42:05 -0000 1.76.2.5
+++ crypto/bio/bio.h 31 May 2011 14:50:42 -0000
@@ -68,6 +68,10 @@
#include <openssl/crypto.h>
+#ifdef OPENSSL_SCTP
+#include <stdint.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -95,6 +99,9 @@
#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */
#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
+#ifdef OPENSSL_SCTP
+#define BIO_TYPE_DGRAM_SCTP (24|0x0400|0x0100)
+#endif
#define BIO_TYPE_ASN1 (22|0x0200) /* filter */
#define BIO_TYPE_COMP (23|0x0200) /* filter */
@@ -161,7 +168,22 @@
#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */
#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to
- * adjust socket timeouts */
+ * adjust socket timeouts */
+
+#ifdef OPENSSL_SCTP
+/* SCTP stuff */
+#define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50
+#define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51
+#define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52
+#define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53
+#define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60
+#define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61
+#define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62
+#define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63
+#define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64
+#define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65
+#define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70
+#endif
/* modifiers */
#define BIO_FP_READ 0x02
@@ -322,6 +344,34 @@
/* Prefix and suffix callback in ASN1 BIO */
typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+#ifdef OPENSSL_SCTP
+/* SCTP parameter structs */
+struct bio_dgram_sctp_sndinfo
+ {
+ uint16_t snd_sid;
+ uint16_t snd_flags;
+ uint32_t snd_ppid;
+ uint32_t snd_context;
+ };
+
+struct bio_dgram_sctp_rcvinfo
+ {
+ uint16_t rcv_sid;
+ uint16_t rcv_ssn;
+ uint16_t rcv_flags;
+ uint32_t rcv_ppid;
+ uint32_t rcv_tsn;
+ uint32_t rcv_cumtsn;
+ uint32_t rcv_context;
+ };
+
+struct bio_dgram_sctp_prinfo
+ {
+ uint16_t pr_policy;
+ uint32_t pr_value;
+ };
+#endif
+
/* connect BIO stuff */
#define BIO_CONN_S_BEFORE 1
#define BIO_CONN_S_GET_IP 2
@@ -619,6 +669,9 @@
BIO_METHOD *BIO_f_nbio_test(void);
#ifndef OPENSSL_NO_DGRAM
BIO_METHOD *BIO_s_datagram(void);
+#ifdef OPENSSL_SCTP
+BIO_METHOD *BIO_s_datagram_sctp(void);
+#endif
#endif
/* BIO_METHOD *BIO_f_ber(void); */
@@ -661,6 +714,14 @@
BIO *BIO_new_socket(int sock, int close_flag);
BIO *BIO_new_dgram(int fd, int close_flag);
+#ifdef OPENSSL_SCTP
+BIO *BIO_new_dgram_sctp(int fd, int close_flag);
+int BIO_dgram_sctp_notification_cb(BIO *b,
+ void (*handle_notifications)(BIO *bio, void \
*context, void *buf), + void *context);
+int BIO_dgram_sctp_wait_for_dry(BIO *b);
+int BIO_dgram_sctp_msg_waiting(BIO *b);
+#endif
BIO *BIO_new_fd(int fd, int close_flag);
BIO *BIO_new_connect(char *host_port);
BIO *BIO_new_accept(char *host_port);
--- crypto/bio/bss_dgram.c 3 Jan 2011 01:07:20 -0000 1.7.2.23.2.1
+++ crypto/bio/bss_dgram.c 31 May 2011 14:50:42 -0000
@@ -70,6 +70,13 @@
#include <sys/timeb.h>
#endif
+#ifdef OPENSSL_SCTP
+#include <netinet/sctp.h>
+#include <fcntl.h>
+#define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00
+#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0
+#endif
+
#ifdef OPENSSL_SYS_LINUX
#define IP_MTU 14 /* linux is lame */
#endif
@@ -88,6 +95,18 @@
static int dgram_free(BIO *data);
static int dgram_clear(BIO *bio);
+#ifdef OPENSSL_SCTP
+static int dgram_sctp_write(BIO *h, const char *buf, int num);
+static int dgram_sctp_read(BIO *h, char *buf, int size);
+static int dgram_sctp_puts(BIO *h, const char *str);
+static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int dgram_sctp_new(BIO *h);
+static int dgram_sctp_free(BIO *data);
+#ifdef SCTP_AUTHENTICATION_EVENT
+static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification \
*snp); +#endif
+#endif
+
static int BIO_dgram_should_retry(int s);
static void get_current_time(struct timeval *t);
@@ -106,6 +125,22 @@
NULL,
};
+#ifdef OPENSSL_SCTP
+static BIO_METHOD methods_dgramp_sctp=
+ {
+ BIO_TYPE_DGRAM_SCTP,
+ "datagram sctp socket",
+ dgram_sctp_write,
+ dgram_sctp_read,
+ dgram_sctp_puts,
+ NULL, /* dgram_gets, */
+ dgram_sctp_ctrl,
+ dgram_sctp_new,
+ dgram_sctp_free,
+ NULL,
+ };
+#endif
+
typedef struct bio_dgram_data_st
{
union {
@@ -122,11 +157,52 @@
struct timeval socket_timeout;
} bio_dgram_data;
+#ifdef OPENSSL_SCTP
+typedef struct bio_dgram_sctp_save_message_st
+ {
+ BIO *bio;
+ char *data;
+ int length;
+ } bio_dgram_sctp_save_message;
+
+typedef struct bio_dgram_sctp_data_st
+ {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sa_in;
+#if OPENSSL_USE_IPV6
+ struct sockaddr_in6 sa_in6;
+#endif
+ } peer;
+ unsigned int connected;
+ unsigned int _errno;
+ unsigned int mtu;
+ struct bio_dgram_sctp_sndinfo sndinfo;
+ struct bio_dgram_sctp_rcvinfo rcvinfo;
+ struct bio_dgram_sctp_prinfo prinfo;
+ void (*handle_notifications)(BIO *bio, void *context, void *buf);
+ void* notification_context;
+ int in_handshake;
+ int ccs_rcvd;
+ int ccs_sent;
+ int save_shutdown;
+ int peer_auth_tested;
+ bio_dgram_sctp_save_message saved_message;
+ } bio_dgram_sctp_data;
+#endif
+
BIO_METHOD *BIO_s_datagram(void)
{
return(&methods_dgramp);
}
+#ifdef OPENSSL_SCTP
+BIO_METHOD *BIO_s_datagram_sctp(void)
+ {
+ return(&methods_dgramp_sctp);
+ }
+#endif
+
BIO *BIO_new_dgram(int fd, int close_flag)
{
BIO *ret;
@@ -137,6 +213,88 @@
return(ret);
}
+#ifdef OPENSSL_SCTP
+BIO *BIO_new_dgram_sctp(int fd, int close_flag)
+ {
+ BIO *bio;
+ int ret, optval = 20000;
+ int auth_data = 0, auth_forward = 0;
+ unsigned char *p;
+ struct sctp_authchunk auth;
+ struct sctp_authchunks *authchunks;
+ socklen_t sockopt_len;
+#ifdef SCTP_AUTHENTICATION_EVENT
+#ifdef SCTP_EVENT
+ struct sctp_event event;
+#else
+ struct sctp_event_subscribe event;
+#endif
+#endif
+
+ bio=BIO_new(BIO_s_datagram_sctp());
+ if (bio == NULL) return(NULL);
+ BIO_set_fd(bio,fd,close_flag);
+
+ /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
+ auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
+ ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct \
sctp_authchunk)); + OPENSSL_assert(ret >= 0);
+ auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
+ ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct \
sctp_authchunk)); + OPENSSL_assert(ret >= 0);
+
+ /* Test if activation was successful. When using accept(),
+ * SCTP-AUTH has to be activated for the listening socket
+ * already, otherwise the connected socket won't use it. */
+ sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
+ authchunks = OPENSSL_malloc(sockopt_len);
+ memset(authchunks, 0, sizeof(struct sctp_authchunks));
+ ret = sctp_opt_info(fd, 0, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
+ OPENSSL_assert(ret >= 0);
+
+ for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
+ p < (unsigned char*) authchunks + sockopt_len;
+ p += sizeof(uint8_t))
+ {
+ if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
+ if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
+ }
+
+ OPENSSL_free(authchunks);
+
+ OPENSSL_assert(auth_data);
+ OPENSSL_assert(auth_forward);
+
+#ifdef SCTP_AUTHENTICATION_EVENT
+#ifdef SCTP_EVENT
+ memset(&event, 0, sizeof(struct sctp_event));
+ event.se_assoc_id = 0;
+ event.se_type = SCTP_AUTHENTICATION_EVENT;
+ event.se_on = 1;
+ ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
+ OPENSSL_assert(ret >= 0);
+#else
+ sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
+ ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
+ OPENSSL_assert(ret >= 0);
+
+ event.sctp_authentication_event = 1;
+
+ ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct \
sctp_event_subscribe)); + OPENSSL_assert(ret >= 0);
+#endif
+#endif
+
+ /* Disable partial delivery by setting the min size
+ * larger than the max record size of 2^14 + 2048 + 13
+ */
+ ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, \
sizeof(optval)); + OPENSSL_assert(ret >= 0);
+
+ return(bio);
+ }
+#endif
+
static int dgram_new(BIO *bi)
{
bio_dgram_data *data = NULL;
@@ -153,6 +311,27 @@
return(1);
}
+#ifdef OPENSSL_SCTP
+static int dgram_sctp_new(BIO *bi)
+ {
+ bio_dgram_sctp_data *data = NULL;
+
+ bi->init=0;
+ bi->num=0;
+ data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data));
+ if (data == NULL)
+ return 0;
+ memset(data, 0x00, sizeof(bio_dgram_sctp_data));
+#ifdef SCTP_PR_SCTP_NONE
+ data->prinfo.policy = SCTP_PR_SCTP_NONE;
+#endif
+ bi->ptr = data;
+
+ bi->flags=0;
+ return(1);
+ }
+#endif
+
static int dgram_free(BIO *a)
{
bio_dgram_data *data;
@@ -167,6 +346,22 @@
return(1);
}
+#ifdef OPENSSL_SCTP
+static int dgram_sctp_free(BIO *a)
+ {
+ bio_dgram_sctp_data *data;
+
+ if (a == NULL) return(0);
+ if ( ! dgram_clear(a))
+ return 0;
+
+ data = (bio_dgram_sctp_data *)a->ptr;
+ if(data != NULL) OPENSSL_free(data);
+
+ return(1);
+ }
+#endif
+
static int dgram_clear(BIO *a)
{
if (a == NULL) return(0);
@@ -326,6 +521,200 @@
return(ret);
}
+#ifdef OPENSSL_SCTP
+#ifdef SCTP_AUTHENTICATION_EVENT
+void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp)
+ {
+ unsigned int sockopt_len = 0;
+ int ret;
+ struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event;
+
+ if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY)
+ {
+ struct sctp_authkeyid authkeyid;
+
+ /* delete key */
+ authkeyid.scact_keynumber = authkeyevent->auth_keynumber;
+ sockopt_len = sizeof(struct sctp_authkeyid);
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
+ &authkeyid, sockopt_len);
+ }
+ }
+#endif
+
+static int dgram_sctp_read(BIO *b, char *out, int outl)
+ {
+ int ret=0, n=0, i, optval, flags;
+ socklen_t optlen;
+ bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
+ struct sctp_sndrcvinfo sinfo;
+ union sctp_notification *snp;
+
+ if (out != NULL)
+ {
+ clear_socket_error();
+
+ do
+ {
+ memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
+ flags = 0;
+ n=sctp_recvmsg(b->num,(void*) out, outl, NULL, NULL, &sinfo, &flags);
+
+ data->rcvinfo.rcv_sid = sinfo.sinfo_stream;
+ data->rcvinfo.rcv_ssn = sinfo.sinfo_ssn;
+ data->rcvinfo.rcv_flags = sinfo.sinfo_flags;
+ data->rcvinfo.rcv_ppid = sinfo.sinfo_ppid;
+ data->rcvinfo.rcv_tsn = sinfo.sinfo_tsn;
+ data->rcvinfo.rcv_cumtsn = sinfo.sinfo_cumtsn;
+ data->rcvinfo.rcv_context = sinfo.sinfo_context;
+
+ if (n <= 0)
+ {
+ if (n < 0)
+ ret = n;
+ break;
+ }
+
+ if (flags & MSG_NOTIFICATION)
+ {
+ snp = (union sctp_notification*) out;
+ if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
+ {
+#ifdef SCTP_EVENT
+ struct sctp_event event;
+#else
+ struct sctp_event_subscribe event;
+ socklen_t eventsize;
+#endif
+ /* If a message has been delayed until the socket
+ * is dry, it can be sent now.
+ */
+ if (data->saved_message.length > 0)
+ {
+ dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
+ data->saved_message.length);
+ OPENSSL_free(data->saved_message.data);
+ data->saved_message.length = 0;
+ }
+
+ /* disable sender dry event */
+#ifdef SCTP_EVENT
+ memset(&event, 0, sizeof(struct sctp_event));
+ event.se_assoc_id = 0;
+ event.se_type = SCTP_SENDER_DRY_EVENT;
+ event.se_on = 0;
+ i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct \
sctp_event)); + OPENSSL_assert(i >= 0);
+#else
+ eventsize = sizeof(struct sctp_event_subscribe);
+ i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
+ OPENSSL_assert(i >= 0);
+
+ event.sctp_sender_dry_event = 0;
+
+ i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct \
sctp_event_subscribe)); + OPENSSL_assert(i >= 0);
+#endif
+ }
+
+#ifdef SCTP_AUTHENTICATION_EVENT
+ if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
+ dgram_sctp_handle_auth_free_key_event(b, snp);
+#endif
+
+ if (data->handle_notifications != NULL)
+ data->handle_notifications(b, data->notification_context, (void*) out);
+
+ memset(out, 0, outl);
+ }
+ else
+ ret += n;
+ }
+ while ((flags & MSG_NOTIFICATION) && (flags & MSG_EOR) && (ret < outl));
+
+ if (ret > 0 && !(flags & MSG_EOR))
+ {
+ /* Partial message read, this should never happen! */
+
+ /* The buffer was too small, this means the peer sent
+ * a message that was larger than allowed. */
+ if (ret == outl)
+ return -1;
+
+ /* Test if socket buffer can handle max record
+ * size (2^14 + 2048 + 13)
+ */
+ optlen = (socklen_t) sizeof(int);
+ ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
+ OPENSSL_assert(ret >= 0);
+ OPENSSL_assert(optval >= 18445);
+
+ /* Test if SCTP doesn't partially deliver below
+ * max record size (2^14 + 2048 + 13)
+ */
+ optlen = (socklen_t) sizeof(int);
+ ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
+ &optval, &optlen);
+ OPENSSL_assert(ret >= 0);
+ OPENSSL_assert(optval >= 18445);
+
+ /* Partially delivered notification??? Probably a bug.... */
+ OPENSSL_assert(!(flags & MSG_NOTIFICATION));
+
+ /* Everything seems ok till now, so it's most likely
+ * a message dropped by PR-SCTP.
+ */
+ memset(out, 0, outl);
+ BIO_set_retry_read(b);
+ return -1;
+ }
+
+ /* Test if peer uses SCTP-AUTH before continuing */
+ if (!data->peer_auth_tested)
+ {
+ int ii, auth_data = 0, auth_forward = 0;
+ unsigned char *p;
+ struct sctp_authchunks *authchunks;
+
+ optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
+ authchunks = OPENSSL_malloc(optlen);
+ memset(authchunks, 0, sizeof(struct sctp_authchunks));
+ ii = sctp_opt_info(b->num, 0, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
+ OPENSSL_assert(ii >= 0);
+
+ for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t);
+ p < (unsigned char*) authchunks + optlen;
+ p += sizeof(uint8_t))
+ {
+ if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
+ if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
+ }
+
+ OPENSSL_free(authchunks);
+
+ if (!auth_data || !auth_forward)
+ {
+ BIOerr(BIO_F_BIO_READ,BIO_R_CONNECT_ERROR);
+ return -1;
+ }
+
+ data->peer_auth_tested = 1;
+ }
+
+ BIO_clear_retry_flags(b);
+ if (ret < 0)
+ {
+ if (BIO_dgram_should_retry(ret))
+ {
+ BIO_set_retry_read(b);
+ data->_errno = get_last_socket_error();
+ }
+ }
+ }
+ return(ret);
+ }
+#endif
+
static int dgram_write(BIO *b, const char *in, int inl)
{
int ret;
@@ -369,6 +758,114 @@
return(ret);
}
+#ifdef OPENSSL_SCTP
+static int dgram_sctp_write(BIO *b, const char *in, int inl)
+ {
+ int ret;
+ bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
+ struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo);
+ struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo);
+ struct bio_dgram_sctp_sndinfo handshake_sinfo;
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
+ char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct \
sctp_prinfo))]; + struct sctp_sndinfo *sndinfo;
+#else
+ char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
+ struct sctp_sndrcvinfo *sndrcvinfo;
+#endif
+
+ clear_socket_error();
+
+ /* If we're send anything else than application data,
+ * disable all user parameters and flags.
+ */
+ if (in[0] != 23) {
+ memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo));
+#ifdef SCTP_SACK_IMMEDIATELY
+ handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY;
+#endif
+ sinfo = &handshake_sinfo;
+ }
+
+ /* If we have to send a shutdown alert message and the
+ * socket is not dry yet, we have to save it and send it
+ * as soon as the socket gets dry.
+ */
+ if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b))
+ {
+ data->saved_message.bio = b;
+ data->saved_message.length = inl;
+ data->saved_message.data = OPENSSL_malloc(inl);
+ memcpy(data->saved_message.data, in, inl);
+ return inl;
+ }
+
+ iov[0].iov_base = (char *)in;
+ iov[0].iov_len = inl;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = (caddr_t)cmsgbuf;
+ msg.msg_controllen = 0;
+#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO)
+ cmsg = (struct cmsghdr *)cmsgbuf;
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
+ sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg);
+ memset(sndinfo, 0, sizeof(struct sctp_sndinfo));
+ sndinfo->snd_sid = sinfo->snd_sid;
+ sndinfo->snd_flags = sinfo->snd_flags;
+ sndinfo->snd_ppid = sinfo->snd_ppid;
+ sndinfo->snd_context = sinfo->snd_context;
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
+
+ cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))];
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_PRINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
+ prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg);
+ memset(prinfo, 0, sizeof(struct sctp_prinfo));
+ prinfo->pr_policy = pinfo->pr_policy;
+ prinfo->pr_value = pinfo->pr_value;
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
+#else
+ cmsg = (struct cmsghdr *)cmsgbuf;
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDRCV;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+ sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+ memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
+ sndrcvinfo->sinfo_stream = sinfo->snd_sid;
+ sndrcvinfo->sinfo_flags = sinfo->snd_flags;
+#ifdef __FreeBSD__
+ sndrcvinfo->sinfo_flags |= pinfo->pr_policy;
+#endif
+ sndrcvinfo->sinfo_ppid = sinfo->snd_ppid;
+ sndrcvinfo->sinfo_context = sinfo->snd_context;
+ sndrcvinfo->sinfo_timetolive = pinfo->pr_value;
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
+#endif
+
+ ret = sendmsg(b->num, &msg, 0);
+
+ BIO_clear_retry_flags(b);
+ if (ret <= 0)
+ {
+ if (BIO_dgram_should_retry(ret))
+ {
+ BIO_set_retry_write(b);
+ data->_errno = get_last_socket_error();
+ }
+ }
+ return(ret);
+ }
+#endif
+
static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret=1;
@@ -728,6 +1225,389 @@
return(ret);
}
+#ifdef OPENSSL_SCTP
+static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr)
+ {
+ long ret=1;
+ bio_dgram_sctp_data *data = NULL;
+ unsigned int sockopt_len = 0;
+ struct sctp_authkeyid authkeyid;
+ struct sctp_authkey *authkey;
+
+ data = (bio_dgram_sctp_data *)b->ptr;
+
+ switch (cmd)
+ {
+ case BIO_CTRL_DGRAM_QUERY_MTU:
+ /* Set to maximum (2^14)
+ * and ignore user input to enable transport
+ * protocol fragmentation.
+ * Returns always 2^14.
+ */
+ data->mtu = 16384;
+ ret = data->mtu;
+ break;
+ case BIO_CTRL_DGRAM_SET_MTU:
+ /* Set to maximum (2^14)
+ * and ignore input to enable transport
+ * protocol fragmentation.
+ * Returns always 2^14.
+ */
+ data->mtu = 16384;
+ ret = data->mtu;
+ break;
+ case BIO_CTRL_DGRAM_SET_CONNECTED:
+ case BIO_CTRL_DGRAM_CONNECT:
+ /* Returns always -1. */
+ ret = -1;
+ break;
+ case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
+ /* SCTP doesn't need the DTLS timer
+ * Returns always 1.
+ */
+ break;
+ case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE:
+ if (num > 0)
+ data->in_handshake = 1;
+ else
+ data->in_handshake = 0;
+
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, \
sizeof(int)); + break;
+ case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY:
+ /* New shared key for SCTP AUTH.
+ * Returns 0 on success, -1 otherwise.
+ */
+
+ /* Get active key */
+ sockopt_len = sizeof(struct sctp_authkeyid);
+ ret = sctp_opt_info(b->num, 0, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
+ if (ret < 0) break;
+
+ /* Add new key */
+ authkey = OPENSSL_malloc(sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t));
+ authkey->sca_keynumber = authkeyid.scact_keynumber + 1;
+ memset(&authkey->sca_key[0], 0x00, 65 * sizeof(uint8_t));
+ memcpy(&authkey->sca_key[0], ptr, 32 * sizeof(uint8_t));
+
+ sockopt_len = sizeof(struct sctp_authkey) + 63 * sizeof(uint8_t);
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len);
+ if (ret < 0) break;
+
+ /* Reset active key */
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
+ &authkeyid, sizeof(struct sctp_authkeyid));
+ if (ret < 0) break;
+
+ break;
+ case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY:
+ /* Returns 0 on success, -1 otherwise. */
+
+ /* Get active key */
+ sockopt_len = sizeof(struct sctp_authkeyid);
+ ret = sctp_opt_info(b->num, 0, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
+ if (ret < 0) break;
+
+ /* Set active key */
+ authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1;
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY,
+ &authkeyid, sizeof(struct sctp_authkeyid));
+ if (ret < 0) break;
+
+ /* CCS has been sent, so remember that and fall through
+ * to check if we need to deactivate an old key
+ */
+ data->ccs_sent = 1;
+
+ case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD:
+ /* Returns 0 on success, -1 otherwise. */
+
+ /* Has this command really been called or is this just a fall-through? */
+ if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD)
+ data->ccs_rcvd = 1;
+
+ /* CSS has been both, received and sent, so deactivate an old key */
+ if (data->ccs_rcvd == 1 && data->ccs_sent == 1)
+ {
+ /* Get active key */
+ sockopt_len = sizeof(struct sctp_authkeyid);
+ ret = sctp_opt_info(b->num, 0, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len);
+ if (ret < 0) break;
+
+ /* Deactivate key or delete second last key if
+ * SCTP_AUTHENTICATION_EVENT is not available.
+ */
+ authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
+#ifdef SCTP_AUTH_DEACTIVATE_KEY
+ sockopt_len = sizeof(struct sctp_authkeyid);
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY,
+ &authkeyid, sockopt_len);
+ if (ret < 0) break;
+#endif
+#ifndef SCTP_AUTHENTICATION_EVENT
+ if (authkeyid.scact_keynumber > 0)
+ {
+ authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1;
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY,
+ &authkeyid, sizeof(struct sctp_authkeyid));
+ if (ret < 0) break;
+ }
+#endif
+
+ data->ccs_rcvd = 0;
+ data->ccs_sent = 0;
+ }
+ break;
+ case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO:
+ /* Returns the size of the copied struct. */
+ if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
+ num = sizeof(struct bio_dgram_sctp_sndinfo);
+
+ memcpy(ptr, &(data->sndinfo), num);
+ ret = num;
+ break;
+ case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO:
+ /* Returns the size of the copied struct. */
+ if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo))
+ num = sizeof(struct bio_dgram_sctp_sndinfo);
+
+ memcpy(&(data->sndinfo), ptr, num);
+ break;
+ case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO:
+ /* Returns the size of the copied struct. */
+ if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
+ num = sizeof(struct bio_dgram_sctp_rcvinfo);
+
+ memcpy(ptr, &data->rcvinfo, num);
+
+ ret = num;
+ break;
+ case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO:
+ /* Returns the size of the copied struct. */
+ if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo))
+ num = sizeof(struct bio_dgram_sctp_rcvinfo);
+
+ memcpy(&(data->rcvinfo), ptr, num);
+ break;
+ case BIO_CTRL_DGRAM_SCTP_GET_PRINFO:
+ /* Returns the size of the copied struct. */
+ if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
+ num = sizeof(struct bio_dgram_sctp_prinfo);
+
+ memcpy(ptr, &(data->prinfo), num);
+ ret = num;
+ break;
+ case BIO_CTRL_DGRAM_SCTP_SET_PRINFO:
+ /* Returns the size of the copied struct. */
+ if (num > (long) sizeof(struct bio_dgram_sctp_prinfo))
+ num = sizeof(struct bio_dgram_sctp_prinfo);
+
+ memcpy(&(data->prinfo), ptr, num);
+ break;
+ case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN:
+ /* Returns always 1. */
+ if (num > 0)
+ data->save_shutdown = 1;
+ else
+ data->save_shutdown = 0;
+ break;
+
+ default:
+ /* Pass to default ctrl function to
+ * process SCTP unspecific commands
+ */
+ ret=dgram_ctrl(b, cmd, num, ptr);
+ break;
+ }
+ return(ret);
+ }
+
+int BIO_dgram_sctp_notification_cb(BIO *b,
+ void (*handle_notifications)(BIO *bio, void \
*context, void *buf), + void *context)
+ {
+ bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr;
+
+ if (handle_notifications != NULL)
+ {
+ data->handle_notifications = handle_notifications;
+ data->notification_context = context;
+ }
+ else
+ return -1;
+
+ return 0;
+ }
+
+int BIO_dgram_sctp_wait_for_dry(BIO *b)
+{
+ int flags, is_dry = 0;
+ int n, sockflags, ret;
+ union sctp_notification snp;
+#ifdef SCTP_EVENT
+ struct sctp_event event;
+#else
+ struct sctp_event_subscribe event;
+ socklen_t eventsize;
+#endif
+ bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
+
+ /* set sender dry event */
+#ifdef SCTP_EVENT
+ memset(&event, 0, sizeof(struct sctp_event));
+ event.se_assoc_id = 0;
+ event.se_type = SCTP_SENDER_DRY_EVENT;
+ event.se_on = 1;
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct \
sctp_event)); +#else
+ eventsize = sizeof(struct sctp_event_subscribe);
+ ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
+ if (ret < 0)
+ return -1;
+
+ event.sctp_sender_dry_event = 1;
+
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct \
sctp_event_subscribe)); +#endif
+ if (ret < 0)
+ return -1;
+
+ /* peek for notification */
+ flags = MSG_PEEK;
+ n = sctp_recvmsg(b->num,(void*)&snp,sizeof(union \
sctp_notification),NULL,NULL,0,&flags); + if (n <= 0)
+ {
+ if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != \
EWOULDBLOCK)) + return -1;
+ else
+ return 0;
+ }
+
+ /* if we find a notification, process it and try again if necessary */
+ while (flags & MSG_NOTIFICATION)
+ {
+ memset(&snp, 0x00, sizeof(union sctp_notification));
+ flags = 0;
+ n = sctp_recvmsg(b->num,(void*)&snp,sizeof(union \
sctp_notification),NULL,NULL,0,&flags); + if (n <= 0)
+ {
+ if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != \
EWOULDBLOCK)) + return -1;
+ else
+ return is_dry;
+ }
+
+ if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
+ {
+ is_dry = 1;
+
+ /* disable sender dry event */
+#ifdef SCTP_EVENT
+ memset(&event, 0, sizeof(struct sctp_event));
+ event.se_assoc_id = 0;
+ event.se_type = SCTP_SENDER_DRY_EVENT;
+ event.se_on = 0;
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct \
sctp_event)); +#else
+ eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
+ ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
+ if (ret < 0)
+ return -1;
+
+ event.sctp_sender_dry_event = 0;
+
+ ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct \
sctp_event_subscribe)); +#endif
+ if (ret < 0)
+ return -1;
+ }
+
+#ifdef SCTP_AUTHENTICATION_EVENT
+ if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
+ dgram_sctp_handle_auth_free_key_event(b, &snp);
+#endif
+
+ if (data->handle_notifications != NULL)
+ data->handle_notifications(b, data->notification_context, (void*) &snp);
+
+ if (is_dry == 1)
+ {
+ /* check for more notifications */
+ sockflags = fcntl(b->num, F_GETFL, 0);
+ fcntl(b->num, F_SETFL, O_NONBLOCK);
+ flags = MSG_PEEK;
+ n = sctp_recvmsg(b->num,(void*)&snp,sizeof(union \
sctp_notification),NULL,NULL,0,&flags); + fcntl(b->num, F_SETFL, sockflags);
+
+ /* if nothing more is waiting just quit. otherwise read again. */
+ if (n <= 0)
+ {
+ if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() \
!= EWOULDBLOCK)) + return -1;
+ else
+ return is_dry;
+ }
+ }
+
+ /* found notification but no dry event, peek again */
+ memset(&snp, 0x00, sizeof(union sctp_notification));
+ flags = MSG_PEEK;
+ n = sctp_recvmsg(b->num,(void*)&snp,sizeof(union \
sctp_notification),NULL,NULL,0,&flags); + if (n <= 0)
+ {
+ if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != \
EWOULDBLOCK)) + return -1;
+ else
+ return is_dry;
+ }
+ }
+
+ /* read anything else */
+ return is_dry;
+}
+
+int BIO_dgram_sctp_msg_waiting(BIO *b)
+ {
+ int n, sockflags, flags;
+ union sctp_notification snp;
+ bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
+
+ /* Check if there are any messages waiting to be read */
+ do
+ {
+ sockflags = fcntl(b->num, F_GETFL, 0);
+ fcntl(b->num, F_SETFL, O_NONBLOCK);
+ flags = MSG_PEEK;
+ n = sctp_recvmsg(b->num,(void*)&snp,sizeof(union \
sctp_notification),NULL,NULL,0,&flags); + fcntl(b->num, F_SETFL, sockflags);
+
+ /* if notification, process and try again */
+ if (n > 0 && (flags & MSG_NOTIFICATION))
+ {
+#ifdef SCTP_AUTHENTICATION_EVENT
+ if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
+ dgram_sctp_handle_auth_free_key_event(b, &snp);
+#endif
+
+ flags = 0;
+ n = sctp_recvmsg(b->num,(void*)&snp,sizeof(union \
sctp_notification),NULL,NULL,0,&flags); +
+ if (data->handle_notifications != NULL)
+ data->handle_notifications(b, data->notification_context, (void*) &snp);
+
+ memset(&snp, 0x00, sizeof(union sctp_notification));
+ }
+
+ } while (n > 0 && (flags & MSG_NOTIFICATION));
+
+ /* Return 1 if there is a message to be read, return 0 otherwise. */
+ if (n > 0)
+ return 1;
+ else
+ return 0;
+ }
+#endif
+
static int dgram_puts(BIO *bp, const char *str)
{
int n,ret;
@@ -737,6 +1617,17 @@
return(ret);
}
+#ifdef OPENSSL_SCTP
+static int dgram_sctp_puts(BIO *bp, const char *str)
+ {
+ int n,ret;
+
+ n=strlen(str);
+ ret=dgram_sctp_write(bp,str,n);
+ return(ret);
+ }
+#endif
+
static int BIO_dgram_should_retry(int i)
{
int err;
--- ssl/d1_both.c 3 Apr 2011 17:14:48 -0000 1.14.2.21.2.3
+++ ssl/d1_both.c 31 May 2011 14:50:43 -0000
@@ -1408,3 +1408,24 @@
ccs_hdr->type = *(data++);
}
+
+int dtls1_shutdown(SSL *s)
+ {
+ int ret;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ !(s->shutdown & SSL_SENT_SHUTDOWN))
+ {
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0) return -1;
+
+ if (ret == 0)
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 1, NULL);
+ }
+#endif
+ ret = ssl3_shutdown(s);
+#ifdef OPENSSL_SCTP
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
+#endif
+ return ret;
+ }
--- ssl/d1_clnt.c 25 May 2011 12:24:43 -0000 1.16.2.15.2.4
+++ ssl/d1_clnt.c 31 May 2011 14:50:43 -0000
@@ -150,7 +150,11 @@
unsigned long Time=(unsigned long)time(NULL);
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int ret= -1;
- int new_state,state,skip=0;;
+ int new_state,state,skip=0;
+#ifdef OPENSSL_SCTP
+ unsigned char sctpauthkey[64];
+ unsigned char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+#endif
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
@@ -164,6 +168,14 @@
s->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+#ifdef OPENSSL_SCTP
+ /* Notify SCTP BIO socket to enter handshake
+ * mode and prevent stream identifier other
+ * than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, \
NULL); +#endif
+
for (;;)
{
state=s->state;
@@ -226,6 +238,42 @@
s->hit = 0;
break;
+#ifdef OPENSSL_SCTP
+ case DTLS1_SCTP_ST_CR_READ_SOCK:
+
+ if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
+ {
+ s->s3->in_read_app_data=2;
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+
+ s->state=s->s3->tmp.next_state;
+ break;
+
+ case DTLS1_SCTP_ST_CW_WRITE_SOCK:
+ /* read app data until dry event */
+
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0) goto end;
+
+ if (ret == 0)
+ {
+ s->s3->in_read_app_data=2;
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+
+ s->state=s->d1->next_state;
+ break;
+#endif
+
case SSL3_ST_CW_CLNT_HELLO_A:
case SSL3_ST_CW_CLNT_HELLO_B:
@@ -248,9 +296,17 @@
s->init_num=0;
- /* turn on buffering for the next lot of output */
- if (s->bbio != s->wbio)
- s->wbio=BIO_push(s->bbio,s->wbio);
+#ifdef OPENSSL_SCTP
+ /* Disable buffering for SCTP */
+ if (SSL_get_wbio(s)->method->type != BIO_TYPE_DGRAM_SCTP)
+ {
+#endif
+ /* turn on buffering for the next lot of output */
+ if (s->bbio != s->wbio)
+ s->wbio=BIO_push(s->bbio,s->wbio);
+#ifdef OPENSSL_SCTP
+ }
+#endif
break;
@@ -262,7 +318,24 @@
{
dtls1_stop_timer(s);
if (s->hit)
+ {
+#ifdef OPENSSL_SCTP
+ /* Add new shared key for SCTP-Auth,
+ * will be ignored if no SCTP used.
+ */
+ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_tls1_key_exporter(s, labelbuffer, sizeof(labelbuffer),
+ NULL, 0,
+ sctpauthkey, sizeof(sctpauthkey));
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+#endif
+
s->state=SSL3_ST_CR_FINISHED_A;
+ }
else
s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
}
@@ -355,11 +428,18 @@
ret=ssl3_get_server_done(s);
if (ret <= 0) goto end;
if (s->s3->tmp.cert_req)
- s->state=SSL3_ST_CW_CERT_A;
+ s->s3->tmp.next_state=SSL3_ST_CW_CERT_A;
else
- s->state=SSL3_ST_CW_KEY_EXCH_A;
+ s->s3->tmp.next_state=SSL3_ST_CW_KEY_EXCH_A;
s->init_num=0;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ state == SSL_ST_RENEGOTIATE)
+ s->state=DTLS1_SCTP_ST_CR_READ_SOCK;
+ else
+#endif
+ s->state=s->s3->tmp.next_state;
break;
case SSL3_ST_CW_CERT_A:
@@ -378,6 +458,22 @@
dtls1_start_timer(s);
ret=dtls1_send_client_key_exchange(s);
if (ret <= 0) goto end;
+
+#ifdef OPENSSL_SCTP
+ /* Add new shared key for SCTP-Auth,
+ * will be ignored if no SCTP used.
+ */
+ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_tls1_key_exporter(s, labelbuffer, sizeof(labelbuffer),
+ NULL, 0,
+ sctpauthkey, sizeof(sctpauthkey));
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+#endif
+
/* EAY EAY EAY need to check for DH fix cert
* sent back */
/* For TLS, cert_req is set to 2, so a cert chain
@@ -388,7 +484,15 @@
}
else
{
- s->state=SSL3_ST_CW_CHANGE_A;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state=SSL3_ST_CW_CHANGE_A;
+ s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
+ else
+#endif
+ s->state=SSL3_ST_CW_CHANGE_A;
s->s3->change_cipher_spec=0;
}
@@ -400,7 +504,15 @@
dtls1_start_timer(s);
ret=dtls1_send_client_verify(s);
if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_CHANGE_A;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state=SSL3_ST_CW_CHANGE_A;
+ s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
+ else
+#endif
+ s->state=SSL3_ST_CW_CHANGE_A;
s->init_num=0;
s->s3->change_cipher_spec=0;
break;
@@ -412,6 +524,14 @@
ret=dtls1_send_change_cipher_spec(s,
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
+
+#ifdef OPENSSL_SCTP
+ /* Change to new shared key of SCTP-Auth,
+ * will be ignored if no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+#endif
+
s->state=SSL3_ST_CW_FINISHED_A;
s->init_num=0;
@@ -457,9 +577,23 @@
if (s->hit)
{
s->s3->tmp.next_state=SSL_ST_OK;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state = s->s3->tmp.next_state;
+ s->s3->tmp.next_state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
+#endif
if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
{
s->state=SSL_ST_OK;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state = SSL_ST_OK;
+ s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
+#endif
s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
s->s3->delay_buf_pop_ret=0;
}
@@ -508,6 +642,16 @@
s->state=SSL3_ST_CW_CHANGE_A;
else
s->state=SSL_ST_OK;
+
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ state == SSL_ST_RENEGOTIATE)
+ {
+ s->d1->next_state=s->state;
+ s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
+ }
+#endif
+
s->init_num=0;
break;
@@ -588,6 +732,15 @@
}
end:
s->in_handshake--;
+
+#ifdef OPENSSL_SCTP
+ /* Notify SCTP BIO socket to leave handshake
+ * mode and allow stream identifier other
+ * than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, \
NULL); +#endif
+
if (buf != NULL)
BUF_MEM_free(buf);
if (cb != NULL)
--- ssl/d1_lib.c 25 May 2011 14:30:05 -0000 1.8.2.13.2.3
+++ ssl/d1_lib.c 31 May 2011 14:50:43 -0000
@@ -284,6 +284,15 @@
void dtls1_start_timer(SSL *s)
{
+#ifdef OPENSSL_SCTP
+ /* Disable timer for SCTP */
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
+ return;
+ }
+#endif
+
/* If timer is not set, initialize duration with 1 second */
if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0)
{
--- ssl/d1_pkt.c 4 Jan 2011 19:33:30 -0000 1.27.2.25.2.4
+++ ssl/d1_pkt.c 31 May 2011 14:50:43 -0000
@@ -232,6 +232,14 @@
item->data = rdata;
+#ifdef OPENSSL_SCTP
+ /* Store bio_dgram_sctp_rcvinfo struct */
+ if (SSL_get_rbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ (s->state == SSL3_ST_SR_FINISHED_A || s->state == SSL3_ST_CR_FINISHED_A)) {
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_GET_RCVINFO, \
sizeof(rdata->recordinfo), &rdata->recordinfo); + }
+#endif
+
/* insert should not fail, since duplicates are dropped */
if (pqueue_insert(queue->q, item) == NULL)
{
@@ -638,20 +646,28 @@
goto again; /* get another record */
}
- /* Check whether this is a repeat, or aged record.
- * Don't check if we're listening and this message is
- * a ClientHello. They can look as if they're replayed,
- * since they arrive from different connections and
- * would be dropped unnecessarily.
- */
- if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
- *p == SSL3_MT_CLIENT_HELLO) &&
- !dtls1_record_replay_check(s, bitmap))
- {
- rr->length = 0;
- s->packet_length=0; /* dump this record */
- goto again; /* get another record */
- }
+#ifdef OPENSSL_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (SSL_get_rbio(s)->method->type != BIO_TYPE_DGRAM_SCTP)
+ {
+#endif
+ /* Check whether this is a repeat, or aged record.
+ * Don't check if we're listening and this message is
+ * a ClientHello. They can look as if they're replayed,
+ * since they arrive from different connections and
+ * would be dropped unnecessarily.
+ */
+ if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE &&
+ *p == SSL3_MT_CLIENT_HELLO) &&
+ !dtls1_record_replay_check(s, bitmap))
+ {
+ rr->length = 0;
+ s->packet_length=0; /* dump this record */
+ goto again; /* get another record */
+ }
+#ifdef OPENSSL_SCTP
+ }
+#endif
/* just read a 0 length packet */
if (rr->length == 0) goto again;
@@ -735,7 +751,17 @@
/* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
+#ifdef OPENSSL_SCTP
+ /* Continue handshake if it had to be interrupted to read
+ * app data with SCTP.
+ */
+ if ((!s->in_handshake && SSL_in_init(s)) ||
+ (SSL_get_rbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == \
DTLS1_SCTP_ST_CR_READ_SOCK) && + s->s3->in_read_app_data != 2))
+#else
if (!s->in_handshake && SSL_in_init(s))
+#endif
{
/* type == SSL3_RT_APPLICATION_DATA */
i=s->handshake_func(s);
@@ -766,6 +792,15 @@
item = pqueue_pop(s->d1->buffered_app_data.q);
if (item)
{
+#ifdef OPENSSL_SCTP
+ /* Restore bio_dgram_sctp_rcvinfo struct */
+ if (SSL_get_rbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ DTLS1_RECORD_DATA *rdata = (DTLS1_RECORD_DATA *) item->data;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SCTP_SET_RCVINFO, \
sizeof(rdata->recordinfo), &rdata->recordinfo); + }
+#endif
+
dtls1_copy_record(s, item);
OPENSSL_free(item->data);
@@ -848,6 +883,31 @@
rr->off=0;
}
}
+
+#ifdef OPENSSL_SCTP
+ /* We were about to renegotiate but had to read
+ * belated application data first, so retry.
+ */
+ if (SSL_get_rbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ rr->type == SSL3_RT_APPLICATION_DATA &&
+ (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == \
DTLS1_SCTP_ST_CR_READ_SOCK)) + {
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ }
+
+ /* We might had to delay a close_notify alert because
+ * of reordered app data. If there was an alert and there
+ * is no message to read anymore, finally set shutdown.
+ */
+ if (SSL_get_rbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
+ {
+ s->shutdown |= SSL_RECEIVED_SHUTDOWN;
+ return(0);
+ }
+#endif
return(n);
}
@@ -1020,6 +1080,21 @@
s->s3->warn_alert = alert_descr;
if (alert_descr == SSL_AD_CLOSE_NOTIFY)
{
+#ifdef OPENSSL_SCTP
+ /* With SCTP and streams the socket may deliver app data
+ * after a close_notify alert. We have to check this
+ * first so that nothing gets discarded.
+ */
+ if (SSL_get_rbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
+ {
+ s->d1->shutdown_received = 1;
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ return -1;
+ }
+#endif
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return(0);
}
@@ -1126,6 +1201,15 @@
if (s->version == DTLS1_BAD_VER)
s->d1->handshake_read_seq++;
+#ifdef OPENSSL_SCTP
+ /* Remember that a CCS has been received,
+ * so that an old key of SCTP-Auth can be
+ * deleted when a CCS is sent. Will be ignored
+ * if no SCTP is used
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD, 1, NULL);
+#endif
+
goto start;
}
@@ -1262,7 +1346,16 @@
{
int i;
- if (SSL_in_init(s) && !s->in_handshake)
+#ifdef OPENSSL_SCTP
+ /* Check if we have to continue an interrupted handshake
+ * for reading belated app data with SCTP.
+ */
+ if ((SSL_in_init(s) && !s->in_handshake) ||
+ (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ (s->state == DTLS1_SCTP_ST_SR_READ_SOCK || s->state == \
DTLS1_SCTP_ST_CR_READ_SOCK))) +#else
+ if (SSL_in_init(s) && !s->in_handshake)
+#endif
{
i=s->handshake_func(s);
if (i < 0) return(i);
--- ssl/d1_srvr.c 25 May 2011 14:30:05 -0000 1.20.2.16.2.6
+++ ssl/d1_srvr.c 31 May 2011 14:50:43 -0000
@@ -151,6 +151,10 @@
int ret= -1;
int new_state,state,skip=0;
int listen;
+#ifdef OPENSSL_SCTP
+ unsigned char sctpauthkey[64];
+ unsigned char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+#endif
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
@@ -167,6 +171,14 @@
s->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
+#ifdef OPENSSL_SCTP
+ /* Notify SCTP BIO socket to enter handshake
+ * mode and prevent stream identifier other
+ * than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, \
NULL); +#endif
+
if (s->cert == NULL)
{
SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
@@ -225,8 +237,12 @@
{
/* Ok, we now need to push on a buffering BIO so that
* the output is sent in a way that TCP likes :-)
+ * ...but not with SCTP :-)
*/
- if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type != BIO_TYPE_DGRAM_SCTP)
+#endif
+ if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
ssl3_init_finished_mac(s);
s->state=SSL3_ST_SR_CLNT_HELLO_A;
@@ -306,6 +322,43 @@
ssl3_init_finished_mac(s);
break;
+#ifdef OPENSSL_SCTP
+ case DTLS1_SCTP_ST_SR_READ_SOCK:
+
+ if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
+ {
+ s->s3->in_read_app_data=2;
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+
+ s->state=SSL3_ST_SR_FINISHED_A;
+ break;
+
+ case DTLS1_SCTP_ST_SW_WRITE_SOCK:
+ ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
+ if (ret < 0) goto end;
+
+ if (ret == 0)
+ {
+ if (s->d1->next_state != SSL_ST_OK)
+ {
+ s->s3->in_read_app_data=2;
+ s->rwstate=SSL_READING;
+ BIO_clear_retry_flags(SSL_get_rbio(s));
+ BIO_set_retry_read(SSL_get_rbio(s));
+ ret = -1;
+ goto end;
+ }
+ }
+
+ s->state=s->d1->next_state;
+ break;
+#endif
+
case SSL3_ST_SW_SRVR_HELLO_A:
case SSL3_ST_SW_SRVR_HELLO_B:
s->renegotiate = 2;
@@ -313,18 +366,31 @@
ret=dtls1_send_server_hello(s);
if (ret <= 0) goto end;
-#ifndef OPENSSL_NO_TLSEXT
if (s->hit)
{
+#ifdef OPENSSL_SCTP
+ /* Add new shared key for SCTP-Auth,
+ * will be ignored if no SCTP used.
+ */
+ snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_tls1_key_exporter(s, labelbuffer, sizeof(labelbuffer),
+ NULL, 0,
+ sctpauthkey, sizeof(sctpauthkey));
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+#endif
+#ifndef OPENSSL_NO_TLSEXT
if (s->tlsext_ticket_expected)
s->state=SSL3_ST_SW_SESSION_TICKET_A;
else
s->state=SSL3_ST_SW_CHANGE_A;
- }
#else
- if (s->hit)
- s->state=SSL3_ST_SW_CHANGE_A;
+ s->state=SSL3_ST_SW_CHANGE_A;
#endif
+ }
else
s->state=SSL3_ST_SW_CERT_A;
s->init_num=0;
@@ -434,6 +500,13 @@
skip=1;
s->s3->tmp.cert_request=0;
s->state=SSL3_ST_SW_SRVR_DONE_A;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
+ s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
+#endif
}
else
{
@@ -443,9 +516,23 @@
if (ret <= 0) goto end;
#ifndef NETSCAPE_HANG_BUG
s->state=SSL3_ST_SW_SRVR_DONE_A;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
+ s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
+#endif
#else
s->state=SSL3_ST_SW_FLUSH;
s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state = s->s3->tmp.next_state;
+ s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
+#endif
#endif
s->init_num=0;
}
@@ -497,6 +584,21 @@
ret=ssl3_get_client_key_exchange(s);
if (ret <= 0) goto end;
dtls1_stop_timer(s);
+#ifdef OPENSSL_SCTP
+ /* Add new shared key for SCTP-Auth,
+ * will be ignored if no SCTP used.
+ */
+ snprintf((char *) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
+ DTLS1_SCTP_AUTH_LABEL);
+
+ SSL_tls1_key_exporter(s, labelbuffer, sizeof(labelbuffer),
+ NULL, 0,
+ sctpauthkey, sizeof(sctpauthkey));
+
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
+ sizeof(sctpauthkey), sctpauthkey);
+#endif
+
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
@@ -534,8 +636,13 @@
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
dtls1_stop_timer(s);
-
- s->state=SSL3_ST_SR_FINISHED_A;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP &&
+ state == SSL_ST_RENEGOTIATE)
+ s->state=DTLS1_SCTP_ST_SR_READ_SOCK;
+ else
+#endif
+ s->state=SSL3_ST_SR_FINISHED_A;
s->init_num=0;
break;
@@ -587,6 +694,14 @@
SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
if (ret <= 0) goto end;
+
+#ifdef OPENSSL_SCTP
+ /* Change to new shared key of SCTP-Auth,
+ * will be ignored if no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
+#endif
+
s->state=SSL3_ST_SW_FINISHED_A;
s->init_num=0;
@@ -611,7 +726,16 @@
if (s->hit)
s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
else
+ {
s->s3->tmp.next_state=SSL_ST_OK;
+#ifdef OPENSSL_SCTP
+ if (SSL_get_wbio(s)->method->type == BIO_TYPE_DGRAM_SCTP)
+ {
+ s->d1->next_state = s->s3->tmp.next_state;
+ s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK;
+ }
+#endif
+ }
s->init_num=0;
break;
@@ -686,6 +810,14 @@
/* BIO_flush(s->wbio); */
s->in_handshake--;
+#ifdef OPENSSL_SCTP
+ /* Notify SCTP BIO socket to leave handshake
+ * mode and prevent stream identifier other
+ * than 0. Will be ignored if no SCTP is used.
+ */
+ BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, \
NULL); +#endif
+
if (cb != NULL)
cb(s,SSL_CB_ACCEPT_EXIT,ret);
return(ret);
--- ssl/dtls1.h 11 May 2011 12:56:38 -0000 1.12.2.16.2.1
+++ ssl/dtls1.h 31 May 2011 14:50:43 -0000
@@ -74,6 +74,9 @@
#else
#include <sys/time.h>
#endif
+#ifdef OPENSSL_SCTP
+#include <netinet/sctp.h>
+#endif
#ifdef __cplusplus
extern "C" {
@@ -107,6 +110,9 @@
#ifndef OPENSSL_NO_SSL_INTERN
+#ifdef OPENSSL_SCTP
+#define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
+#endif
typedef struct dtls1_bitmap_st
{
@@ -245,6 +251,13 @@
unsigned int retransmitting;
unsigned int change_cipher_spec_ok;
+#ifdef OPENSSL_SCTP
+ /* used when SSL_ST_XX_FLUSH is entered */
+ int next_state;
+
+ int shutdown_received;
+#endif
+
} DTLS1_STATE;
typedef struct dtls1_record_data_st
@@ -253,6 +266,9 @@
unsigned int packet_length;
SSL3_BUFFER rbuf;
SSL3_RECORD rrec;
+#ifdef OPENSSL_SCTP
+ struct bio_dgram_sctp_rcvinfo recordinfo;
+#endif
} DTLS1_RECORD_DATA;
#endif
--- ssl/ssl3.h 20 May 2011 14:58:44 -0000 1.44.2.7.2.4
+++ ssl/ssl3.h 31 May 2011 14:50:43 -0000
@@ -527,6 +527,10 @@
/*client */
/* extra state */
#define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT)
+#ifdef OPENSSL_SCTP
+#define DTLS1_SCTP_ST_CW_WRITE_SOCK (0x310|SSL_ST_CONNECT)
+#define DTLS1_SCTP_ST_CR_READ_SOCK (0x320|SSL_ST_CONNECT)
+#endif
/* write to server */
#define SSL3_ST_CW_CLNT_HELLO_A (0x110|SSL_ST_CONNECT)
#define SSL3_ST_CW_CLNT_HELLO_B (0x111|SSL_ST_CONNECT)
@@ -569,6 +573,10 @@
/* server */
/* extra state */
#define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT)
+#ifdef OPENSSL_SCTP
+#define DTLS1_SCTP_ST_SW_WRITE_SOCK (0x310|SSL_ST_ACCEPT)
+#define DTLS1_SCTP_ST_SR_READ_SOCK (0x320|SSL_ST_ACCEPT)
+#endif
/* read from client */
/* Do not change the number values, they do matter */
#define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT)
--- ssl/ssl_locl.h 20 May 2011 14:58:44 -0000 1.100.2.10.2.6
+++ ssl/ssl_locl.h 31 May 2011 14:50:43 -0000
@@ -761,7 +761,7 @@
ssl3_read, \
ssl3_peek, \
ssl3_write, \
- ssl3_shutdown, \
+ dtls1_shutdown, \
ssl3_renegotiate, \
ssl3_renegotiate_check, \
dtls1_get_message, \
@@ -1021,6 +1021,7 @@
void dtls1_free(SSL *s);
void dtls1_clear(SSL *s);
long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
+int dtls1_shutdown(SSL *s);
long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
int dtls1_get_record(SSL *s);
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majordomo@openssl.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic