Submitted by: Robin Seggelmann <seggelmann@fh-muenster.de>
Reviewed by: steve

Add SCTP support for DTLS (RFC 6083).
This commit is contained in:
Dr. Stephen Henson 2011-12-25 14:45:15 +00:00
parent b9e1488865
commit 7e159e0133
11 changed files with 1524 additions and 33 deletions

View File

@ -10,7 +10,7 @@ use strict;
# 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 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimenta
# [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, ...)
@ -709,6 +710,7 @@ my %disabled = ( # "what" => "comment" [or special keyword "experimental
"md2" => "default",
"rc5" => "default",
"rfc3779" => "default",
"sctp" => "default",
"shared" => "default",
"store" => "experimental",
"zlib" => "default",
@ -791,6 +793,7 @@ PROCESS_ARGS:
# rewrite some options in "enable-..." form
s /^-?-?shared$/enable-shared/;
s /^sctp$/enable-sctp/;
s /^threads$/enable-threads/;
s /^zlib$/enable-zlib/;
s /^zlib-dynamic$/enable-zlib-dynamic/;
@ -1445,6 +1448,14 @@ if (!$IsMK1MF)
}
}
if (!defined($disabled{"sctp"}))
{
if ($target =~ /^solaris/)
{
$cflags = "$cflags -D_XPG4_2 -D__EXTENSIONS__";
}
}
$cpuid_obj.=" uplink.o uplink-x86.o" if ($cflags =~ /\-DOPENSSL_USE_APPLINK/);
#

View File

@ -68,6 +68,10 @@
#include <openssl/crypto.h>
#ifndef OPENSSL_NO_SCTP
#include <stdint.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -95,6 +99,9 @@ extern "C" {
#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */
#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */
#define BIO_TYPE_DGRAM (21|0x0400|0x0100)
#ifndef OPENSSL_NO_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 @@ extern "C" {
#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 */
#ifndef OPENSSL_NO_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
@ -331,6 +353,34 @@ typedef struct bio_f_buffer_ctx_struct
/* Prefix and suffix callback in ASN1 BIO */
typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
#ifndef OPENSSL_NO_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
@ -628,6 +678,9 @@ BIO_METHOD *BIO_f_linebuffer(void);
BIO_METHOD *BIO_f_nbio_test(void);
#ifndef OPENSSL_NO_DGRAM
BIO_METHOD *BIO_s_datagram(void);
#ifndef OPENSSL_NO_SCTP
BIO_METHOD *BIO_s_datagram_sctp(void);
#endif
#endif
/* BIO_METHOD *BIO_f_ber(void); */
@ -670,6 +723,15 @@ int BIO_set_tcp_ndelay(int sock,int turn_on);
BIO *BIO_new_socket(int sock, int close_flag);
BIO *BIO_new_dgram(int fd, int close_flag);
#ifndef OPENSSL_NO_SCTP
BIO *BIO_new_dgram_sctp(int fd, int close_flag);
int BIO_dgram_is_sctp(BIO *bio);
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);

File diff suppressed because it is too large Load Diff

View File

@ -1417,3 +1417,24 @@ dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
ccs_hdr->type = *(data++);
}
int dtls1_shutdown(SSL *s)
{
int ret;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
!(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);
#ifndef OPENSSL_NO_SCTP
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN, 0, NULL);
#endif
return ret;
}

View File

@ -151,7 +151,11 @@ int dtls1_connect(SSL *s)
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;
#ifndef OPENSSL_NO_SCTP
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
#endif
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
@ -165,6 +169,14 @@ int dtls1_connect(SSL *s)
s->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
#ifndef OPENSSL_NO_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;
@ -227,6 +239,42 @@ int dtls1_connect(SSL *s)
s->hit = 0;
break;
#ifndef OPENSSL_NO_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:
@ -249,9 +297,17 @@ int dtls1_connect(SSL *s)
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);
#ifndef OPENSSL_NO_SCTP
/* Disable buffering for SCTP */
if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
#endif
/* turn on buffering for the next lot of output */
if (s->bbio != s->wbio)
s->wbio=BIO_push(s->bbio,s->wbio);
#ifndef OPENSSL_NO_SCTP
}
#endif
break;
@ -263,7 +319,24 @@ int dtls1_connect(SSL *s)
{
dtls1_stop_timer(s);
if (s->hit)
{
#ifndef OPENSSL_NO_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_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), NULL, 0, 0);
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;
}
@ -356,11 +429,18 @@ int dtls1_connect(SSL *s)
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;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
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:
@ -379,6 +459,22 @@ int dtls1_connect(SSL *s)
dtls1_start_timer(s);
ret=dtls1_send_client_key_exchange(s);
if (ret <= 0) goto end;
#ifndef OPENSSL_NO_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_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), NULL, 0, 0);
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
@ -389,7 +485,15 @@ int dtls1_connect(SSL *s)
}
else
{
s->state=SSL3_ST_CW_CHANGE_A;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
}
@ -401,7 +505,15 @@ int dtls1_connect(SSL *s)
dtls1_start_timer(s);
ret=dtls1_send_client_verify(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_CHANGE_A;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
@ -413,6 +525,14 @@ int dtls1_connect(SSL *s)
ret=dtls1_send_change_cipher_spec(s,
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
#ifndef OPENSSL_NO_SCTP
/* Change to new shared key of SCTP-Auth,
* will be ignored if no SCTP used.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
#endif
s->state=SSL3_ST_CW_FINISHED_A;
s->init_num=0;
@ -458,9 +578,23 @@ int dtls1_connect(SSL *s)
if (s->hit)
{
s->s3->tmp.next_state=SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
}
@ -509,6 +643,16 @@ int dtls1_connect(SSL *s)
s->state=SSL3_ST_CW_CHANGE_A;
else
s->state=SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
state == SSL_ST_RENEGOTIATE)
{
s->d1->next_state=s->state;
s->state=DTLS1_SCTP_ST_CW_WRITE_SOCK;
}
#endif
s->init_num=0;
break;
@ -516,6 +660,13 @@ int dtls1_connect(SSL *s)
s->rwstate=SSL_WRITING;
if (BIO_flush(s->wbio) <= 0)
{
/* If the write error was fatal, stop trying */
if (!BIO_should_retry(s->wbio))
{
s->rwstate=SSL_NOTHING;
s->state=s->s3->tmp.next_state;
}
ret= -1;
goto end;
}
@ -589,6 +740,15 @@ int dtls1_connect(SSL *s)
}
end:
s->in_handshake--;
#ifndef OPENSSL_NO_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)

View File

@ -292,6 +292,15 @@ const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
void dtls1_start_timer(SSL *s)
{
#ifndef OPENSSL_NO_SCTP
/* Disable timer for SCTP */
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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)
{

View File

@ -232,6 +232,14 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority)
item->data = rdata;
#ifndef OPENSSL_NO_SCTP
/* Store bio_dgram_sctp_rcvinfo struct */
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
(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 @@ again:
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 */
}
#ifndef OPENSSL_NO_SCTP
/* Only do replay check if no SCTP bio */
if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
{
#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 */
}
#ifndef OPENSSL_NO_SCTP
}
#endif
/* just read a 0 length packet */
if (rr->length == 0) goto again;
@ -737,7 +753,17 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
/* Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */
#ifndef OPENSSL_NO_SCTP
/* Continue handshake if it had to be interrupted to read
* app data with SCTP.
*/
if ((!s->in_handshake && SSL_in_init(s)) ||
(BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
(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);
@ -768,6 +794,15 @@ start:
item = pqueue_pop(s->d1->buffered_app_data.q);
if (item)
{
#ifndef OPENSSL_NO_SCTP
/* Restore bio_dgram_sctp_rcvinfo struct */
if (BIO_dgram_is_sctp(SSL_get_rbio(s)))
{
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);
@ -850,6 +885,31 @@ start:
rr->off=0;
}
}
#ifndef OPENSSL_NO_SCTP
/* We were about to renegotiate but had to read
* belated application data first, so retry.
*/
if (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
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 (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
s->d1->shutdown_received && !BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))
{
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return(0);
}
#endif
return(n);
}
@ -1022,6 +1082,21 @@ start:
s->s3->warn_alert = alert_descr;
if (alert_descr == SSL_AD_CLOSE_NOTIFY)
{
#ifndef OPENSSL_NO_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 (BIO_dgram_is_sctp(SSL_get_rbio(s)) &&
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);
}
@ -1128,6 +1203,15 @@ start:
if (s->version == DTLS1_BAD_VER)
s->d1->handshake_read_seq++;
#ifndef OPENSSL_NO_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;
}
@ -1264,7 +1348,16 @@ dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len)
{
int i;
if (SSL_in_init(s) && !s->in_handshake)
#ifndef OPENSSL_NO_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) ||
(BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
(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);

View File

@ -151,6 +151,10 @@ int dtls1_accept(SSL *s)
int ret= -1;
int new_state,state,skip=0;
int listen;
#ifndef OPENSSL_NO_SCTP
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
#endif
RAND_add(&Time,sizeof(Time),0);
ERR_clear_error();
@ -168,6 +172,13 @@ int dtls1_accept(SSL *s)
if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
s->d1->listen = listen;
#ifndef OPENSSL_NO_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)
{
@ -227,8 +238,12 @@ int dtls1_accept(SSL *s)
{
/* 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; }
#ifndef OPENSSL_NO_SCTP
if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
#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;
@ -313,6 +328,43 @@ int dtls1_accept(SSL *s)
ssl3_init_finished_mac(s);
break;
#ifndef OPENSSL_NO_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;
@ -320,18 +372,31 @@ int dtls1_accept(SSL *s)
ret=dtls1_send_server_hello(s);
if (ret <= 0) goto end;
#ifndef OPENSSL_NO_TLSEXT
if (s->hit)
{
#ifndef OPENSSL_NO_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_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), NULL, 0, 0);
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;
@ -441,6 +506,13 @@ int dtls1_accept(SSL *s)
skip=1;
s->s3->tmp.cert_request=0;
s->state=SSL3_ST_SW_SRVR_DONE_A;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
}
#endif
}
else
{
@ -450,9 +522,23 @@ int dtls1_accept(SSL *s)
if (ret <= 0) goto end;
#ifndef NETSCAPE_HANG_BUG
s->state=SSL3_ST_SW_SRVR_DONE_A;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
}
@ -472,6 +558,13 @@ int dtls1_accept(SSL *s)
s->rwstate=SSL_WRITING;
if (BIO_flush(s->wbio) <= 0)
{
/* If the write error was fatal, stop trying */
if (!BIO_should_retry(s->wbio))
{
s->rwstate=SSL_NOTHING;
s->state=s->s3->tmp.next_state;
}
ret= -1;
goto end;
}
@ -504,6 +597,21 @@ int dtls1_accept(SSL *s)
ret=ssl3_get_client_key_exchange(s);
if (ret <= 0) goto end;
dtls1_stop_timer(s);
#ifndef OPENSSL_NO_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_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
sizeof(labelbuffer), NULL, 0, 0);
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;
@ -541,8 +649,13 @@ int dtls1_accept(SSL *s)
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
dtls1_stop_timer(s);
s->state=SSL3_ST_SR_FINISHED_A;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
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;
@ -594,6 +707,14 @@ int dtls1_accept(SSL *s)
SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);
if (ret <= 0) goto end;
#ifndef OPENSSL_NO_SCTP
/* Change to new shared key of SCTP-Auth,
* will be ignored if no SCTP used.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
#endif
s->state=SSL3_ST_SW_FINISHED_A;
s->init_num=0;
@ -618,7 +739,16 @@ int dtls1_accept(SSL *s)
if (s->hit)
s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
else
{
s->s3->tmp.next_state=SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
{
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;
@ -690,6 +820,14 @@ end:
/* BIO_flush(s->wbio); */
s->in_handshake--;
#ifndef OPENSSL_NO_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);

View File

@ -111,6 +111,9 @@ extern "C" {
#ifndef OPENSSL_NO_SSL_INTERN
#ifndef OPENSSL_NO_SCTP
#define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
#endif
typedef struct dtls1_bitmap_st
{
@ -249,6 +252,13 @@ typedef struct dtls1_state_st
unsigned int retransmitting;
unsigned int change_cipher_spec_ok;
#ifndef OPENSSL_NO_SCTP
/* used when SSL_ST_XX_FLUSH is entered */
int next_state;
int shutdown_received;
#endif
} DTLS1_STATE;
typedef struct dtls1_record_data_st
@ -257,6 +267,9 @@ typedef struct dtls1_record_data_st
unsigned int packet_length;
SSL3_BUFFER rbuf;
SSL3_RECORD rrec;
#ifndef OPENSSL_NO_SCTP
struct bio_dgram_sctp_rcvinfo recordinfo;
#endif
} DTLS1_RECORD_DATA;
#endif

View File

@ -533,6 +533,10 @@ typedef struct ssl3_state_st
/*client */
/* extra state */
#define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT)
#ifndef OPENSSL_NO_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)
@ -579,6 +583,10 @@ typedef struct ssl3_state_st
/* server */
/* extra state */
#define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT)
#ifndef OPENSSL_NO_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)

View File

@ -772,7 +772,7 @@ const SSL_METHOD *func_name(void) \
ssl3_read, \
ssl3_peek, \
ssl3_write, \
ssl3_shutdown, \
dtls1_shutdown, \
ssl3_renegotiate, \
ssl3_renegotiate_check, \
dtls1_get_message, \
@ -1039,6 +1039,7 @@ int dtls1_connect(SSL *s);
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);