Commit 7e159e01 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

PR: 2535

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

Add SCTP support for DTLS (RFC 6083).
parent b9e14888
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -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/);

#
+63 −1
Original line number Diff line number Diff line
@@ -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 */

@@ -163,6 +170,21 @@ extern "C" {
#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT   45 /* Next DTLS handshake timeout to
                                              * 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
#define BIO_FP_WRITE		0x04
@@ -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);
+975 −0

File changed.

Preview size limit exceeded, changes collapsed.

+21 −0
Original line number Diff line number Diff line
@@ -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;
	}
+168 −8
Original line number Diff line number Diff line
@@ -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;

#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,6 +485,14 @@ int dtls1_connect(SSL *s)
				}
			else
				{
#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,6 +505,14 @@ int dtls1_connect(SSL *s)
			dtls1_start_timer(s);
			ret=dtls1_send_client_verify(s);
			if (ret <= 0) goto end;
#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;
@@ -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)
Loading