PR: 2535
Submitted by: Robin Seggelmann <seggelmann@fh-muenster.de> Reviewed by: steve Add SCTP support for DTLS (RFC 6083).
This commit is contained in:
parent
60553cc209
commit
e065e6cda2
11 changed files with 1524 additions and 33 deletions
13
Configure
13
Configure
|
@ -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, ...)
|
||||
|
@ -714,6 +715,7 @@ my %disabled = ( # "what" => "comment" [or special keyword "experimental
|
|||
"md2" => "default",
|
||||
"rc5" => "default",
|
||||
"rfc3779" => "default",
|
||||
"sctp" => "default",
|
||||
"shared" => "default",
|
||||
"store" => "experimental",
|
||||
"zlib" => "default",
|
||||
|
@ -781,6 +783,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/;
|
||||
|
@ -1387,6 +1390,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/);
|
||||
|
||||
#
|
||||
|
|
|
@ -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);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
|
166
ssl/d1_clnt.c
166
ssl/d1_clnt.c
|
@ -150,7 +150,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();
|
||||
|
@ -164,6 +168,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;
|
||||
|
@ -226,6 +238,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:
|
||||
|
||||
|
@ -248,9 +296,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;
|
||||
|
||||
|
@ -262,7 +318,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;
|
||||
}
|
||||
|
@ -355,11 +428,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:
|
||||
|
@ -378,6 +458,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
|
||||
|
@ -388,6 +484,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;
|
||||
}
|
||||
|
@ -400,6 +504,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;
|
||||
|
@ -412,6 +524,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;
|
||||
|
||||
|
@ -457,9 +577,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;
|
||||
}
|
||||
|
@ -508,6 +642,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;
|
||||
|
||||
|
@ -515,6 +659,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;
|
||||
}
|
||||
|
@ -588,6 +739,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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
93
ssl/d1_pkt.c
93
ssl/d1_pkt.c
|
@ -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,6 +646,11 @@ again:
|
|||
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,
|
||||
|
@ -652,6 +665,9 @@ again:
|
|||
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;
|
||||
|
||||
#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);
|
||||
|
|
146
ssl/d1_srvr.c
146
ssl/d1_srvr.c
|
@ -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,7 +238,11 @@ 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 :-)
|
||||
*/
|
||||
#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);
|
||||
|
@ -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;
|
||||
#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,7 +649,12 @@ int dtls1_accept(SSL *s)
|
|||
ret=ssl3_get_cert_verify(s);
|
||||
if (ret <= 0) goto end;
|
||||
dtls1_stop_timer(s);
|
||||
|
||||
#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);
|
||||
|
|
13
ssl/dtls1.h
13
ssl/dtls1.h
|
@ -107,6 +107,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
|
||||
{
|
||||
|
@ -245,6 +248,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
|
||||
|
@ -253,6 +263,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
|
||||
|
|
|
@ -532,6 +532,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)
|
||||
|
@ -576,6 +580,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)
|
||||
|
|
|
@ -774,7 +774,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, \
|
||||
|
@ -1041,6 +1041,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);
|
||||
|
|
Loading…
Reference in a new issue